]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #25905 - michaelwoerister:lldb-pp-strings, r=brson
authorbors <bors@rust-lang.org>
Tue, 2 Jun 2015 13:07:41 +0000 (13:07 +0000)
committerbors <bors@rust-lang.org>
Tue, 2 Jun 2015 13:07:41 +0000 (13:07 +0000)
GDB and LLDB pretty printers have some common functionality and also access some common information, such as the layout of standard library types. So far, this information has been duplicated in the two pretty printing python modules. This PR introduces a common module used by both debuggers.

This PR also implements proper rendering of `String` and `&str` values in LLDB.

29 files changed:
configure
mk/cfg/x86_64-pc-windows-msvc.mk
mk/crates.mk
mk/main.mk
mk/target.mk
mk/tests.mk
src/doc/index.md
src/doc/trpl/guessing-game.md
src/doc/trpl/installing-rust.md
src/doc/trpl/iterators.md
src/doc/trpl/mutability.md
src/doc/trpl/raw-pointers.md
src/etc/check-sanitycheck.py
src/liballoc/arc.rs
src/libcollections/str.rs
src/libcollections/string.rs
src/libcore/option.rs
src/librustc/diagnostics.rs
src/librustc_driver/lib.rs
src/librustdoc/html/static/main.css
src/libserialize/json.rs
src/libstd/collections/hash/table.rs
src/libstd/io/error.rs
src/libstd/io/mod.rs
src/libstd/num/f32.rs
src/libstd/num/f64.rs
src/libstd/sys/windows/stdio.rs
src/libstd/thread/local.rs
src/libstd/thread/scoped_tls.rs

index 20a5fa390f00b5ca1273c84d2f9d222e5331bd41..9be47beeb9174948388ce95c924be943bb227fd3 100755 (executable)
--- a/configure
+++ b/configure
@@ -565,7 +565,7 @@ opt rpath 0 "build rpaths into rustc itself"
 # This is used by the automation to produce single-target nightlies
 opt dist-host-only 0 "only install bins for the host architecture"
 opt inject-std-version 1 "inject the current compiler version of libstd into programs"
-opt llvm-version-check 1 "don't check if the LLVM version is supported, build anyway"
+opt llvm-version-check 1 "check if the LLVM version is supported, build anyway"
 
 # Optimization and debugging options. These may be overridden by the release channel, etc.
 opt_nosave optimize 1 "build optimized rust code"
@@ -593,6 +593,7 @@ valopt musl-root "/usr/local" "MUSL root installation directory"
 opt_nosave manage-submodules 1 "let the build manage the git submodules"
 opt_nosave clang 0 "prefer clang to gcc for building the runtime"
 opt_nosave jemalloc 1 "build liballoc with jemalloc"
+opt elf-tls 1 "elf thread local storage on platforms where supported"
 
 valopt_nosave prefix "/usr/local" "set installation prefix"
 valopt_nosave local-rust-root "/usr/local" "set prefix for local rust binary"
index bd1088b7cd13348ef691d2994b690acae8ca991a..1e1906a298084dce9f7efc0690efb37ace352903 100644 (file)
@@ -80,3 +80,8 @@ CUSTOM_DEPS_rustc_llvm_T_x86_64-pc-windows-msvc += \
 x86_64-pc-windows-msvc/rt/rustc_llvm.def: $(S)src/etc/mklldef.py \
                        $(S)src/librustc_llvm/lib.rs
        $(CFG_PYTHON) $^ $@ rustc_llvm-$(CFG_FILENAME_EXTRA)
+
+# All windows nightiles are currently a GNU triple, so this MSVC triple is not
+# bootstrapping from itself. This is relevant during stage0, and other parts of
+# the build system take this into account.
+BOOTSTRAP_FROM_x86_64-pc-windows-msvc := x86_64-pc-windows-gnu
index 62dc1019066f0b446cd0f88b83a15f9d30332f58..93be1e6ba6326a96989bed6ae81d5b8a9b83b132 100644 (file)
@@ -150,3 +150,7 @@ TOOL_INPUTS_$(1) := $$(call rwildcard,$$(dir $$(TOOL_SOURCE_$(1))),*.rs)
 endef
 
 $(foreach crate,$(TOOLS),$(eval $(call RUST_TOOL,$(crate))))
+
+ifdef CFG_DISABLE_ELF_TLS
+RUSTFLAGS_std := --cfg no_elf_tls
+endif
index de5adfd1297865314c63abf6ddc589c092b95f99..32d1fcf3968fc054dd67ac43c44434be19438249 100644 (file)
@@ -74,9 +74,6 @@ ifneq ($(wildcard $(subst $(SPACE),\$(SPACE),$(CFG_GIT_DIR))),)
 endif
 endif
 
-CFG_BUILD_DATE = $(shell date +%F)
-CFG_VERSION += (built $(CFG_BUILD_DATE))
-
 # Windows exe's need numeric versions - don't use anything but
 # numbers and dots here
 CFG_VERSION_WIN = $(CFG_RELEASE_NUM)
