about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-02-25 00:40:09 +0000
committerbors <bors@rust-lang.org>2017-02-25 00:40:09 +0000
commit7932349e95ebd9de314e5c5fce155c33940a148b (patch)
tree2661207eb32ef57cfc5540ba31d5c3b8d5350881
parent08230775a026c955873ba557e624b7f665661f37 (diff)
parentf26bbb351051b17fd2d32f19fb4964415fe1d07b (diff)
Auto merge of #40072 - GuillaumeGomez:rollup, r=GuillaumeGomez
Rollup of 11 pull requests

- Successful merges: #39777, #39815, #39845, #39886, #39940, #40010, #40030, #40048, #40050, #40052, #40071
- Failed merges:
-rw-r--r--src/doc/book/src/procedural-macros.md75
-rw-r--r--src/doc/book/src/the-stack-and-the-heap.md2
-rw-r--r--src/doc/nomicon/src/exception-safety.md4
-rw-r--r--src/libcollections/fmt.rs25
-rw-r--r--src/libcollections/string.rs42
-rw-r--r--src/libcollections/vec.rs2
-rw-r--r--src/libcore/slice.rs2
-rw-r--r--src/libcore/str/mod.rs14
-rw-r--r--src/librustc/ty/inhabitedness/mod.rs2
-rw-r--r--src/libstd/sync/barrier.rs76
-rw-r--r--src/libstd/sync/mutex.rs4
-rw-r--r--src/libstd/thread/mod.rs9
-rw-r--r--src/libtest/lib.rs6
13 files changed, 223 insertions, 40 deletions
diff --git a/src/doc/book/src/procedural-macros.md b/src/doc/book/src/procedural-macros.md
index 079324d56d1..4f5a6a7c033 100644
--- a/src/doc/book/src/procedural-macros.md
+++ b/src/doc/book/src/procedural-macros.md
@@ -170,7 +170,7 @@ a representation of our type (which can be either a `struct` or an `enum`).
 Check out the [docs](https://docs.rs/syn/0.10.5/syn/struct.MacroInput.html),
 there is some useful information there. We are able to get the name of the
 type using `ast.ident`. The `quote!` macro lets us write up the Rust code
-that we wish to return and convert it into `Tokens`. `quote!` let's us use some
+that we wish to return and convert it into `Tokens`. `quote!` lets us use some
 really cool templating mechanics; we simply write `#name` and `quote!` will
 replace it with the variable named `name`. You can even do some repetition
 similar to regular macros work. You should check out the
@@ -211,3 +211,76 @@ Hello, World! My name is Waffles
 ```
 
 We've done it!
+
+## Custom Attributes
+
+In some cases it might make sense to allow users some kind of configuration.
+For example, the user might want to overwrite the name that is printed in the `hello_world()` method.
+
+This can be achieved with custom attributes:
+
+```rust,ignore
+#[derive(HelloWorld)]
+#[HelloWorldName = "the best Pancakes"]
+struct Pancakes;
+
+fn main() {
+    Pancakes::hello_world();
+}
+```
+
+If we try to compile this though, the compiler will respond with an error:
+
+```bash
+error: The attribute `HelloWorldName` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+```
+
+The compiler needs to know that we're handling this attribute and to not respond with an error.
+This is done in the `hello-world-derive` crate by adding `attributes` to the `proc_macro_derive` attribute:
+
+```rust,ignore
+#[proc_macro_derive(HelloWorld, attributes(HelloWorldName))]
+pub fn hello_world(input: TokenStream) -> TokenStream 
+```
+
+Multiple attributes can be specified that way.
+
+## Raising Errors
+
+Let's assume that we do not want to accept enums as input to our custom derive method.
+
+This condition can be easily checked with the help of `syn`. 
+But how do we tell the user, that we do not accept enums?
+The idiomatic way to report errors in procedural macros is to panic:
+
+```rust,ignore
+fn impl_hello_world(ast: &syn::MacroInput) -> quote::Tokens {
+    let name = &ast.ident;
+    // Check if derive(HelloWorld) was specified for a struct
+    if let syn::Body::Struct(_) = ast.body {
+        // Yes, this is a struct
+        quote! {
+            impl HelloWorld for #name {
+                fn hello_world() {
+                    println!("Hello, World! My name is {}", stringify!(#name));
+                }
+            }
+        }
+    } else {
+        //Nope. This is an Enum. We cannot handle these!
+       panic!("#[derive(HelloWorld)] is only defined for structs, not for enums!");
+    }
+}
+```
+
+If a user now tries to derive `HelloWorld` from an enum they will be greeted with following, hopefully helpful, error:
+
+```bash
+error: custom derive attribute panicked
+  --> src/main.rs
+   |
+   | #[derive(HelloWorld)]
+   |          ^^^^^^^^^^
+   |
+   = help: message: #[derive(HelloWorld)] is only defined for structs, not for enums!
+```
diff --git a/src/doc/book/src/the-stack-and-the-heap.md b/src/doc/book/src/the-stack-and-the-heap.md
index b9b3b801eae..6866505df13 100644
--- a/src/doc/book/src/the-stack-and-the-heap.md
+++ b/src/doc/book/src/the-stack-and-the-heap.md
@@ -86,7 +86,7 @@ to a large number, representing how much RAM your computer has. For example, if
 you have a gigabyte of RAM, your addresses go from `0` to `1,073,741,823`. That
 number comes from 2<sup>30</sup>, the number of bytes in a gigabyte. [^gigabyte]
 
-[^gigabyte]: ‘Gigabyte’ can mean two things: 10^9, or 2^30. The SI standard resolved this by stating that ‘gigabyte’ is 10^9, and ‘gibibyte’ is 2^30. However, very few people use this terminology, and rely on context to differentiate. We follow in that tradition here.
+[^gigabyte]: ‘Gigabyte’ can mean two things: 10<sup>9</sup>, or 2<sup>30</sup>. The IEC standard resolved this by stating that ‘gigabyte’ is 10<sup>9</sup>, and ‘gibibyte’ is 2<sup>30</sup>. However, very few people use this terminology, and rely on context to differentiate. We follow in that tradition here.
 
 This memory is kind of like a giant array: addresses start at zero and go
 up to the final number. So here’s a diagram of our first stack frame:
diff --git a/src/doc/nomicon/src/exception-safety.md b/src/doc/nomicon/src/exception-safety.md
index 80e72cd5e36..a3cbc6abd69 100644
--- a/src/doc/nomicon/src/exception-safety.md
+++ b/src/doc/nomicon/src/exception-safety.md
@@ -93,7 +93,7 @@ uselessly. We would rather have the following:
 ```text
 bubble_up(heap, index):
     let elem = heap[index]
-    while index != 0 && element < heap[parent(index)]:
+    while index != 0 && elem < heap[parent(index)]:
         heap[index] = heap[parent(index)]
         index = parent(index)
     heap[index] = elem
@@ -137,7 +137,7 @@ If Rust had `try` and `finally` like in Java, we could do the following:
 bubble_up(heap, index):
     let elem = heap[index]
     try:
-        while index != 0 && element < heap[parent(index)]:
+        while index != 0 && elem < heap[parent(index)]:
             heap[index] = heap[parent(index)]
             index = parent(index)
     finally:
diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs
index bd74848a01d..079541235a2 100644
--- a/src/libcollections/fmt.rs
+++ b/src/libcollections/fmt.rs
@@ -62,7 +62,7 @@
 //!
 //! A format string is required to use all of its arguments, otherwise it is a
 //! compile-time error. You may refer to the same argument more than once in the
-//! format string, although it must always be referred to with the same type.
+//! format string.
 //!
 //! ## Named parameters
 //!
@@ -89,19 +89,8 @@
 //!
 //! ## Argument types
 //!
-//! Each argument's type is dictated by the format string. It is a requirement
-//! that every argument is only ever referred to by one type. For example, this
-//! is an invalid format string:
-//!
-//! ```text
-//! {0:x} {0:o}
-//! ```
-//!
-//! This is invalid because the first argument is both referred to as a
-//! hexadecimal as well as an
-//! octal.
-//!
-//! There are various parameters which do require a particular type, however.
+//! Each argument's type is dictated by the format string.
+//! There are various parameters which require a particular type, however.
 //! An example is the `{:.*}` syntax, which sets the number of decimal places
 //! in floating-point types:
 //!
@@ -113,13 +102,7 @@
 //!
 //! If this syntax is used, then the number of characters to print precedes the
 //! actual object being formatted, and the number of characters must have the
-//! type `usize`. Although a `usize` can be printed with `{}`, it is invalid to
-//! reference an argument as such. For example this is another invalid format
-//! string:
-//!
-//! ```text
-//! {:.*} {0}
-//! ```
+//! type `usize`.
 //!
 //! ## Formatting traits
 //!
diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs
index e92eb4ff7bd..10bc5ab88c9 100644
--- a/src/libcollections/string.rs
+++ b/src/libcollections/string.rs
@@ -1629,6 +1629,43 @@ impl hash::Hash for String {
     }
 }
 
+/// Implements the `+` operator for concatenating two strings.
+///
+/// This consumes the `String` on the left-hand side and re-uses its buffer (growing it if
+/// necessary). This is done to avoid allocating a new `String` and copying the entire contents on
+/// every operation, which would lead to `O(n^2)` running time when building an `n`-byte string by
+/// repeated concatenation.
+///
+/// The string on the right-hand side is only borrowed; its contents are copied into the returned
+/// `String`.
+///
+/// # Examples
+///
+/// Concatenating two `String`s takes the first by value and borrows the second:
+///
+/// ```
+/// let a = String::from("hello");
+/// let b = String::from(" world");
+/// let c = a + &b;
+/// // `a` is moved and can no longer be used here.
+/// ```
+///
+/// If you want to keep using the first `String`, you can clone it and append to the clone instead:
+///
+/// ```
+/// let a = String::from("hello");
+/// let b = String::from(" world");
+/// let c = a.clone() + &b;
+/// // `a` is still valid here.
+/// ```
+///
+/// Concatenating `&str` slices can be done by converting the first to a `String`:
+///
+/// ```
+/// let a = "hello";
+/// let b = " world";
+/// let c = a.to_string() + b;
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Add<&'a str> for String {
     type Output = String;
@@ -1640,6 +1677,11 @@ impl<'a> Add<&'a str> for String {
     }
 }
 
