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:
commit
7932349e95
@ -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!
|
||||
```
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
//!
|
||||
|
@ -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]
|
||||
|
@ -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]
|
||||
|
@ -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> {
|
||||
|
@ -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]
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 }
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user