@@ -130,9 +127,7 @@ CFG_JEMALLOC_FLAGS += $(JEMALLOC_FLAGS)
 
 ifdef CFG_ENABLE_DEBUG_ASSERTIONS
   $(info cfg: enabling debug assertions (CFG_ENABLE_DEBUG_ASSERTIONS))
-  CFG_RUSTC_FLAGS += --cfg debug -C debug-assertions=on
-else
-  CFG_RUSTC_FLAGS += --cfg ndebug
+  CFG_RUSTC_FLAGS += -C debug-assertions=on
 endif
 
 ifdef CFG_ENABLE_DEBUGINFO
@@ -334,7 +329,6 @@ endif
 ifdef CFG_VER_HASH
 export CFG_VER_HASH
 endif
-export CFG_BUILD_DATE
 export CFG_VERSION
 export CFG_VERSION_WIN
 export CFG_RELEASE
index c8efb8e86d6d75fd13cbeab9079da6c2e4b2f562..3c274dc4fd5f2863a4b257ef117ef89d05ffa8b1 100644 (file)
@@ -181,3 +181,42 @@ $(foreach host,$(CFG_HOST), \
   $(foreach stage,$(STAGES), \
    $(foreach tool,$(TOOLS), \
     $(eval $(call TARGET_TOOL,$(stage),$(target),$(host),$(tool)))))))
