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:
This commit is contained in:
bors 2017-02-25 00:40:09 +00:00
commit 7932349e95
13 changed files with 223 additions and 40 deletions

View File

@ -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!
```

View File

@ -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 heres a diagram of our first stack frame:

View File

@ -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:

View File

@ -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
//!

View File

@ -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]

View File

@ -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]

View File

@ -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> {

View File

@ -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]

View File

@ -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);
}

View File

@ -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 }
}

View File

@ -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

View File

@ -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 {

View File

@ -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;