+/// Implements the `+=` operator for appending to a `String`.
+///
+/// This has the same behavior as the [`push_str()`] method.
+///
+/// [`push_str()`]: struct.String.html#method.push_str
 #[stable(feature = "stringaddassign", since = "1.12.0")]
 impl<'a> AddAssign<&'a str> for String {
     #[inline]
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs
index 9e3f117f9b2..bc7f562452d 100644
--- a/src/libcollections/vec.rs
+++ b/src/libcollections/vec.rs
@@ -1776,6 +1776,7 @@ array_impls! {
     30 31 32
 }
 
+/// Implements comparison of vectors, lexicographically.
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: PartialOrd> PartialOrd for Vec<T> {
     #[inline]
@@ -1787,6 +1788,7 @@ impl<T: PartialOrd> PartialOrd for Vec<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Eq> Eq for Vec<T> {}
 
+/// Implements ordering of vectors, lexicographically.
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Ord> Ord for Vec<T> {
     #[inline]
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs
index 3e0b8425573..0331c5d4ba4 100644
--- a/src/libcore/slice.rs
+++ b/src/libcore/slice.rs
@@ -2202,6 +2202,7 @@ impl<A, B> PartialEq<[B]> for [A] where A: PartialEq<B> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Eq> Eq for [T] {}
 
+/// Implements comparison of vectors lexicographically.
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Ord> Ord for [T] {
     fn cmp(&self, other: &[T]) -> Ordering {
@@ -2209,6 +2210,7 @@ impl<T: Ord> Ord for [T] {
     }
 }
 
+/// Implements comparison of vectors lexicographically.
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: PartialOrd> PartialOrd for [T] {
     fn partial_cmp(&self, other: &[T]) -> Option<Ordering> {
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 49a6b1b5fce..925cd84154a 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -1366,6 +1366,13 @@ mod traits {
     use ops;
     use str::eq_slice;
 
+    /// Implements ordering of strings.
+    ///
+    /// Strings are ordered  lexicographically by their byte values.  This orders Unicode code
+    /// points based on their positions in the code charts.  This is not necessarily the same as
+    /// "alphabetical" order, which varies by language and locale.  Sorting strings according to
+    /// culturally-accepted standards requires locale-specific data that is outside the scope of
+    /// the `str` type.
     #[stable(feature = "rust1", since = "1.0.0")]
     impl Ord for str {
         #[inline]
@@ -1387,6 +1394,13 @@ mod traits {
     #[stable(feature = "rust1", since = "1.0.0")]
     impl Eq for str {}
 
+    /// Implements comparison operations on strings.
+    ///
+    /// Strings are compared lexicographically by their byte values.  This compares Unicode code
+    /// points based on their positions in the code charts.  This is not necessarily the same as
+    /// "alphabetical" order, which varies by language and locale.  Comparing strings according to
+    /// culturally-accepted standards requires locale-specific data that is outside the scope of
+    /// the `str` type.
     #[stable(feature = "rust1", since = "1.0.0")]
     impl PartialOrd for str {
         #[inline]
diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs
index 24ca476e5ff..77c863a0123 100644
--- a/src/librustc/ty/inhabitedness/mod.rs
+++ b/src/librustc/ty/inhabitedness/mod.rs
@@ -187,7 +187,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
                         //      which contains a Foo<((T, T), (T, T))>
                         //      which contains a Foo<(((T, T), (T, T)), ((T, T), (T, T)))>
                         //      etc.
-                        let error = format!("reached recursion limit while checking
+                        let error = format!("reached recursion limit while checking \
                                              inhabitedness of `{}`", self);
                         tcx.sess.fatal(&error);
                     }
diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs
index fc4fd4ce92b..f15e7ff8916 100644
--- a/src/libstd/sync/barrier.rs
+++ b/src/libstd/sync/barrier.rs
@@ -14,6 +14,8 @@ use sync::{Mutex, Condvar};
 /// A barrier enables multiple threads to synchronize the beginning
 /// of some computation.
 ///
+/// # Examples
+///
 /// ```
 /// use std::sync::{Arc, Barrier};
 /// use std::thread;
@@ -50,8 +52,19 @@ struct BarrierState {
 
 /// A result returned from wait.
 ///
-/// Currently this opaque structure only has one method, `.is_leader()`. Only
+/// Currently this opaque structure only has one method, [`.is_leader()`]. Only
 /// one thread will receive a result that will return `true` from this function.
+///
+/// [`.is_leader()`]: #method.is_leader
+///
+/// # Examples
+///
+/// ```
+/// use std::sync::Barrier;
+///
+/// let barrier = Barrier::new(1);
+/// let barrier_wait_result = barrier.wait();
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct BarrierWaitResult(bool);
 
@@ -65,8 +78,18 @@ impl fmt::Debug for Barrier {
 impl Barrier {
     /// Creates a new barrier that can block a given number of threads.
     ///
-    /// A barrier will block `n`-1 threads which call `wait` and then wake up
-    /// all threads at once when the `n`th thread calls `wait`.
+    /// A barrier will block `n`-1 threads which call [`wait`] and then wake up
+    /// all threads at once when the `n`th thread calls [`wait`].
+    ///
+    /// [`wait`]: #method.wait
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::sync::Barrier;
+    ///
+    /// let barrier = Barrier::new(10);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(n: usize) -> Barrier {
         Barrier {
@@ -84,10 +107,37 @@ impl Barrier {
     /// Barriers are re-usable after all threads have rendezvoused once, and can
     /// be used continuously.
     ///
-    /// A single (arbitrary) thread will receive a `BarrierWaitResult` that
-    /// returns `true` from `is_leader` when returning from this function, and
+    /// A single (arbitrary) thread will receive a [`BarrierWaitResult`] that
+    /// returns `true` from [`is_leader`] when returning from this function, and
     /// all other threads will receive a result that will return `false` from
-    /// `is_leader`
+    /// [`is_leader`].
+    ///
+    /// [`BarrierWaitResult`]: struct.BarrierWaitResult.html
+    /// [`is_leader`]: struct.BarrierWaitResult.html#method.is_leader
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::sync::{Arc, Barrier};
+    /// use std::thread;
+    ///
+    /// let mut handles = Vec::with_capacity(10);
+    /// let barrier = Arc::new(Barrier::new(10));
+    /// for _ in 0..10 {
+    ///     let c = barrier.clone();
+    ///     // The same messages will be printed together.
+    ///     // You will NOT see any interleaving.
+    ///     handles.push(thread::spawn(move|| {
+    ///         println!("before wait");
+    ///         c.wait();
+    ///         println!("after wait");
+    ///     }));
+    /// }
+    /// // Wait for other threads to finish.
+    /// for handle in handles {
+    ///     handle.join().unwrap();
+    /// }
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn wait(&self) -> BarrierWaitResult {
         let mut lock = self.lock.lock().unwrap();
@@ -120,10 +170,22 @@ impl fmt::Debug for BarrierWaitResult {
 }
 
 impl BarrierWaitResult {
-    /// Returns whether this thread from `wait` is the "leader thread".
+    /// Returns whether this thread from [`wait`] is the "leader thread".
     ///
     /// Only one thread will have `true` returned from their result, all other
     /// threads will have `false` returned.
+    ///
+    /// [`wait`]: struct.Barrier.html#method.wait
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::sync::Barrier;
+    ///
+    /// let barrier = Barrier::new(1);
+    /// let barrier_wait_result = barrier.wait();
+    /// println!("{:?}", barrier_wait_result.is_leader());
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_leader(&self) -> bool { self.0 }
 }
diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs
index 0d6ad5e38e9..97b84d59218 100644
--- a/src/libstd/sync/mutex.rs
+++ b/src/libstd/sync/mutex.rs
@@ -133,11 +133,13 @@ unsafe impl<T: ?Sized + Send> Sync for Mutex<T> { }
 /// dropped (falls out of scope), the lock will be unlocked.
 ///
 /// The data protected by the mutex can be access through this guard via its
-/// `Deref` and `DerefMut` implementations.
+/// [`Deref`] and [`DerefMut`] implementations.
 ///
 /// This structure is created by the [`lock()`] and [`try_lock()`] methods on
 /// [`Mutex`].
 ///
+/// [`Deref`]: ../../std/ops/trait.Deref.html
+/// [`DerefMut`]: ../../std/ops/trait.DerefMut.html
 /// [`lock()`]: struct.Mutex.html#method.lock
 /// [`try_lock()`]: struct.Mutex.html#method.try_lock
 /// [`Mutex`]: struct.Mutex.html
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index 93e320c4522..2bc066d3fea 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -235,7 +235,7 @@ pub use self::local::{LocalKey, LocalKeyState};
 pub struct Builder {
     // A name for the thread-to-be, for identification in panic messages
     name: Option<String>,
-    // The size of the stack for the spawned thread
+    // The size of the stack for the spawned thread in bytes
     stack_size: Option<usize>,
 }
 
@@ -289,14 +289,17 @@ impl Builder {
         self
     }
 
-    /// Sets the size of the stack for the new thread.
+    /// Sets the size of the stack (in bytes) for the new thread.
+    ///
+    /// The actual stack size may be greater than this value if
+    /// the platform specifies minimal stack size.
     ///
     /// # Examples
     ///
     /// ```
     /// use std::thread;
     ///
-    /// let builder = thread::Builder::new().stack_size(10);
+    /// let builder = thread::Builder::new().stack_size(32 * 1024);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn stack_size(mut self, size: usize) -> Builder {
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index 112bf61cf97..5fdb0aa0641 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -106,7 +106,7 @@ impl fmt::Display for TestName {
 }
 
 #[derive(Clone, Copy, PartialEq, Eq)]
-enum NamePadding {
+pub enum NamePadding {
     PadNone,
     PadOnRight,
 }
@@ -950,7 +950,7 @@ fn stdout_isatty() -> bool {
 }
 
 #[derive(Clone)]
-enum TestEvent {
+pub enum TestEvent {
     TeFiltered(Vec<TestDesc>),
     TeWait(TestDesc, NamePadding),
     TeResult(TestDesc, TestResult, Vec<u8>),
@@ -960,7 +960,7 @@ enum TestEvent {
 pub type MonitorMsg = (TestDesc, TestResult, Vec<u8>);
 
 
-fn run_tests<F>(opts: &TestOpts, tests: Vec<TestDescAndFn>, mut callback: F) -> io::Result<()>
+pub fn run_tests<F>(opts: &TestOpts, tests: Vec<TestDescAndFn>, mut callback: F) -> io::Result<()>
     where F: FnMut(TestEvent) -> io::Result<()>
 {
     use std::collections::HashMap;