+
+# We have some triples which are bootstrapped from other triples, and this means
+# that we need to fixup some of the native tools that a triple depends on.
+#
+# For example, MSVC requires the llvm-ar.exe executable to manage archives, but
+# it bootstraps from the GNU Windows triple. This means that the compiler will
+# add this directory to PATH when executing new processes:
+#
+#      $SYSROOT/rustlib/x86_64-pc-windows-gnu/bin
+#
+# Unfortunately, however, the GNU triple is not known about in stage0, so the
+# tools are actually located in:
+#
+#      $SYSROOT/rustlib/x86_64-pc-windows-msvc/bin
+#
+# To remedy this problem, the rules below copy all native tool dependencies into
+# the bootstrap triple's location in stage 0 so the bootstrap compiler can find
+# the right sets of tools. Later stages (1+) will have the right host triple for
+# the compiler, so there's no need to worry there.
+#
+# $(1) - stage
+# $(2) - triple that's being used as host/target
+# $(3) - triple snapshot is built for
+# $(4) - crate
+# $(5) - tool
+define MOVE_TOOLS_TO_SNAPSHOT_HOST_DIR
+ifneq (,$(3))
+$$(TLIB$(1)_T_$(2)_H_$(2))/stamp.$(4): $$(HLIB$(1)_H_$(2))/rustlib/$(3)/bin/$(5)
+
+$$(HLIB$(1)_H_$(2))/rustlib/$(3)/bin/$(5): $$(TBIN$(1)_T_$(2)_H_$(2))/$(5)
+       mkdir -p $$(@D)
+       cp $$< $$@
+endif
+endef
+
+$(foreach target,$(CFG_TARGET), \
+ $(foreach crate,$(CRATES), \
+  $(foreach tool,$(NATIVE_TOOL_DEPS_$(crate)_T_$(target)), \
+   $(eval $(call MOVE_TOOLS_TO_SNAPSHOT_HOST_DIR,0,$(target),$(BOOTSTRAP_FROM_$(target)),$(crate),$(tool))))))
index 2f1510ba87c286c600a96bb1c23676c63d9f9c30..185cc9b2f4c581d0ec4ba0b8a334f0250c1e943a 100644 (file)
@@ -172,23 +172,24 @@ check: check-sanitycheck cleantmptestlogs cleantestlibs all check-stage2 tidy
        $(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log
 
 # As above but don't bother running tidy.
-check-notidy: cleantmptestlogs cleantestlibs all check-stage2
+check-notidy: check-sanitycheck cleantmptestlogs cleantestlibs all check-stage2
        $(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log
 
 # A slightly smaller set of tests for smoke testing.
-check-lite: cleantestlibs cleantmptestlogs \
+check-lite: check-sanitycheck cleantestlibs cleantmptestlogs \
        $(foreach crate,$(TEST_TARGET_CRATES),check-stage2-$(crate)) \
        check-stage2-rpass check-stage2-rpass-valgrind \
        check-stage2-rfail check-stage2-cfail check-stage2-pfail check-stage2-rmake
        $(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log
 
 # Only check the 'reference' tests: rpass/cfail/rfail/rmake.
-check-ref: cleantestlibs cleantmptestlogs check-stage2-rpass check-stage2-rpass-valgrind \
-       check-stage2-rfail check-stage2-cfail check-stage2-pfail check-stage2-rmake
+check-ref: check-sanitycheck cleantestlibs cleantmptestlogs check-stage2-rpass \
+       check-stage2-rpass-valgrind check-stage2-rfail check-stage2-cfail check-stage2-pfail \
+       check-stage2-rmake
        $(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log
 
 # Only check the docs.
-check-docs: cleantestlibs cleantmptestlogs check-stage2-docs
+check-docs: check-sanitycheck cleantestlibs cleantmptestlogs check-stage2-docs
        $(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log
 
 # Some less critical tests that are not prone to breakage.
index c4725c26e46bd14fd634dafb8ac5aeb8c627d808..f561cf5d70f56633b3668897fdf68153e8e2fae4 100644 (file)
@@ -86,3 +86,14 @@ something if you know its name.
 
 If you encounter an error while compiling your code you may be able to look it
 up in the [Rust Compiler Error Index](error-index.html).
+
+# Community Translations
+
+Several projects have been started to translate the documentation into other
+languages:
+
+- [Russian](https://github.com/kgv/rust_book_ru)
+- [Korean](https://github.com/rust-kr/doc.rust-kr.org)
+- [Chinese](https://github.com/KaiserY/rust-book-chinese)
+- [Spanish](https://github.com/goyox86/elpr)
+
index 41d4146c9acdc3d191fb8dd22a5100f8330ebdbd..a599b8a855e9209bb63420737870f07bf45c0297 100644 (file)
@@ -38,7 +38,7 @@ Finally, Cargo generated a ‘Hello, world!’ for us. Check out `src/main.rs`:
 
 ```rust
 fn main() {
-    println!("Hello, world!")
+    println!("Hello, world!");
 }
 ```
 
@@ -362,7 +362,7 @@ everything that follows it is part of it, until the next section starts.
 Cargo uses the dependencies section to know what dependencies on external
 crates you have, and what versions you require. In this case, we’ve used version `0.3.0`.
 Cargo understands [Semantic Versioning][semver], which is a standard for writing version
-numbers. If we wanted to use the latest version we could use `*` or we could use a range 
+numbers. If we wanted to use the latest version we could use `*` or we could use a range
 of versions. [Cargo’s documentation][cargodoc] contains more details.
 
 [semver]: http://semver.org
index cc1ffdded1e14d423c548d4ae5945b26748a3f0c..73bbe77fe2685bc3d90b36f378179759c8d28a24 100644 (file)
@@ -2,8 +2,12 @@
 
 The first step to using Rust is to install it! There are a number of ways to
 install Rust, but the easiest is to use the `rustup` script. If you're on Linux
-or a Mac, all you need to do is this (note that you don't need to type in the
-`$`s, they just indicate the start of each command):
+or a Mac, all you need to do is this: 
+
+> Note: you don't need to type in the `$`s, they just indicate the start of
+> each command. You’ll see many tutorials and examples around the web that
+> follow this convention: `$` for commands run as your regular user, and
+> `#` for commands you should be running as an administrator.
 
 ```bash
 $ curl -sf -L https://static.rust-lang.org/rustup.sh | sh
index 80c0def285ab534163150f1e09b30ac2c9795588..249c1cc7e34f6171c9673204923226da5a70fd64 100644 (file)
@@ -213,7 +213,7 @@ As we've said before, an iterator is something that we can call the
 `.next()` method on repeatedly, and it gives us a sequence of things.
 Because you need to call the method, this means that iterators
 can be *lazy* and not generate all of the values upfront. This code,
-for example, does not actually generate the numbers `1-100`, instead
+for example, does not actually generate the numbers `1-99`, instead
 creating a value that merely represents the sequence:
 
 ```rust
@@ -321,7 +321,7 @@ You can chain all three things together: start with an iterator, adapt it
 a few times, and then consume the result. Check it out:
 
 ```rust
-(1..1000)
+(1..)
     .filter(|&x| x % 2 == 0)
     .filter(|&x| x % 3 == 0)
     .take(5)
index fe41def4d7cc3265150ed97aa987285b52fa24be..e30825badcc1451b3fc57fe5b5a74ca0e94bbeee 100644 (file)
@@ -89,7 +89,7 @@ philosophy, memory safety, and the mechanism by which Rust guarantees it, the
 > * exactly one mutable reference (`&mut T`)
 
 [ownership]: ownership.html
-[borrowing]: borrowing.html#The-Rules
+[borrowing]: references-and-borrowing.html#borrowing
 
 So, that’s the real definition of ‘immutability’: is this safe to have two
 pointers to? In `Arc<T>`’s case, yes: the mutation is entirely contained inside
index 4a37af3c227827f779157a1d2f44dcb54df03126..0f189adf40abf77b070c8b352e8fef7b80e859c8 100644 (file)
@@ -77,7 +77,7 @@ For more operations on raw pointers, see [their API documentation][rawapi].
 # FFI
 
 Raw pointers are useful for FFI: Rust’s `*const T` and `*mut T` are similar to
-C’s `const T*` and `T*`, respectfully. For more about this use, consult the
+C’s `const T*` and `T*`, respectively. For more about this use, consult the
 [FFI chapter][ffi].
 
 [ffi]: ffi.html
index fc8ed7b383ec5943f7852534e636e3e43d6ca6ad..0e103fbcffbad6a0fb1b2f34044b0887200519c8 100644 (file)
 # except according to those terms.
 
 import os
+import subprocess
 import sys
 import functools
 
 STATUS = 0
 
-
 def error_unless_permitted(env_var, message):
     global STATUS
     if not os.getenv(env_var):
         sys.stderr.write(message)
         STATUS = 1
 
-
 def only_on(platforms):
     def decorator(func):
         @functools.wraps(func)
@@ -33,8 +32,7 @@ def only_on(platforms):
         return inner
     return decorator
 
-
-@only_on(('linux', 'darwin', 'freebsd', 'openbsd'))
+@only_on(['linux', 'darwin', 'freebsd', 'openbsd'])
 def check_rlimit_core():
     import resource
     soft, hard = resource.getrlimit(resource.RLIMIT_CORE)
@@ -45,8 +43,14 @@ will segfault many rustc's, creating many potentially large core files.
 set ALLOW_NONZERO_RLIMIT_CORE to ignore this warning
 """ % (soft))
 
+@only_on(['win32'])
+def check_console_code_page():
+    if '65001' not in subprocess.check_output(['cmd', '/c', 'chcp']):
+        sys.stderr.write('Warning: the console output code page is not UTF-8, \
+some tests may fail. Use `cmd /c "chcp 65001"` to setup UTF-8 code page.\n')
 
 def main():
+    check_console_code_page()
     check_rlimit_core()
 
 if __name__ == '__main__':
index 97e85b114b06079dd07d0eeb6b751538673233be..593ecc72d50cd00379065dba912c00333742ef39 100644 (file)
@@ -250,6 +250,9 @@ pub fn strong_count<T: ?Sized>(this: &Arc<T>) -> usize { this.inner().strong.loa
 ///
 /// Returns `None` if the `Arc<T>` is not unique.
 ///
+/// This function is marked **unsafe** because it is racy if weak pointers
+/// are active.
+///
 /// # Examples
 ///
 /// ```
@@ -258,6 +261,7 @@ pub fn strong_count<T: ?Sized>(this: &Arc<T>) -> usize { this.inner().strong.loa
 /// # fn main() {
 /// use alloc::arc::{Arc, get_mut};
 ///
+/// # unsafe {
 /// let mut x = Arc::new(3);
 /// *get_mut(&mut x).unwrap() = 4;
 /// assert_eq!(*x, 4);
@@ -265,17 +269,19 @@ pub fn strong_count<T: ?Sized>(this: &Arc<T>) -> usize { this.inner().strong.loa
 /// let _y = x.clone();
 /// assert!(get_mut(&mut x).is_none());
 /// # }
+/// # }
 /// ```
 #[inline]
 #[unstable(feature = "alloc")]
-pub fn get_mut<T: ?Sized>(this: &mut Arc<T>) -> Option<&mut T> {
+pub unsafe fn get_mut<T: ?Sized>(this: &mut Arc<T>) -> Option<&mut T> {
+    // FIXME(#24880) potential race with upgraded weak pointers here
     if strong_count(this) == 1 && weak_count(this) == 0 {
         // This unsafety is ok because we're guaranteed that the pointer
         // returned is the *only* pointer that will ever be returned to T. Our
         // reference count is guaranteed to be 1 at this point, and we required
         // the Arc itself to be `mut`, so we're returning the only possible
         // reference to the inner data.
-        let inner = unsafe { &mut **this._ptr };
+        let inner = &mut **this._ptr;
         Some(&mut inner.data)
     } else {
         None
@@ -332,19 +338,26 @@ impl<T: Clone> Arc<T> {
     /// This is also referred to as a copy-on-write operation because the inner
     /// data is cloned if the reference count is greater than one.
     ///
+    /// This method is marked **unsafe** because it is racy if weak pointers
+    /// are active.
+    ///
     /// # Examples
     ///
     /// ```
     /// # #![feature(alloc)]
     /// use std::sync::Arc;
     ///
+    /// # unsafe {
     /// let mut five = Arc::new(5);
     ///
     /// let mut_five = five.make_unique();
+    /// # }
     /// ```
     #[inline]
     #[unstable(feature = "alloc")]
-    pub fn make_unique(&mut self) -> &mut T {
+    pub unsafe fn make_unique(&mut self) -> &mut T {
+        // FIXME(#24880) potential race with upgraded weak pointers here
+        //
         // Note that we hold a strong reference, which also counts as a weak
         // reference, so we only clone if there is an additional reference of
         // either kind.
@@ -354,7 +367,7 @@ pub fn make_unique(&mut self) -> &mut T {
         }
         // As with `get_mut()`, the unsafety is ok because our reference was
         // either unique to begin with, or became one upon cloning the contents.
-        let inner = unsafe { &mut **self._ptr };
+        let inner = &mut **self._ptr;
         &mut inner.data
     }
 }
@@ -744,39 +757,43 @@ fn manually_share_arc() {
 
     #[test]
     fn test_arc_get_mut() {
-        let mut x = Arc::new(3);
-        *get_mut(&mut x).unwrap() = 4;
-        assert_eq!(*x, 4);
-        let y = x.clone();
-        assert!(get_mut(&mut x).is_none());
-        drop(y);
-        assert!(get_mut(&mut x).is_some());
-        let _w = x.downgrade();
-        assert!(get_mut(&mut x).is_none());
+        unsafe {
+            let mut x = Arc::new(3);
+            *get_mut(&mut x).unwrap() = 4;
+            assert_eq!(*x, 4);
+            let y = x.clone();
+            assert!(get_mut(&mut x).is_none());
+            drop(y);
+            assert!(get_mut(&mut x).is_some());
+            let _w = x.downgrade();
+            assert!(get_mut(&mut x).is_none());
+        }
     }
 
     #[test]
     fn test_cowarc_clone_make_unique() {
-        let mut cow0 = Arc::new(75);
-        let mut cow1 = cow0.clone();
-        let mut cow2 = cow1.clone();
-
-        assert!(75 == *cow0.make_unique());
-        assert!(75 == *cow1.make_unique());
-        assert!(75 == *cow2.make_unique());
-
-        *cow0.make_unique() += 1;
-        *cow1.make_unique() += 2;
-        *cow2.make_unique() += 3;
-
-        assert!(76 == *cow0);
-        assert!(77 == *cow1);
-        assert!(78 == *cow2);
-
-        // none should point to the same backing memory
-        assert!(*cow0 != *cow1);
-        assert!(*cow0 != *cow2);
-        assert!(*cow1 != *cow2);
+        unsafe {
+            let mut cow0 = Arc::new(75);
+            let mut cow1 = cow0.clone();
+            let mut cow2 = cow1.clone();
+
+            assert!(75 == *cow0.make_unique());
+            assert!(75 == *cow1.make_unique());
+            assert!(75 == *cow2.make_unique());
+
+            *cow0.make_unique() += 1;
+            *cow1.make_unique() += 2;
+            *cow2.make_unique() += 3;
+
+            assert!(76 == *cow0);
+            assert!(77 == *cow1);
+            assert!(78 == *cow2);
+
+            // none should point to the same backing memory
+            assert!(*cow0 != *cow1);
+            assert!(*cow0 != *cow2);
+            assert!(*cow1 != *cow2);
+        }
     }
 
     #[test]
@@ -789,7 +806,9 @@ fn test_cowarc_clone_unique2() {
         assert!(75 == *cow1);
         assert!(75 == *cow2);
 
-        *cow0.make_unique() += 1;
+        unsafe {
+            *cow0.make_unique() += 1;
+        }
 
         assert!(76 == *cow0);
         assert!(75 == *cow1);
@@ -810,7 +829,9 @@ fn test_cowarc_clone_weak() {
         assert!(75 == *cow0);
         assert!(75 == *cow1_weak.upgrade().unwrap());
 
-        *cow0.make_unique() += 1;
+        unsafe {
+            *cow0.make_unique() += 1;
+        }
 
         assert!(76 == *cow0);
         assert!(cow1_weak.upgrade().is_none());
index d9a45872489a425428bb9ca7218b07fcd47794f6..ccfc6dc0f29e858df044b67e4efd82392d5a215d 100644 (file)
@@ -30,7 +30,7 @@
 //! You can get a non-`'static` `&str` by taking a slice of a `String`:
 //!
 //! ```
-//! let some_string = "Hello, world.".to_string();
+//! let some_string = "Hello, world.".to_string();
 //! let s = &some_string;
 //! ```
 //!
index 7563bb76b52f803b7b5321a68bf6cd07e36de1ab..c328a58f0770efcf7f97021857cdcd33f14c17df 100644 (file)
@@ -495,8 +495,7 @@ pub fn push(&mut self, ch: char) {
     ///
     /// ```
     /// let s = String::from("hello");
-    /// let b: &[_] = &[104, 101, 108, 108, 111];
-    /// assert_eq!(s.as_bytes(), b);
+    /// assert_eq!(s.as_bytes(), [104, 101, 108, 108, 111]);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
index 8da28094be3aed3c007bd1469f45949cd80a05c7..8d2d725251220d5ee55721256785e198e990aa71 100644 (file)
@@ -320,7 +320,7 @@ pub fn as_mut_slice<'r>(&'r mut self) -> &'r mut [T] {
     ///
     /// ```{.should_panic}
     /// let x: Option<&str> = None;
-    /// x.expect("the world is ending"); // panics with `world is ending`
+    /// x.expect("the world is ending"); // panics with `the world is ending`
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -409,9 +409,11 @@ pub fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
     /// Convert an `Option<String>` into an `Option<usize>`, consuming the original:
     ///
     /// ```
-    /// let num_as_str: Option<String> = Some("10".to_string());
-    /// // `Option::map` takes self *by value*, consuming `num_as_str`
-    /// let num_as_int: Option<usize> = num_as_str.map(|n| n.len());
+    /// let maybe_some_string = Some(String::from("Hello, World!"));
+    /// // `Option::map` takes self *by value*, consuming `maybe_some_string`
+    /// let maybe_some_len = maybe_some_string.map(|s| s.len());
+    ///
+    /// assert_eq!(maybe_some_len, Some(13));
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -422,7 +424,8 @@ pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> {
         }
     }
 
-    /// Applies a function to the contained value or returns a default.
+    /// Applies a function to the contained value (if any),
+    /// or returns a `default` (if not).
     ///
     /// # Examples
     ///
@@ -435,14 +438,15 @@ pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn map_or<U, F: FnOnce(T) -> U>(self, def: U, f: F) -> U {
+    pub fn map_or<U, F: FnOnce(T) -> U>(self, default: U, f: F) -> U {
         match self {
             Some(t) => f(t),
-            None => def
+            None => default,
         }
     }
 
-    /// Applies a function to the contained value or computes a default.
+    /// Applies a function to the contained value (if any),
+    /// or computes a `default` (if not).
     ///
     /// # Examples
     ///
@@ -457,10 +461,10 @@ pub fn map_or<U, F: FnOnce(T) -> U>(self, def: U, f: F) -> U {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn map_or_else<U, D: FnOnce() -> U, F: FnOnce(T) -> U>(self, def: D, f: F) -> U {
+    pub fn map_or_else<U, D: FnOnce() -> U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U {
         match self {
             Some(t) => f(t),
-            None => def()
+            None => default()
         }
     }
 
index a3577981c1e4b6105b67d2f19e90984e8b29ebea..5e79e5a5a4ed2edf6b1a7623d4ab8bc5b9faf75a 100644 (file)
@@ -176,6 +176,38 @@ struct X { x: (), }
 the heap at runtime, and therefore cannot be done at compile time.
 "##,
 
+E0011: r##"
+Initializers for constants and statics are evaluated at compile time.
+User-defined operators rely on user-defined functions, which cannot be evaluated
+at compile time.
+
+Bad example:
+
+```
+use std::ops::Index;
+
+struct Foo { a: u8 }
+
+impl Index<u8> for Foo {
+    type Output = u8;
+
+    fn index<'a>(&'a self, idx: u8) -> &'a u8 { &self.a }
+}
+
+const a: Foo = Foo { a: 0u8 };
+const b: u8 = a[0]; // Index trait is defined by the user, bad!
+```
+
+Only operators on builtin types are allowed.
+
+Example:
+
+```
+const a: &'static [i32] = &[1, 2, 3];
+const b: i32 = a[0]; // Good!
+```
+"##,
+
 E0013: r##"
 Static and const variables can refer to other const variables. But a const
 variable cannot refer to a static variable. For example, `Y` cannot refer to `X`
@@ -899,7 +931,6 @@ fn bar(&self) -> i32 { self.0 }
 
 
 register_diagnostics! {
-    E0011,
     E0014,
     E0016,
     E0017,
index d91a26ed4ee9b0b37ed36b1b4e4ab26a8fa6cd21..49879b472feb7e1838598a2ce977ca708d24ce35 100644 (file)
@@ -483,10 +483,6 @@ pub fn commit_date_str() -> Option<&'static str> {
     option_env!("CFG_VER_DATE")
 }
 
-pub fn build_date_str() -> Option<&'static str> {
-    option_env!("CFG_BUILD_DATE")
-}
-
 /// Prints version information and returns None on success or an error
 /// message on panic.
 pub fn version(binary: &str, matches: &getopts::Matches) {
@@ -498,7 +494,6 @@ fn unw(x: Option<&str>) -> &str { x.unwrap_or("unknown") }
         println!("binary: {}", binary);
         println!("commit-hash: {}", unw(commit_hash_str()));
         println!("commit-date: {}", unw(commit_date_str()));
-        println!("build-date: {}", unw(build_date_str()));
         println!("host: {}", config::host_triple());
         println!("release: {}", unw(release_str()));
     }
index 575322e63526d531b10611eb3cd6b1aeb0f93759..aaebdc34cd464729ca782eea957780be535fbbc6 100644 (file)
@@ -338,10 +338,10 @@ nav.sub {
     font-size: 1em;
     position: relative;
 }
-/* Shift "where ..." part of method definition down a line */
-.content .method .where { display: block; }
+/* Shift "where ..." part of method or fn definition down a line */
+.content .method .where, .content .fn .where { display: block; }
 /* Bit of whitespace to indent it */
-.content .method .where::before { content: '  '; }
+.content .method .where::before, .content .fn .where::before { content: '  '; }
 
 .content .methods > div { margin-left: 40px; }
 
index adc4f69334f17f0df7f722bdc1d6d6e01966ab7f..24cc7fe878af471ff13af8c73e9127175bce8402 100644 (file)
 //!         val: num.to_json(),
 //!     }).unwrap();
 //!     println!("data: {}", data);
-//!     // data: {"uid":1,"dsc":"test","val":"0.0001+12.539j"};
+//!     // data: {"uid":1,"dsc":"test","val":"0.0001+12.539i"};
 //! }
 //! ```
 //!
index 4841f36c7f74719d15e0a51fb20209f4399351f5..2616bc5278589ad4dc2b6fbcff5ef1dc48b59bf3 100644 (file)
@@ -528,6 +528,7 @@ fn test_rounding() {
 
 // Returns a tuple of (key_offset, val_offset),
 // from the start of a mallocated array.
+#[inline]
 fn calculate_offsets(hashes_size: usize,
                      keys_size: usize, keys_align: usize,
                      vals_align: usize)
index 85b957640fdab03f5b150d7938bed3dcd63e0305..c4e472f158edff8ad354b482f183753f3c33027c 100644 (file)
@@ -95,6 +95,13 @@ pub enum ErrorKind {
     /// A parameter was incorrect.
     #[stable(feature = "rust1", since = "1.0.0")]
     InvalidInput,
+    /// Data not valid for the operation were encountered.
+    ///
+    /// Unlike `InvalidInput`, this typically means that the operation
+    /// parameters were valid, however the error was caused by malformed
+    /// input data.
+    #[stable(feature = "io_invalid_data", since = "1.2.0")]
+    InvalidData,
     /// The I/O operation's timeout expired, causing it to be canceled.
     #[stable(feature = "rust1", since = "1.0.0")]
     TimedOut,
index c664def304e09e55c7847874184d589f86ea8a31..3d0dfbba0ab99ddfbb03f679452500418d163b4a 100644 (file)
@@ -80,7 +80,7 @@ fn drop(&mut self) {
         let ret = f(g.s);
         if str::from_utf8(&g.s[g.len..]).is_err() {
             ret.and_then(|_| {
-                Err(Error::new(ErrorKind::InvalidInput,
+                Err(Error::new(ErrorKind::InvalidData,
                                "stream did not contain valid UTF-8"))
             })
         } else {
index e31d97b3240385c0b08283ae5f2e67d197575131..c22f5d073de89c346ade8ce6013efc9e2b9f882f 100644 (file)
@@ -660,6 +660,8 @@ pub fn next_after(self, other: f32) -> f32 {
     ///
     /// assert_eq!(x.max(y), y);
     /// ```
+    ///
+    /// If one of the arguments is NaN, then the other argument is returned.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn max(self, other: f32) -> f32 {
@@ -674,6 +676,8 @@ pub fn max(self, other: f32) -> f32 {
     ///
     /// assert_eq!(x.min(y), x);
     /// ```
+    ///
+    /// If one of the arguments is NaN, then the other argument is returned.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn min(self, other: f32) -> f32 {
index e87855ffd4eed8526b541ad312e92f79eb10d4c1..cde0b567ade0fc935cc51a7d7235afbef999062c 100644 (file)
@@ -636,6 +636,8 @@ pub fn next_after(self, other: f64) -> f64 {
     ///
     /// assert_eq!(x.max(y), y);
     /// ```
+    ///
+    /// If one of the arguments is NaN, then the other argument is returned.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn max(self, other: f64) -> f64 {
@@ -650,6 +652,8 @@ pub fn max(self, other: f64) -> f64 {
     ///
     /// assert_eq!(x.min(y), x);
     /// ```
+    ///
+    /// If one of the arguments is NaN, then the other argument is returned.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn min(self, other: f64) -> f64 {
index 03547165f5d8700aa3f3939b8511db9cb237724e..e56722a189d7eb4bdb832bdeb83c70d152798b03 100644 (file)
@@ -170,5 +170,5 @@ pub fn handle(&self) -> &Handle {
 }
 
 fn invalid_encoding() -> io::Error {
-    io::Error::new(io::ErrorKind::InvalidInput, "text was not valid unicode")
+    io::Error::new(io::ErrorKind::InvalidData, "text was not valid unicode")
 }
index 0eafd4d5f12e952817ea91c94b48c762a7b3fd1d..cdd7dff010837e6e1ab57ac579f7df6ec5cbc22c 100644 (file)
@@ -99,37 +99,60 @@ pub struct LocalKey<T> {
 
 /// Declare a new thread local storage key of type `std::thread::LocalKey`.
 ///
-/// See [LocalKey documentation](thread/struct.LocalKey.html) for more information.
+/// See [LocalKey documentation](thread/struct.LocalKey.html) for more
+/// information.
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow_internal_unstable]
+#[cfg(not(no_elf_tls))]
 macro_rules! thread_local {
     (static $name:ident: $t:ty = $init:expr) => (
-        static $name: ::std::thread::LocalKey<$t> = {
-            #[cfg_attr(all(any(target_os = "macos", target_os = "linux"),
-                           not(target_arch = "aarch64")),
-                       thread_local)]
-            static __KEY: ::std::thread::__LocalKeyInner<$t> =
-                ::std::thread::__LocalKeyInner::new();
-            fn __init() -> $t { $init }
-            fn __getit() -> &'static ::std::thread::__LocalKeyInner<$t> { &__KEY }
-            ::std::thread::LocalKey::new(__getit, __init)
-        };
+        static $name: ::std::thread::LocalKey<$t> =
+            __thread_local_inner!($t, $init,
+                #[cfg_attr(all(any(target_os = "macos", target_os = "linux"),
+                               not(target_arch = "aarch64")),
+                           thread_local)]);
     );
     (pub static $name:ident: $t:ty = $init:expr) => (
-        pub static $name: ::std::thread::LocalKey<$t> = {
-            #[cfg_attr(all(any(target_os = "macos", target_os = "linux"),
-                           not(target_arch = "aarch64")),
-                       thread_local)]
-            static __KEY: ::std::thread::__LocalKeyInner<$t> =
-                ::std::thread::__LocalKeyInner::new();
-            fn __init() -> $t { $init }
-            fn __getit() -> &'static ::std::thread::__LocalKeyInner<$t> { &__KEY }
-            ::std::thread::LocalKey::new(__getit, __init)
-        };
+        pub static $name: ::std::thread::LocalKey<$t> =
+            __thread_local_inner!($t, $init,
+                #[cfg_attr(all(any(target_os = "macos", target_os = "linux"),
+                               not(target_arch = "aarch64")),
+                           thread_local)]);
     );
 }
 
+#[macro_export]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[allow_internal_unstable]
+#[cfg(no_elf_tls)]
+macro_rules! thread_local {
+    (static $name:ident: $t:ty = $init:expr) => (
+        static $name: ::std::thread::LocalKey<$t> =
+            __thread_local_inner!($t, $init, #[]);
+    );
+    (pub static $name:ident: $t:ty = $init:expr) => (
+        pub static $name: ::std::thread::LocalKey<$t> =
+            __thread_local_inner!($t, $init, #[]);
+    );
+}
+
+#[doc(hidden)]
+#[unstable(feature = "thread_local_internals",
+           reason = "should not be necessary")]
+#[macro_export]
+#[allow_internal_unstable]
+macro_rules! __thread_local_inner {
+    ($t:ty, $init:expr, #[$($attr:meta),*]) => {{
+        $(#[$attr])*
+        static __KEY: ::std::thread::__LocalKeyInner<$t> =
+            ::std::thread::__LocalKeyInner::new();
+        fn __init() -> $t { $init }
+        fn __getit() -> &'static ::std::thread::__LocalKeyInner<$t> { &__KEY }
+        ::std::thread::LocalKey::new(__getit, __init)
+    }}
+}
+
 /// Indicator of the state of a thread local storage key.
 #[unstable(feature = "std_misc",
            reason = "state querying was recently added")]
@@ -163,7 +186,10 @@ pub enum LocalKeyState {
 
 impl<T: 'static> LocalKey<T> {
     #[doc(hidden)]
-    pub const fn new(inner: fn() -> &'static __KeyInner<T>, init: fn() -> T) -> LocalKey<T> {
+    #[unstable(feature = "thread_local_internals",
+               reason = "recently added to create a key")]
+    pub const fn new(inner: fn() -> &'static __KeyInner<T>,
+                     init: fn() -> T) -> LocalKey<T> {
         LocalKey {
             inner: inner,
             init: init
@@ -240,7 +266,9 @@ pub fn state(&'static self) -> LocalKeyState {
     }
 }
 
-#[cfg(all(any(target_os = "macos", target_os = "linux"), not(target_arch = "aarch64")))]
+#[cfg(all(any(target_os = "macos", target_os = "linux"),
+          not(target_arch = "aarch64"),
+          not(no_elf_tls)))]
 #[doc(hidden)]
 mod imp {
     use prelude::v1::*;
@@ -371,7 +399,9 @@ fn _tlv_atexit(dtor: unsafe extern fn(*mut u8),
     }
 }
 
-#[cfg(any(not(any(target_os = "macos", target_os = "linux")), target_arch = "aarch64"))]
+#[cfg(any(not(any(target_os = "macos", target_os = "linux")),
+          target_arch = "aarch64",
+          no_elf_tls))]
 #[doc(hidden)]
 mod imp {
     use prelude::v1::*;
index dda1db9aecea4a80b3a5fa484311d229194a78de..f0a4c318d91272de5655ea84ea993cb31aa1ec20 100644 (file)
@@ -60,9 +60,11 @@ pub struct ScopedKey<T> { inner: imp::KeyInner<T> }
 /// This macro declares a `static` item on which methods are used to get and
 /// set the value stored within.
 ///
-/// See [ScopedKey documentation](thread/struct.ScopedKey.html) for more information.
+/// See [ScopedKey documentation](thread/struct.ScopedKey.html) for more
+/// information.
 #[macro_export]
 #[allow_internal_unstable]
+#[cfg(not(no_elf_tls))]
 macro_rules! scoped_thread_local {
     (static $name:ident: $t:ty) => (
         #[cfg_attr(not(any(windows,
@@ -86,6 +88,20 @@ macro_rules! scoped_thread_local {
     );
 }
 
+#[macro_export]
+#[allow_internal_unstable]
+#[cfg(no_elf_tls)]
+macro_rules! scoped_thread_local {
+    (static $name:ident: $t:ty) => (
+        static $name: ::std::thread::ScopedKey<$t> =
+            ::std::thread::ScopedKey::new();
+    );
+    (pub static $name:ident: $t:ty) => (
+        pub static $name: ::std::thread::ScopedKey<$t> =
+            ::std::thread::ScopedKey::new();
+    );
+}
+
 #[unstable(feature = "scoped_tls",
            reason = "scoped TLS has yet to have wide enough use to fully consider \
                      stabilizing its interface")]
@@ -187,7 +203,8 @@ pub fn is_set(&'static self) -> bool {
               target_os = "android",
               target_os = "ios",
               target_os = "openbsd",
-              target_arch = "aarch64")))]
+              target_arch = "aarch64",
+              no_elf_tls)))]
 mod imp {
     use std::cell::Cell;
 
@@ -208,7 +225,8 @@ pub unsafe fn get(&self) -> *mut T { self.inner.get() }
           target_os = "android",
           target_os = "ios",
           target_os = "openbsd",
-          target_arch = "aarch64"))]
+          target_arch = "aarch64",
+          no_elf_tls))]
 mod imp {
     use prelude::v1::*;