Auto merge of #25384 - steveklabnik:rollup, r=steveklabnik
- Successful merges: #25308, #25360, #25363, #25365, #25371, #25372, #25376, #25379, #25382 - Failed merges:
This commit is contained in:
commit
5a341ecfc9
10 changed files with 252 additions and 31 deletions
|
@ -1346,6 +1346,8 @@ vtable when the trait is used as a [trait object](#trait-objects).
|
|||
Traits are implemented for specific types through separate
|
||||
[implementations](#implementations).
|
||||
|
||||
Consider the following trait:
|
||||
|
||||
```
|
||||
# type Surface = i32;
|
||||
# type BoundingBox = i32;
|
||||
|
@ -1360,6 +1362,20 @@ This defines a trait with two methods. All values that have
|
|||
`draw` and `bounding_box` methods called, using `value.bounding_box()`
|
||||
[syntax](#method-call-expressions).
|
||||
|
||||
Traits can include default implementations of methods, as in:
|
||||
|
||||
```
|
||||
trait Foo {
|
||||
fn bar(&self);
|
||||
|
||||
fn baz(&self) { println!("We called baz."); }
|
||||
}
|
||||
```
|
||||
|
||||
Here the `baz` method has a default implementation, so types that implement
|
||||
`Foo` need only implement `bar`. It is also possible for implementing types
|
||||
to override a method that has a default implementation.
|
||||
|
||||
Type parameters can be specified for a trait to make it generic. These appear
|
||||
after the trait name, using the same syntax used in [generic
|
||||
functions](#generic-functions).
|
||||
|
@ -1372,6 +1388,35 @@ trait Seq<T> {
|
|||
}
|
||||
```
|
||||
|
||||
It is also possible to define associated types for a trait. Consider the
|
||||
following example of a `Container` trait. Notice how the type is available
|
||||
for use in the method signatures:
|
||||
|
||||
```
|
||||
trait Container {
|
||||
type E;
|
||||
fn empty() -> Self;
|
||||
fn insert(&mut self, Self::E);
|
||||
}
|
||||
```
|
||||
|
||||
In order for a type to implement this trait, it must not only provide
|
||||
implementations for every method, but it must specify the type `E`. Here's
|
||||
an implementation of `Container` for the standard library type `Vec`:
|
||||
|
||||
```
|
||||
# trait Container {
|
||||
# type E;
|
||||
# fn empty() -> Self;
|
||||
# fn insert(&mut self, Self::E);
|
||||
# }
|
||||
impl<T> Container for Vec<T> {
|
||||
type E = T;
|
||||
fn empty() -> Vec<T> { Vec::new() }
|
||||
fn insert(&mut self, x: T) { self.push(x); }
|
||||
}
|
||||
```
|
||||
|
||||
Generic functions may use traits as _bounds_ on their type parameters. This
|
||||
will have two effects: only types that have the trait may instantiate the
|
||||
parameter, and within the generic function, the methods of the trait can be
|
||||
|
@ -3470,13 +3515,21 @@ more of the closure traits:
|
|||
|
||||
### Trait objects
|
||||
|
||||
Every trait item (see [traits](#traits)) defines a type with the same name as
|
||||
the trait. This type is called the _trait object_ of the trait. Trait objects
|
||||
permit "late binding" of methods, dispatched using _virtual method tables_
|
||||
("vtables"). Whereas most calls to trait methods are "early bound" (statically
|
||||
resolved) to specific implementations at compile time, a call to a method on an
|
||||
trait objects is only resolved to a vtable entry at compile time. The actual
|
||||
implementation for each vtable entry can vary on an object-by-object basis.
|
||||
In Rust, a type like `&SomeTrait` or `Box<SomeTrait>` is called a _trait object_.
|
||||
Each instance of a trait object includes:
|
||||
|
||||
- a pointer to an instance of a type `T` that implements `SomeTrait`
|
||||
- a _virtual method table_, often just called a _vtable_, which contains, for
|
||||
each method of `SomeTrait` that `T` implements, a pointer to `T`'s
|
||||
implementation (i.e. a function pointer).
|
||||
|
||||
The purpose of trait objects is to permit "late binding" of methods. A call to
|
||||
a method on a trait object is only resolved to a vtable entry at compile time.
|
||||
The actual implementation for each vtable entry can vary on an object-by-object
|
||||
basis.
|
||||
|
||||
Note that for a trait object to be instantiated, the trait must be
|
||||
_object-safe_. Object safety rules are defined in [RFC 255][rfc255].
|
||||
|
||||
Given a pointer-typed expression `E` of type `&T` or `Box<T>`, where `T`
|
||||
implements trait `R`, casting `E` to the corresponding pointer type `&R` or
|
||||
|
|
|
@ -175,7 +175,7 @@ data, we call the `clone()` method. In this example, `y` is no longer a referenc
|
|||
to the vector stored in `x`, but a copy of its first element, `"Hello"`. Now
|
||||
that we don’t have a reference, our `push()` works just fine.
|
||||
|
||||
[move]: move-semantics.html
|
||||
[move]: ownership.html#move-semantics
|
||||
|
||||
If we truly want a reference, we need the other option: ensure that our reference
|
||||
goes out of scope before we try to do the mutation. That looks like this:
|
||||
|
|
|
@ -450,7 +450,7 @@ which blocks execution until the thread has completed execution. This ensures
|
|||
that the threads complete their work before the program exits.
|
||||
|
||||
If you run this program, you’ll see that the philosophers eat out of order!
|
||||
We have mult-threading!
|
||||
We have multi-threading!
|
||||
|
||||
```text
|
||||
Gilles Deleuze is eating.
|
||||
|
|
|
@ -181,6 +181,8 @@ match version {
|
|||
This function makes use of an enum, `ParseError`, to enumerate the various
|
||||
errors that can occur.
|
||||
|
||||
The [`Debug`](../std/fmt/trait.Debug.html) trait is what lets us print the enum value using the `{:?}` format operation.
|
||||
|
||||
# Non-recoverable errors with `panic!`
|
||||
|
||||
In the case of an error that is unexpected and not recoverable, the `panic!`
|
||||
|
|
|
@ -266,7 +266,7 @@ Rust programs use [jemalloc][jemalloc] for this purpose.
|
|||
Anyway, back to our example. Since this memory is on the heap, it can stay
|
||||
alive longer than the function which allocates the box. In this case, however,
|
||||
it doesn’t.[^moving] When the function is over, we need to free the stack frame
|
||||
for `main()`. `Box<T>`, though, has a trick up its sleve: [Drop][drop]. The
|
||||
for `main()`. `Box<T>`, though, has a trick up its sleeve: [Drop][drop]. The
|
||||
implementation of `Drop` for `Box` deallocates the memory that was allocated
|
||||
when it was created. Great! So when `x` goes away, it first frees the memory
|
||||
allocated on the heap:
|
||||
|
|
|
@ -18,39 +18,41 @@
|
|||
//! You can explicitly create a `Vec<T>` with `new()`:
|
||||
//!
|
||||
//! ```
|
||||
//! let xs: Vec<i32> = Vec::new();
|
||||
//! let v: Vec<i32> = Vec::new();
|
||||
//! ```
|
||||
//!
|
||||
//! ...or by using the `vec!` macro:
|
||||
//!
|
||||
//! ```
|
||||
//! let ys: Vec<i32> = vec![];
|
||||
//! let v: Vec<i32> = vec![];
|
||||
//!
|
||||
//! let zs = vec![1i32, 2, 3, 4, 5];
|
||||
//! let v = vec![1, 2, 3, 4, 5];
|
||||
//!
|
||||
//! let v = vec![0; 10]; // ten zeroes
|
||||
//! ```
|
||||
//!
|
||||
//! You can `push` values onto the end of a vector (which will grow the vector as needed):
|
||||
//!
|
||||
//! ```
|
||||
//! let mut xs = vec![1i32, 2];
|
||||
//! let mut v = vec![1, 2];
|
||||
//!
|
||||
//! xs.push(3);
|
||||
//! v.push(3);
|
||||
//! ```
|
||||
//!
|
||||
//! Popping values works in much the same way:
|
||||
//!
|
||||
//! ```
|
||||
//! let mut xs = vec![1i32, 2];
|
||||
//! let mut v = vec![1, 2];
|
||||
//!
|
||||
//! let two = xs.pop();
|
||||
//! let two = v.pop();
|
||||
//! ```
|
||||
//!
|
||||
//! Vectors also support indexing (through the `Index` and `IndexMut` traits):
|
||||
//!
|
||||
//! ```
|
||||
//! let mut xs = vec![1i32, 2, 3];
|
||||
//! let three = xs[2];
|
||||
//! xs[1] = xs[1] + 5;
|
||||
//! let mut v = vec![1, 2, 3];
|
||||
//! let three = v[2];
|
||||
//! v[1] = v[1] + 5;
|
||||
//! ```
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
|
@ -167,7 +167,7 @@ macro_rules! try {
|
|||
})
|
||||
}
|
||||
|
||||
/// Use the `format!` syntax to write data into a buffer of type `&mut Writer`.
|
||||
/// Use the `format!` syntax to write data into a buffer of type `&mut Write`.
|
||||
/// See `std::fmt` for more information.
|
||||
///
|
||||
/// # Examples
|
||||
|
|
|
@ -427,8 +427,8 @@ be taken.
|
|||
|
||||
E0271: r##"
|
||||
This is because of a type mismatch between the associated type of some
|
||||
trait (e.g. T::Bar, where T implements trait Quux { type Bar; })
|
||||
and another type U that is required to be equal to T::Bar, but is not.
|
||||
trait (e.g. `T::Bar`, where `T` implements `trait Quux { type Bar; }`)
|
||||
and another type `U` that is required to be equal to `T::Bar`, but is not.
|
||||
Examples follow.
|
||||
|
||||
Here is a basic example:
|
||||
|
|
|
@ -20,6 +20,7 @@ Imports (`use` statements) are not allowed after non-item statements, such as
|
|||
variable declarations and expression statements.
|
||||
|
||||
Here is an example that demonstrates the error:
|
||||
|
||||
```
|
||||
fn f() {
|
||||
// Variable declaration before import
|
||||
|
@ -33,6 +34,7 @@ The solution is to declare the imports at the top of the block, function, or
|
|||
file.
|
||||
|
||||
Here is the previous example again, with the correct order:
|
||||
|
||||
```
|
||||
fn f() {
|
||||
use std::io::Read;
|
||||
|
@ -52,6 +54,7 @@ The name chosen for an external crate conflicts with another external crate that
|
|||
has been imported into the current module.
|
||||
|
||||
Wrong example:
|
||||
|
||||
```
|
||||
extern crate a;
|
||||
extern crate crate_a as a;
|
||||
|
@ -61,6 +64,7 @@ The solution is to choose a different name that doesn't conflict with any
|
|||
external crate imported into the current module.
|
||||
|
||||
Correct example:
|
||||
|
||||
```
|
||||
extern crate a;
|
||||
extern crate crate_a as other_name;
|
||||
|
@ -71,6 +75,7 @@ E0260: r##"
|
|||
The name for an item declaration conflicts with an external crate's name.
|
||||
|
||||
For instance,
|
||||
|
||||
```
|
||||
extern crate abc;
|
||||
|
||||
|
|
|
@ -19,6 +19,51 @@ methods that do not have default implementations), as well as any required
|
|||
trait items like associated types or constants.
|
||||
"##,
|
||||
|
||||
E0049: r##"
|
||||
This error indicates that an attempted implementation of a trait method
|
||||
has the wrong number of type parameters.
|
||||
|
||||
For example, the trait below has a method `foo` with a type parameter `T`,
|
||||
but the implementation of `foo` for the type `Bar` is missing this parameter:
|
||||
|
||||
```
|
||||
trait Foo {
|
||||
fn foo<T: Default>(x: T) -> Self;
|
||||
}
|
||||
|
||||
struct Bar;
|
||||
|
||||
// error: method `foo` has 0 type parameters but its trait declaration has 1
|
||||
// type parameter
|
||||
impl Foo for Bar {
|
||||
fn foo(x: bool) -> Self { Bar }
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
||||
E0050: r##"
|
||||
This error indicates that an attempted implementation of a trait method
|
||||
has the wrong number of function parameters.
|
||||
|
||||
For example, the trait below has a method `foo` with two function parameters
|
||||
(`&self` and `u8`), but the implementation of `foo` for the type `Bar` omits
|
||||
the `u8` parameter:
|
||||
|
||||
```
|
||||
trait Foo {
|
||||
fn foo(&self, x: u8) -> bool;
|
||||
}
|
||||
|
||||
struct Bar;
|
||||
|
||||
// error: method `foo` has 1 parameter but the declaration in trait `Foo::foo`
|
||||
// has 2
|
||||
impl Foo for Bar {
|
||||
fn foo(&self) -> bool { true }
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
||||
E0054: r##"
|
||||
It is not allowed to cast to a bool. If you are trying to cast a numeric type
|
||||
to a bool, you can compare it with zero instead:
|
||||
|
@ -138,6 +183,88 @@ enum Empty {}
|
|||
```
|
||||
"##,
|
||||
|
||||
E0106: r##"
|
||||
This error indicates that a lifetime is missing from a type. If it is an error
|
||||
inside a function signature, the problem may be with failing to adhere to the
|
||||
lifetime elision rules (see below).
|
||||
|
||||
Here are some simple examples of where you'll run into this error:
|
||||
|
||||
```
|
||||
struct Foo { x: &bool } // error
|
||||
struct Foo<'a> { x: &'a bool } // correct
|
||||
|
||||
enum Bar { A(u8), B(&bool), } // error
|
||||
enum Bar<'a> { A(u8), B(&'a bool), } // correct
|
||||
|
||||
type MyStr = &str; // error
|
||||
type MyStr<'a> = &'a str; //correct
|
||||
|
||||
```
|
||||
|
||||
Lifetime elision is a special, limited kind of inference for lifetimes in
|
||||
function signatures which allows you to leave out lifetimes in certain cases.
|
||||
For more background on lifetime elision see [the book][book-le].
|
||||
|
||||
The lifetime elision rules require that any function signature with an elided
|
||||
output lifetime must either have
|
||||
|
||||
- exactly one input lifetime
|
||||
- or, multiple input lifetimes, but the function must also be a method with a
|
||||
`&self` or `&mut self` receiver
|
||||
|
||||
In the first case, the output lifetime is inferred to be the same as the unique
|
||||
input lifetime. In the second case, the lifetime is instead inferred to be the
|
||||
same as the lifetime on `&self` or `&mut self`.
|
||||
|
||||
Here are some examples of elision errors:
|
||||
|
||||
```
|
||||
// error, no input lifetimes
|
||||
fn foo() -> &str { ... }
|
||||
|
||||
// error, `x` and `y` have distinct lifetimes inferred
|
||||
fn bar(x: &str, y: &str) -> &str { ... }
|
||||
|
||||
// error, `y`'s lifetime is inferred to be distinct from `x`'s
|
||||
fn baz<'a>(x: &'a str, y: &str) -> &str { ... }
|
||||
```
|
||||
|
||||
[book-le]: http://doc.rust-lang.org/nightly/book/lifetimes.html#lifetime-elision
|
||||
"##,
|
||||
|
||||
E0107: r##"
|
||||
This error means that an incorrect number of lifetime parameters were provided
|
||||
for a type (like a struct or enum) or trait.
|
||||
|
||||
Some basic examples include:
|
||||
|
||||
```
|
||||
struct Foo<'a>(&'a str);
|
||||
enum Bar { A, B, C }
|
||||
|
||||
struct Baz<'a> {
|
||||
foo: Foo, // error: expected 1, found 0
|
||||
bar: Bar<'a>, // error: expected 0, found 1
|
||||
}
|
||||
```
|
||||
|
||||
Here's an example that is currently an error, but may work in a future version
|
||||
of Rust:
|
||||
|
||||
```
|
||||
struct Foo<'a>(&'a str);
|
||||
|
||||
trait Quux { }
|
||||
impl Quux for Foo { } // error: expected 1, found 0
|
||||
```
|
||||
|
||||
Lifetime elision in implementation headers was part of the lifetime elision
|
||||
RFC. It is, however, [currently unimplemented][iss15872].
|
||||
|
||||
[iss15872]: https://github.com/rust-lang/rust/issues/15872
|
||||
"##,
|
||||
|
||||
E0131: r##"
|
||||
It is not possible to define `main` with type parameters, or even with function
|
||||
parameters. When `main` is present, it must take no arguments and return `()`.
|
||||
|
@ -152,6 +279,20 @@ fn(isize, *const *const u8) -> isize
|
|||
```
|
||||
"##,
|
||||
|
||||
E0166: r##"
|
||||
This error means that the compiler found a return expression in a function
|
||||
marked as diverging. A function diverges if it has `!` in the place of the
|
||||
return type in its signature. For example:
|
||||
|
||||
```
|
||||
fn foo() -> ! { return; } // error
|
||||
```
|
||||
|
||||
For a function that diverges, every control path in the function must never
|
||||
return, for example with a `loop` that never breaks or a call to another
|
||||
diverging function (such as `panic!()`).
|
||||
"##,
|
||||
|
||||
E0184: r##"
|
||||
Explicitly implementing both Drop and Copy for a type is currently disallowed.
|
||||
This feature can make some sense in theory, but the current implementation is
|
||||
|
@ -161,6 +302,24 @@ it has been disabled for now.
|
|||
[iss20126]: https://github.com/rust-lang/rust/issues/20126
|
||||
"##,
|
||||
|
||||
E0201: r##"
|
||||
It is an error to define a method--a trait method or an inherent method--more
|
||||
than once.
|
||||
|
||||
For example,
|
||||
|
||||
```
|
||||
struct Foo(u8);
|
||||
|
||||
impl Foo {
|
||||
fn bar() {}
|
||||
|
||||
// error: duplicate method
|
||||
fn bar(&self) -> bool { self.0 > 5 }
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
||||
E0204: r##"
|
||||
An attempt to implement the `Copy` trait for a struct failed because one of the
|
||||
fields does not implement `Copy`. To fix this, you must implement `Copy` for the
|
||||
|
@ -292,6 +451,13 @@ const B: [u32; foo()] = [];
|
|||
use std::{f64, u8};
|
||||
const C: [u32; u8::MAX + f64::EPSILON] = [];
|
||||
```
|
||||
"##,
|
||||
|
||||
E0322: r##"
|
||||
The `Sized` trait is a special trait built-in to the compiler for types with a
|
||||
constant size known at compile-time. This trait is automatically implemented
|
||||
for types as needed by the compiler, and it is currently disallowed to
|
||||
explicitly implement it for a type.
|
||||
"##
|
||||
|
||||
}
|
||||
|
@ -312,8 +478,6 @@ register_diagnostics! {
|
|||
E0040, // explicit use of destructor method
|
||||
E0044, // foreign items may not have type parameters
|
||||
E0045, // variadic function must have C calling convention
|
||||
E0049,
|
||||
E0050,
|
||||
E0053,
|
||||
E0055, // method has an incompatible type for trait
|
||||
E0057, // method has an incompatible type for trait
|
||||
|
@ -345,8 +509,6 @@ register_diagnostics! {
|
|||
E0102,
|
||||
E0103,
|
||||
E0104,
|
||||
E0106,
|
||||
E0107,
|
||||
E0116,
|
||||
E0117,
|
||||
E0118,
|
||||
|
@ -364,7 +526,6 @@ register_diagnostics! {
|
|||
E0159,
|
||||
E0163,
|
||||
E0164,
|
||||
E0166,
|
||||
E0167,
|
||||
E0168,
|
||||
E0172,
|
||||
|
@ -390,7 +551,6 @@ register_diagnostics! {
|
|||
E0198, // negative implementations are not unsafe
|
||||
E0199, // implementing trait is not unsafe
|
||||
E0200, // trait requires an `unsafe impl` declaration
|
||||
E0201, // duplicate method in trait impl
|
||||
E0202, // associated items are not allowed in inherent impls
|
||||
E0203, // type parameter has more than one relaxed default bound,
|
||||
// and only one is supported
|
||||
|
@ -421,7 +581,7 @@ register_diagnostics! {
|
|||
E0231, // only named substitution parameters are allowed
|
||||
E0232, // this attribute must have a value
|
||||
E0233,
|
||||
E0234, // `for` loop expression has type which does not implement the `Iterator` trait
|
||||
E0234,
|
||||
E0235, // structure constructor specifies a structure of type but
|
||||
E0236, // no lang item for range syntax
|
||||
E0237, // no lang item for range syntax
|
||||
|
@ -438,7 +598,6 @@ register_diagnostics! {
|
|||
E0319, // trait impls for defaulted traits allowed just for structs/enums
|
||||
E0320, // recursive overflow during dropck
|
||||
E0321, // extended coherence rules for defaulted traits violated
|
||||
E0322, // cannot implement Sized explicitly
|
||||
E0323, // implemented an associated const when another trait item expected
|
||||
E0324, // implemented a method when another trait item expected
|
||||
E0325, // implemented an associated type when another trait item expected
|
||||
|
|
Loading…
Add table
Reference in a new issue