diff options
| author | bors <bors@rust-lang.org> | 2017-02-25 00:40:09 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-02-25 00:40:09 +0000 |
| commit | 7932349e95ebd9de314e5c5fce155c33940a148b (patch) | |
| tree | 2661207eb32ef57cfc5540ba31d5c3b8d5350881 | |
| parent | 08230775a026c955873ba557e624b7f665661f37 (diff) | |
| parent | f26bbb351051b17fd2d32f19fb4964415fe1d07b (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.md | 75 | ||||
| -rw-r--r-- | src/doc/book/src/the-stack-and-the-heap.md | 2 | ||||
| -rw-r--r-- | src/doc/nomicon/src/exception-safety.md | 4 | ||||
| -rw-r--r-- | src/libcollections/fmt.rs | 25 | ||||
| -rw-r--r-- | src/libcollections/string.rs | 42 | ||||
| -rw-r--r-- | src/libcollections/vec.rs | 2 | ||||
| -rw-r--r-- | src/libcore/slice.rs | 2 | ||||
| -rw-r--r-- | src/libcore/str/mod.rs | 14 | ||||
| -rw-r--r-- | src/librustc/ty/inhabitedness/mod.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sync/barrier.rs | 76 | ||||
| -rw-r--r-- | src/libstd/sync/mutex.rs | 4 | ||||
| -rw-r--r-- | src/libstd/thread/mod.rs | 9 | ||||
| -rw-r--r-- | src/libtest/lib.rs | 6 |
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; |
