Auto merge of #25340 - Manishearth:rollup, r=Manishearth
- Successful merges: #24996, #25220, #25221, #25267, #25322, #25327, #25329, #25330, #25331, #25335 - Failed merges: #25334
This commit is contained in:
commit
c2b30b86df
16 changed files with 443 additions and 89 deletions
|
@ -5,15 +5,14 @@ to jump to any particular section.
|
|||
|
||||
# Getting Started
|
||||
|
||||
If you haven't seen Rust at all yet, the first thing you should read is the [30
|
||||
minute intro](intro.html). It will give you an overview of the basic ideas of Rust
|
||||
at a high level.
|
||||
If you haven't seen Rust at all yet, the first thing you should read is the
|
||||
introduction to [The Rust Programming Language](book/index.html). It'll give
|
||||
you a good idea of what Rust is like.
|
||||
|
||||
Once you know you really want to learn Rust, the next step is reading [The
|
||||
Rust Programming Language](book/index.html). It is a lengthy explanation of
|
||||
Rust, its syntax, and its concepts. Upon completing the book, you'll be an
|
||||
intermediate Rust developer, and will have a good grasp of the fundamental
|
||||
ideas behind Rust.
|
||||
The book provides a lengthy explanation of Rust, its syntax, and its
|
||||
concepts. Upon completing the book, you'll be an intermediate Rust
|
||||
developer, and will have a good grasp of the fundamental ideas behind
|
||||
Rust.
|
||||
|
||||
[Rust By Example][rbe] was originally a community resource, but was then
|
||||
donated to the Rust project. As the name implies, it teaches you Rust through a
|
||||
|
@ -24,7 +23,7 @@ series of small examples.
|
|||
# Community & Getting Help
|
||||
|
||||
If you need help with something, or just want to talk about Rust with others,
|
||||
there's a few places you can do that:
|
||||
there are a few places you can do that:
|
||||
|
||||
The Rust IRC channels on [irc.mozilla.org](http://irc.mozilla.org/) are the
|
||||
fastest way to get help.
|
||||
|
@ -59,7 +58,7 @@ the language in as much detail as possible is in [the reference](reference.html)
|
|||
|
||||
# Tools
|
||||
|
||||
Rust's still a young language, so there isn't a ton of tooling yet, but the
|
||||
Rust is still a young language, so there isn't a ton of tooling yet, but the
|
||||
tools we have are really nice.
|
||||
|
||||
[Cargo](http://crates.io) is Rust's package manager, and its website contains
|
||||
|
@ -69,16 +68,21 @@ lots of good documentation.
|
|||
|
||||
# FAQs
|
||||
|
||||
There are questions that are asked quite often, and so we've made FAQs for them:
|
||||
There are questions that are asked quite often, so we've made FAQs for them:
|
||||
|
||||
* [Language Design FAQ](complement-design-faq.html)
|
||||
* [Language FAQ](complement-lang-faq.html)
|
||||
* [Project FAQ](complement-project-faq.html)
|
||||
* [How to submit a bug report](https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports)
|
||||
|
||||
# The standard library
|
||||
# The Standard Library
|
||||
|
||||
We have [API documentation for the entire standard
|
||||
library](std/index.html). There's a list of crates on the left with more
|
||||
specific sections, or you can use the search bar at the top to search for
|
||||
something if you know its name.
|
||||
|
||||
# The Error Index
|
||||
|
||||
If you encounter an error while compiling your code you may be able to look it
|
||||
up in the [Rust Compiler Error Index](error-index.html).
|
||||
|
|
|
@ -426,12 +426,12 @@ x;
|
|||
x::y::z;
|
||||
```
|
||||
|
||||
Path components are usually [identifiers](#identifiers), but the trailing
|
||||
component of a path may be an angle-bracket-enclosed list of type arguments. In
|
||||
[expression](#expressions) context, the type argument list is given after a
|
||||
final (`::`) namespace qualifier in order to disambiguate it from a relational
|
||||
expression involving the less-than symbol (`<`). In type expression context,
|
||||
the final namespace qualifier is omitted.
|
||||
Path components are usually [identifiers](#identifiers), but they may
|
||||
also include angle-bracket-enclosed lists of type arguments. In
|
||||
[expression](#expressions) context, the type argument list is given
|
||||
after a `::` namespace qualifier in order to disambiguate it from a
|
||||
relational expression involving the less-than symbol (`<`). In type
|
||||
expression context, the final namespace qualifier is omitted.
|
||||
|
||||
Two examples of paths with type arguments:
|
||||
|
||||
|
@ -497,8 +497,9 @@ names, and invoked through a consistent syntax: `some_extension!(...)`.
|
|||
|
||||
Users of `rustc` can define new syntax extensions in two ways:
|
||||
|
||||
* [Compiler plugins][plugin] can include arbitrary
|
||||
Rust code that manipulates syntax trees at compile time.
|
||||
* [Compiler plugins][plugin] can include arbitrary Rust code that
|
||||
manipulates syntax trees at compile time. Note that the interface
|
||||
for compiler plugins is considered highly unstable.
|
||||
|
||||
* [Macros](book/macros.html) define new syntax in a higher-level,
|
||||
declarative way.
|
||||
|
@ -560,14 +561,18 @@ Nested repetitions are allowed.
|
|||
The parser used by the macro system is reasonably powerful, but the parsing of
|
||||
Rust syntax is restricted in two ways:
|
||||
|
||||
1. The parser will always parse as much as possible. If it attempts to match
|
||||
`$i:expr [ , ]` against `8 [ , ]`, it will attempt to parse `i` as an array
|
||||
index operation and fail. Adding a separator can solve this problem.
|
||||
1. Macro definitions are required to include suitable separators after parsing
|
||||
expressions and other bits of the Rust grammar. This implies that
|
||||
a macro definition like `$i:expr [ , ]` is not legal, because `[` could be part
|
||||
of an expression. A macro definition like `$i:expr,` or `$i:expr;` would be legal,
|
||||
however, because `,` and `;` are legal separators. See [RFC 550] for more information.
|
||||
2. The parser must have eliminated all ambiguity by the time it reaches a `$`
|
||||
_name_ `:` _designator_. This requirement most often affects name-designator
|
||||
pairs when they occur at the beginning of, or immediately after, a `$(...)*`;
|
||||
requiring a distinctive token in front can solve the problem.
|
||||
|
||||
[RFC 550]: https://github.com/rust-lang/rfcs/blob/master/text/0550-macro-future-proofing.md
|
||||
|
||||
# Crates and source files
|
||||
|
||||
Although Rust, like any other language, can be implemented by an interpreter as
|
||||
|
@ -686,7 +691,8 @@ type arguments as a list of comma-separated types enclosed within angle
|
|||
brackets, in order to refer to the type-parameterized item. In practice, the
|
||||
type-inference system can usually infer such argument types from context. There
|
||||
are no general type-parametric types, only type-parametric items. That is, Rust
|
||||
has no notion of type abstraction: there are no first-class "forall" types.
|
||||
has no notion of type abstraction: there are no higher-ranked (or "forall") types
|
||||
abstracted over other types, though higher-ranked types do exist for lifetimes.
|
||||
|
||||
### Modules
|
||||
|
||||
|
@ -732,6 +738,7 @@ mod vec;
|
|||
|
||||
mod thread {
|
||||
// Load the `local_data` module from `thread/local_data.rs`
|
||||
// or `thread/local_data/mod.rs`.
|
||||
mod local_data;
|
||||
}
|
||||
```
|
||||
|
@ -1004,7 +1011,8 @@ the guarantee that these issues are never caused by safe code.
|
|||
* `&mut` and `&` follow LLVM’s scoped [noalias] model, except if the `&T`
|
||||
contains an `UnsafeCell<U>`. Unsafe code must not violate these aliasing
|
||||
guarantees.
|
||||
* Mutating an immutable value/reference without `UnsafeCell<U>`
|
||||
* Mutating non-mutable data (that is, data reached through a shared reference or
|
||||
data owned by a `let` binding), unless that data is contained within an `UnsafeCell<U>`.
|
||||
* Invoking undefined behavior via compiler intrinsics:
|
||||
* Indexing outside of the bounds of an object with `std::ptr::offset`
|
||||
(`offset` intrinsic), with
|
||||
|
@ -1034,9 +1042,13 @@ be undesired.
|
|||
* Exiting without calling destructors
|
||||
* Sending signals
|
||||
* Accessing/modifying the file system
|
||||
* Unsigned integer overflow (well-defined as wrapping)
|
||||
* Signed integer overflow (well-defined as two’s complement representation
|
||||
wrapping)
|
||||
* Integer overflow
|
||||
- Overflow is considered "unexpected" behavior and is always user-error,
|
||||
unless the `wrapping` primitives are used. In non-optimized builds, the compiler
|
||||
will insert debug checks that panic on overflow, but in optimized builds overflow
|
||||
instead results in wrapped values. See [RFC 560] for the rationale and more details.
|
||||
|
||||
[RFC 560]: https://github.com/rust-lang/rfcs/blob/master/text/0560-integer-overflow.md
|
||||
|
||||
#### Diverging functions
|
||||
|
||||
|
@ -1310,11 +1322,26 @@ type of the value is not required to ascribe to `Sync`.
|
|||
|
||||
### Traits
|
||||
|
||||
A _trait_ describes a set of method types.
|
||||
A _trait_ describes an abstract interface that types can
|
||||
implement. This interface consists of associated items, which come in
|
||||
three varieties:
|
||||
|
||||
Traits can include default implementations of methods, written in terms of some
|
||||
unknown [`self` type](#self-types); the `self` type may either be completely
|
||||
unspecified, or constrained by some other trait.
|
||||
- functions
|
||||
- constants
|
||||
- types
|
||||
|
||||
Associated functions whose first parameter is named `self` are called
|
||||
methods and may be invoked using `.` notation (e.g., `x.foo()`).
|
||||
|
||||
All traits define an implicit type parameter `Self` that refers to
|
||||
"the type that is implementing this interface". Traits may also
|
||||
contain additional type parameters. These type parameters (including
|
||||
`Self`) may be constrained by other traits and so forth as usual.
|
||||
|
||||
Trait bounds on `Self` are considered "supertraits". These are
|
||||
required to be acyclic. Supertraits are somewhat different from other
|
||||
constraints in that they affect what methods are available in the
|
||||
vtable when the trait is used as a [trait object](#trait-objects).
|
||||
|
||||
Traits are implemented for specific types through separate
|
||||
[implementations](#implementations).
|
||||
|
@ -1359,15 +1386,18 @@ fn draw_twice<T: Shape>(surface: Surface, sh: T) {
|
|||
}
|
||||
```
|
||||
|
||||
Traits also define an [trait object](#trait-objects) with the same name as the
|
||||
trait. Values of this type are created by [casting](#type-cast-expressions)
|
||||
pointer values (pointing to a type for which an implementation of the given
|
||||
trait is in scope) to pointers to the trait name, used as a type.
|
||||
Traits also define an [trait object](#trait-objects) with the same
|
||||
name as the trait. Values of this type are created by coercing from a
|
||||
pointer of some specific type to a pointer of trait type. For example,
|
||||
`&T` could be coerced to `&Shape` if `T: Shape` holds (and similarly
|
||||
for `Box<T>`). This coercion can either be implicit or
|
||||
[explicit](#type-cast-expressions). Here is an example of an explicit
|
||||
coercion:
|
||||
|
||||
```
|
||||
# trait Shape { fn dummy(&self) { } }
|
||||
# impl Shape for i32 { }
|
||||
# let mycircle = 0i32;
|
||||
trait Shape { }
|
||||
impl Shape for i32 { }
|
||||
let mycircle = 0i32;
|
||||
let myshape: Box<Shape> = Box::new(mycircle) as Box<Shape>;
|
||||
```
|
||||
|
||||
|
@ -2041,7 +2071,8 @@ The name `str_eq` has a special meaning to the Rust compiler, and the presence
|
|||
of this definition means that it will use this definition when generating calls
|
||||
to the string equality function.
|
||||
|
||||
A complete list of the built-in language items will be added in the future.
|
||||
The set of language items is currently considered unstable. A complete
|
||||
list of the built-in language items will be added in the future.
|
||||
|
||||
### Inline attributes
|
||||
|
||||
|
@ -2053,11 +2084,6 @@ The compiler automatically inlines functions based on internal heuristics.
|
|||
Incorrectly inlining functions can actually make the program slower, so it
|
||||
should be used with care.
|
||||
|
||||
Immutable statics are always considered inlineable unless marked with
|
||||
`#[inline(never)]`. It is undefined whether two different inlineable statics
|
||||
have the same memory address. In other words, the compiler is free to collapse
|
||||
duplicate inlineable statics together.
|
||||
|
||||
`#[inline]` and `#[inline(always)]` always cause the function to be serialized
|
||||
into the crate metadata to allow cross-crate inlining.
|
||||
|
||||
|
@ -2259,10 +2285,6 @@ The currently implemented features of the reference compiler are:
|
|||
* `unboxed_closures` - Rust's new closure design, which is currently a work in
|
||||
progress feature with many known bugs.
|
||||
|
||||
* `unsafe_destructor` - Allows use of the `#[unsafe_destructor]` attribute,
|
||||
which is considered wildly unsafe and will be
|
||||
obsoleted by language improvements.
|
||||
|
||||
* `unsafe_no_drop_flag` - Allows use of the `#[unsafe_no_drop_flag]` attribute,
|
||||
which removes hidden flag added to a type that
|
||||
implements the `Drop` trait. The design for the
|
||||
|
@ -2382,18 +2404,54 @@ expressions](#index-expressions) (`expr[expr]`), and [field
|
|||
references](#field-expressions) (`expr.f`). All other expressions are rvalues.
|
||||
|
||||
The left operand of an [assignment](#assignment-expressions) or
|
||||
[compound-assignment](#compound-assignment-expressions) expression is an lvalue
|
||||
context, as is the single operand of a unary
|
||||
[borrow](#unary-operator-expressions). All other expression contexts are
|
||||
rvalue contexts.
|
||||
[compound-assignment](#compound-assignment-expressions) expression is
|
||||
an lvalue context, as is the single operand of a unary
|
||||
[borrow](#unary-operator-expressions). The discriminant or subject of
|
||||
a [match expression](#match-expressions) may be an lvalue context, if
|
||||
ref bindings are made, but is otherwise an rvalue context. All other
|
||||
expression contexts are rvalue contexts.
|
||||
|
||||
When an lvalue is evaluated in an _lvalue context_, it denotes a memory
|
||||
location; when evaluated in an _rvalue context_, it denotes the value held _in_
|
||||
that memory location.
|
||||
|
||||
When an rvalue is used in an lvalue context, a temporary un-named lvalue is
|
||||
created and used instead. A temporary's lifetime equals the largest lifetime
|
||||
of any reference that points to it.
|
||||
##### Temporary lifetimes
|
||||
|
||||
When an rvalue is used in an lvalue context, a temporary un-named
|
||||
lvalue is created and used instead. The lifetime of temporary values
|
||||
is typically the innermost enclosing statement; the tail expression of
|
||||
a block is considered part of the statement that encloses the block.
|
||||
|
||||
When a temporary rvalue is being created that is assigned into a `let`
|
||||
declaration, however, the temporary is created with the lifetime of
|
||||
the enclosing block instead, as using the enclosing statement (the
|
||||
`let` declaration) would be a guaranteed error (since a pointer to the
|
||||
temporary would be stored into a variable, but the temporary would be
|
||||
freed before the variable could be used). The compiler uses simple
|
||||
syntactic rules to decide which values are being assigned into a `let`
|
||||
binding, and therefore deserve a longer temporary lifetime.
|
||||
|
||||
Here are some examples:
|
||||
|
||||
- `let x = foo(&temp())`. The expression `temp()` is an rvalue. As it
|
||||
is being borrowed, a temporary is created which will be freed after
|
||||
the innermost enclosing statement (the `let` declaration, in this case).
|
||||
- `let x = temp().foo()`. This is the same as the previous example,
|
||||
except that the value of `temp()` is being borrowed via autoref on a
|
||||
method-call. Here we are assuming that `foo()` is an `&self` method
|
||||
defined in some trait, say `Foo`. In other words, the expression
|
||||
`temp().foo()` is equivalent to `Foo::foo(&temp())`.
|
||||
- `let x = &temp()`. Here, the same temporary is being assigned into
|
||||
`x`, rather than being passed as a parameter, and hence the
|
||||
temporary's lifetime is considered to be the enclosing block.
|
||||
- `let x = SomeStruct { foo: &temp() }`. As in the previous case, the
|
||||
temporary is assigned into a struct which is then assigned into a
|
||||
binding, and hence it is given the lifetime of the enclosing block.
|
||||
- `let x = [ &temp() ]`. As in the previous case, the
|
||||
temporary is assigned into an array which is then assigned into a
|
||||
binding, and hence it is given the lifetime of the enclosing block.
|
||||
- `let ref x = temp()`. In this case, the temporary is created using a ref binding,
|
||||
but the result is the same: the lifetime is extended to the enclosing block.
|
||||
|
||||
#### Moved and copied types
|
||||
|
||||
|
@ -2535,8 +2593,10 @@ A field access is an [lvalue](#lvalues,-rvalues-and-temporaries) referring to
|
|||
the value of that field. When the type providing the field inherits mutability,
|
||||
it can be [assigned](#assignment-expressions) to.
|
||||
|
||||
Also, if the type of the expression to the left of the dot is a pointer, it is
|
||||
automatically dereferenced to make the field access possible.
|
||||
Also, if the type of the expression to the left of the dot is a
|
||||
pointer, it is automatically dereferenced as many times as necessary
|
||||
to make the field access possible. In cases of ambiguity, we prefer
|
||||
fewer autoderefs to more.
|
||||
|
||||
### Array expressions
|
||||
|
||||
|
@ -2577,6 +2637,11 @@ let arr = ["a", "b"];
|
|||
arr[10]; // panics
|
||||
```
|
||||
|
||||
Also, if the type of the expression to the left of the brackets is a
|
||||
pointer, it is automatically dereferenced as many times as necessary
|
||||
to make the indexing possible. In cases of ambiguity, we prefer fewer
|
||||
autoderefs to more.
|
||||
|
||||
### Range expressions
|
||||
|
||||
The `..` operator will construct an object of one of the `std::ops::Range` variants.
|
||||
|
@ -2599,7 +2664,7 @@ assert_eq!(x,y);
|
|||
|
||||
### Unary operator expressions
|
||||
|
||||
Rust defines three unary operators. They are all written as prefix operators,
|
||||
Rust defines the following unary operators. They are all written as prefix operators,
|
||||
before the expression they apply to.
|
||||
|
||||
* `-`
|
||||
|
@ -2613,11 +2678,20 @@ before the expression they apply to.
|
|||
implemented by the type and required for an outer expression that will or
|
||||
could mutate the dereference), and produces the result of dereferencing the
|
||||
`&` or `&mut` borrowed pointer returned from the overload method.
|
||||
|
||||
* `!`
|
||||
: Logical negation. On the boolean type, this flips between `true` and
|
||||
`false`. On integer types, this inverts the individual bits in the
|
||||
two's complement representation of the value.
|
||||
* `&` and `&mut`
|
||||
: Borrowing. When applied to an lvalue, these operators produce a
|
||||
reference (pointer) to the lvalue. The lvalue is also placed into
|
||||
a borrowed state for the duration of the reference. For a shared
|
||||
borrow (`&`), this implies that the lvalue may not be mutated, but
|
||||
it may be read or shared again. For a mutable borrow (`&mut`), the
|
||||
lvalue may not be accessed in any way until the borrow expires.
|
||||
If the `&` or `&mut` operators are applied to an rvalue, a
|
||||
temporary value is created; the lifetime of this temporary value
|
||||
is defined by [syntactic rules](#temporary-lifetimes).
|
||||
|
||||
### Binary operator expressions
|
||||
|
||||
|
@ -2727,6 +2801,13 @@ fn avg(v: &[f64]) -> f64 {
|
|||
}
|
||||
```
|
||||
|
||||
Some of the conversions which can be done through the `as` operator
|
||||
can also be done implicitly at various points in the program, such as
|
||||
argument passing and assignment to a `let` binding with an explicit
|
||||
type. Implicit conversions are limited to "harmless" conversions that
|
||||
do not lose information and which have minimal or no risk of
|
||||
surprising side-effects on the dynamic execution semantics.
|
||||
|
||||
#### Assignment expressions
|
||||
|
||||
An _assignment expression_ consists of an
|
||||
|
@ -3348,6 +3429,22 @@ let bo: Binop = add;
|
|||
x = bo(5,7);
|
||||
```
|
||||
|
||||
#### Function types for specific items
|
||||
|
||||
Internally to the compiler, there are also function types that are specific to a particular
|
||||
function item. In the following snippet, for example, the internal types of the functions
|
||||
`foo` and `bar` are different, despite the fact that they have the same signature:
|
||||
|
||||
```
|
||||
fn foo() { }
|
||||
fn bar() { }
|
||||
```
|
||||
|
||||
The types of `foo` and `bar` can both be implicitly coerced to the fn
|
||||
pointer type `fn()`. There is currently no syntax for unique fn types,
|
||||
though the compiler will emit a type like `fn() {foo}` in error
|
||||
messages to indicate "the unique fn type for the function `foo`".
|
||||
|
||||
### Closure types
|
||||
|
||||
A [lambda expression](#lambda-expressions) produces a closure value with
|
||||
|
@ -3432,8 +3529,9 @@ has type `Vec<A>`, a vector with element type `A`.
|
|||
|
||||
### Self types
|
||||
|
||||
The special type `self` has a meaning within methods inside an impl item. It
|
||||
refers to the type of the implicit `self` argument. For example, in:
|
||||
The special type `Self` has a meaning within traits and impls. In a trait definition, it refers
|
||||
to an implicit type parameter representing the "implementing" type. In an impl,
|
||||
it is an alias for the implementing type. For example, in:
|
||||
|
||||
```
|
||||
trait Printable {
|
||||
|
@ -3447,8 +3545,9 @@ impl Printable for String {
|
|||
}
|
||||
```
|
||||
|
||||
`self` refers to the value of type `String` that is the receiver for a call to
|
||||
the method `make_string`.
|
||||
The notation `&self` is a shorthand for `self: &Self`. In this case,
|
||||
in the impl, `Self` refers to the value of type `String` that is the
|
||||
receiver for a call to the method `make_string`.
|
||||
|
||||
# Special traits
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
* [Concurrency](concurrency.md)
|
||||
* [Error Handling](error-handling.md)
|
||||
* [FFI](ffi.md)
|
||||
* [Borrow and AsRef](borrow-and-asref.md)
|
||||
* [Syntax and Semantics](syntax-and-semantics.md)
|
||||
* [Variable Bindings](variable-bindings.md)
|
||||
* [Functions](functions.md)
|
||||
|
|
93
src/doc/trpl/borrow-and-asref.md
Normal file
93
src/doc/trpl/borrow-and-asref.md
Normal file
|
@ -0,0 +1,93 @@
|
|||
% Borrow and AsRef
|
||||
|
||||
The [`Borrow`][borrow] and [`AsRef`][asref] traits are very similar, but
|
||||
different. Here’s a quick refresher on what these two traits mean.
|
||||
|
||||
[borrow]: ../std/borrow/trait.Borrow.html
|
||||
[asref]: ../std/convert/trait.AsRef.html
|
||||
|
||||
# Borrow
|
||||
|
||||
The `Borrow` trait is used when you’re writing a datastructure, and you want to
|
||||
use either an owned or borrowed type as synonymous for some purpose.
|
||||
|
||||
For example, [`HashMap`][hashmap] has a [`get` method][get] which uses `Borrow`:
|
||||
|
||||
```rust,ignore
|
||||
fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
|
||||
where K: Borrow<Q>,
|
||||
Q: Hash + Eq
|
||||
```
|
||||
|
||||
[hashmap]: ../std/collections/struct.HashMap.html
|
||||
[get]: ../std/collections/struct.HashMap.html#method.get
|
||||
|
||||
This signature is pretty complicated. The `K` parameter is what we’re interested
|
||||
in here. It refers to a parameter of the `HashMap` itself:
|
||||
|
||||
```rust,ignore
|
||||
struct HashMap<K, V, S = RandomState> {
|
||||
```
|
||||
|
||||
The `K` parameter is the type of _key_ the `HashMap` uses. So, looking at
|
||||
the signature of `get()` again, we can use `get()` when the key implements
|
||||
`Borrow<Q>`. That way, we can make a `HashMap` which uses `String` keys,
|
||||
but use `&str`s when we’re searching:
|
||||
|
||||
```rust
|
||||
use std::collections::HashMap;
|
||||
|
||||
let mut map = HashMap::new();
|
||||
map.insert("Foo".to_string(), 42);
|
||||
|
||||
assert_eq!(map.get("Foo"), Some(&42));
|
||||
```
|
||||
|
||||
This is because the standard library has `impl Borrow<str> for String`.
|
||||
|
||||
For most types, when you want to take an owned or borrowed type, a `&T` is
|
||||
enough. But one area where `Borrow` is effective is when there’s more than one
|
||||
kind of borrowed value. Slices are an area where this is especially true: you
|
||||
can have both an `&[T]` or a `&mut [T]`. If we wanted to accept both of these
|
||||
types, `Borrow` is up for it:
|
||||
|
||||
```
|
||||
use std::borrow::Borrow;
|
||||
use std::fmt::Display;
|
||||
|
||||
fn foo<T: Borrow<i32> + Display>(a: T) {
|
||||
println!("a is borrowed: {}", a);
|
||||
}
|
||||
|
||||
let mut i = 5;
|
||||
|
||||
foo(&i);
|
||||
foo(&mut i);
|
||||
```
|
||||
|
||||
This will print out `a is borrowed: 5` twice.
|
||||
|
||||
# AsRef
|
||||
|
||||
The `AsRef` trait is a conversion trait. It’s used for converting some value to
|
||||
a reference in generic code. Like this:
|
||||
|
||||
```rust
|
||||
let s = "Hello".to_string();
|
||||
|
||||
fn foo<T: AsRef<str>>(s: T) {
|
||||
let slice = s.as_ref();
|
||||
}
|
||||
```
|
||||
|
||||
# Which should I use?
|
||||
|
||||
We can see how they’re kind of the same: they both deal with owned and borrowed
|
||||
versions of some type. However, they’re a bit different.
|
||||
|
||||
Choose `Borrow` when you want to abstract over different kinds of borrowing, or
|
||||
when you’re building a datastructure that treats owned and borrowed values in
|
||||
equivalent ways, such as hashing and comparison.
|
||||
|
||||
Choose `AsRef` when you want to convert something to a reference directly, and
|
||||
you’re writing generic code.
|
|
@ -5,7 +5,7 @@ Rust’s most unique and compelling features, with which Rust developers should
|
|||
become quite acquainted. Ownership is how Rust achieves its largest goal,
|
||||
memory safety. There are a few distinct concepts, each with its own chapter:
|
||||
|
||||
* [ownership][ownership], ownership, the key concept
|
||||
* [ownership][ownership], the key concept
|
||||
* [borrowing][borrowing], and their associated feature ‘references’
|
||||
* lifetimes, which you’re reading now
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ become quite acquainted. Ownership is how Rust achieves its largest goal,
|
|||
memory safety. There are a few distinct concepts, each with its own
|
||||
chapter:
|
||||
|
||||
* ownership, which you’re reading now.
|
||||
* ownership, which you’re reading now
|
||||
* [borrowing][borrowing], and their associated feature ‘references’
|
||||
* [lifetimes][lifetimes], an advanced concept of borrowing
|
||||
|
||||
|
@ -23,7 +23,7 @@ Before we get to the details, two important notes about the ownership system.
|
|||
Rust has a focus on safety and speed. It accomplishes these goals through many
|
||||
‘zero-cost abstractions’, which means that in Rust, abstractions cost as little
|
||||
as possible in order to make them work. The ownership system is a prime example
|
||||
of a zero cost abstraction. All of the analysis we’ll talk about in this guide
|
||||
of a zero-cost abstraction. All of the analysis we’ll talk about in this guide
|
||||
is _done at compile time_. You do not pay any run-time cost for any of these
|
||||
features.
|
||||
|
||||
|
@ -41,7 +41,7 @@ With that in mind, let’s learn about ownership.
|
|||
|
||||
# Ownership
|
||||
|
||||
[`Variable bindings`][bindings] have a property in Rust: they ‘have ownership’
|
||||
[Variable bindings][bindings] have a property in Rust: they ‘have ownership’
|
||||
of what they’re bound to. This means that when a binding goes out of scope, the
|
||||
resource that they’re bound to are freed. For example:
|
||||
|
||||
|
@ -106,8 +106,8 @@ take(v);
|
|||
println!("v[0] is: {}", v[0]);
|
||||
```
|
||||
|
||||
Same error: “use of moved value.” When we transfer ownership to something else,
|
||||
we say that we’ve ‘moved’ the thing we refer to. You don’t need some sort of
|
||||
Same error: ‘use of moved value’. When we transfer ownership to something else,
|
||||
we say that we’ve ‘moved’ the thing we refer to. You don’t need any sort of
|
||||
special annotation here, it’s the default thing that Rust does.
|
||||
|
||||
## The details
|
||||
|
@ -121,19 +121,19 @@ let v = vec![1, 2, 3];
|
|||
let v2 = v;
|
||||
```
|
||||
|
||||
The first line creates some data for the vector on the [stack][sh], `v`. The
|
||||
vector’s data, however, is stored on the [heap][sh], and so it contains a
|
||||
pointer to that data. When we move `v` to `v2`, it creates a copy of that pointer,
|
||||
for `v2`. Which would mean two pointers to the contents of the vector on the
|
||||
heap. That would be a problem: it would violate Rust’s safety guarantees by
|
||||
introducing a data race. Therefore, Rust forbids using `v` after we’ve done the
|
||||
move.
|
||||
The first line allocates memory for the vector object, `v`, and for the data it
|
||||
contains. The vector object is stored on the [stack][sh] and contains a pointer
|
||||
to the content (`[1, 2, 3]`) stored on the [heap][sh]. When we move `v` to `v2`,
|
||||
it creates a copy of that pointer, for `v2`. Which means that there would be two
|
||||
pointers to the content of the vector on the heap. It would violate Rust’s
|
||||
safety guarantees by introducing a data race. Therefore, Rust forbids using `v`
|
||||
after we’ve done the move.
|
||||
|
||||
[sh]: the-stack-and-the-heap.html
|
||||
|
||||
It’s also important to note that optimizations may remove the actual copy of
|
||||
the bytes, depending on circumstances. So it may not be as inefficient as it
|
||||
initially seems.
|
||||
the bytes on the stack, depending on circumstances. So it may not be as
|
||||
inefficient as it initially seems.
|
||||
|
||||
## `Copy` types
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ let x = true;
|
|||
let y: bool = false;
|
||||
```
|
||||
|
||||
A common use of booleans is in [`if` statements][if].
|
||||
A common use of booleans is in [`if` conditionals][if].
|
||||
|
||||
[if]: if.html
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
% while loops
|
||||
% while Loops
|
||||
|
||||
Rust also has a `while` loop. It looks like this:
|
||||
|
||||
|
|
|
@ -37,6 +37,11 @@ use self::Cow::*;
|
|||
/// trait: if `T: Borrow<U>`, then `&U` can be borrowed from `&T`. A given
|
||||
/// type can be borrowed as multiple different types. In particular, `Vec<T>:
|
||||
/// Borrow<Vec<T>>` and `Vec<T>: Borrow<[T]>`.
|
||||
///
|
||||
/// `Borrow` is very similar to, but different than, `AsRef`. See
|
||||
/// [the book][book] for more.
|
||||
///
|
||||
/// [book]: ../../book/borrow-and-asref.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait Borrow<Borrowed: ?Sized> {
|
||||
/// Immutably borrows from an owned value.
|
||||
|
|
|
@ -24,6 +24,11 @@ use marker::Sized;
|
|||
|
||||
/// A cheap, reference-to-reference conversion.
|
||||
///
|
||||
/// `AsRef` is very similar to, but different than, `Borrow`. See
|
||||
/// [the book][book] for more.
|
||||
///
|
||||
/// [book]: ../../book/borrow-and-asref.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Both `String` and `&str` implement `AsRef<str>`:
|
||||
|
|
|
@ -5722,6 +5722,9 @@ pub mod funcs {
|
|||
pub fn tcgetpgrp(fd: c_int) -> pid_t;
|
||||
pub fn ttyname(fd: c_int) -> *mut c_char;
|
||||
pub fn unlink(c: *const c_char) -> c_int;
|
||||
pub fn wait(status: *const c_int) -> pid_t;
|
||||
pub fn waitpid(pid: pid_t, status: *const c_int, options: c_int)
|
||||
-> pid_t;
|
||||
pub fn write(fd: c_int, buf: *const c_void, count: size_t)
|
||||
-> ssize_t;
|
||||
pub fn pread(fd: c_int, buf: *mut c_void, count: size_t,
|
||||
|
@ -5773,6 +5776,9 @@ pub mod funcs {
|
|||
pub fn sysconf(name: c_int) -> c_long;
|
||||
pub fn ttyname(fd: c_int) -> *mut c_char;
|
||||
pub fn unlink(c: *const c_char) -> c_int;
|
||||
pub fn wait(status: *const c_int) -> pid_t;
|
||||
pub fn waitpid(pid: pid_t, status: *const c_int, options: c_int)
|
||||
-> pid_t;
|
||||
pub fn write(fd: c_int, buf: *const c_void, count: size_t)
|
||||
-> ssize_t;
|
||||
pub fn pread(fd: c_int, buf: *mut c_void, count: size_t,
|
||||
|
|
|
@ -273,8 +273,8 @@ See also http://doc.rust-lang.org/book/unsafe.html
|
|||
|
||||
E0137: r##"
|
||||
This error indicates that the compiler found multiple functions with the
|
||||
#[main] attribute. This is an error because there must be a unique entry point
|
||||
into a Rust program.
|
||||
`#[main]` attribute. This is an error because there must be a unique entry
|
||||
point into a Rust program.
|
||||
"##,
|
||||
|
||||
E0152: r##"
|
||||
|
|
|
@ -10,8 +10,111 @@
|
|||
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
// Error messages for EXXXX errors.
|
||||
// Each message should start and end with a new line, and be wrapped to 80 characters.
|
||||
// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
|
||||
register_long_diagnostics! {
|
||||
|
||||
E0154: r##"
|
||||
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
|
||||
let x = 0;
|
||||
use std::io::Read;
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
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;
|
||||
let x = 0;
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
See the Declaration Statements section of the reference for more information
|
||||
about what constitutes an Item declaration and what does not:
|
||||
|
||||
http://doc.rust-lang.org/reference.html#statements
|
||||
"##,
|
||||
|
||||
E0259: r##"
|
||||
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;
|
||||
```
|
||||
|
||||
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;
|
||||
```
|
||||
"##,
|
||||
|
||||
E0260: r##"
|
||||
The name for an item declaration conflicts with an external crate's name.
|
||||
|
||||
For instance,
|
||||
```
|
||||
extern crate abc;
|
||||
|
||||
struct abc;
|
||||
```
|
||||
|
||||
There are two possible solutions:
|
||||
|
||||
Solution #1: Rename the item.
|
||||
|
||||
```
|
||||
extern crate abc;
|
||||
|
||||
struct xyz;
|
||||
```
|
||||
|
||||
Solution #2: Import the crate with a different name.
|
||||
|
||||
```
|
||||
extern crate abc as xyz;
|
||||
|
||||
struct abc;
|
||||
```
|
||||
|
||||
See the Declaration Statements section of the reference for more information
|
||||
about what constitutes an Item declaration and what does not:
|
||||
|
||||
http://doc.rust-lang.org/reference.html#statements
|
||||
"##,
|
||||
|
||||
E0317: r##"
|
||||
User-defined types or type parameters cannot shadow the primitive types.
|
||||
This error indicates you tried to define a type, struct or enum with the same
|
||||
name as an existing primitive type.
|
||||
|
||||
See the Types section of the reference for more information about the primitive
|
||||
types:
|
||||
|
||||
http://doc.rust-lang.org/reference.html#types
|
||||
"##
|
||||
|
||||
}
|
||||
|
||||
register_diagnostics! {
|
||||
E0154,
|
||||
E0157,
|
||||
E0153,
|
||||
E0251, // a named type or value has already been imported in this module
|
||||
|
@ -22,9 +125,6 @@ register_diagnostics! {
|
|||
E0256, // import conflicts with type in this module
|
||||
E0257, // inherent implementations are only allowed on types defined in the current module
|
||||
E0258, // import conflicts with existing submodule
|
||||
E0259, // an extern crate has already been imported into this module
|
||||
E0260, // name conflicts with an external crate that has been imported into this module
|
||||
E0317, // user-defined types or type parameters cannot shadow the primitive types
|
||||
E0364, // item is private
|
||||
E0365 // item is private
|
||||
}
|
||||
|
|
|
@ -186,7 +186,7 @@ struct Foo<'a> {
|
|||
```
|
||||
|
||||
This fails because `&mut T` is not `Copy`, even when `T` is `Copy` (this
|
||||
differs from the behavior for `&T`, which is `Copy` when `T` is `Copy`).
|
||||
differs from the behavior for `&T`, which is always `Copy`).
|
||||
"##,
|
||||
|
||||
E0205: r##"
|
||||
|
@ -216,7 +216,7 @@ enum Foo<'a> {
|
|||
```
|
||||
|
||||
This fails because `&mut T` is not `Copy`, even when `T` is `Copy` (this
|
||||
differs from the behavior for `&T`, which is `Copy` when `T` is `Copy`).
|
||||
differs from the behavior for `&T`, which is always `Copy`).
|
||||
"##,
|
||||
|
||||
E0206: r##"
|
||||
|
|
25
src/test/compile-fail/issue-20413.rs
Normal file
25
src/test/compile-fail/issue-20413.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
trait Foo {
|
||||
fn answer(self);
|
||||
}
|
||||
|
||||
struct NoData<T>;
|
||||
//~^ ERROR: parameter `T` is never used
|
||||
|
||||
impl<T> Foo for T where NoData<T>: Foo {
|
||||
//~^ ERROR: overflow evaluating the requirement
|
||||
fn answer(self) {
|
||||
let val: NoData<T> = NoData;
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
16
src/test/run-pass/issue-18075.rs
Normal file
16
src/test/run-pass/issue-18075.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// exec-env:RUST_LOG=rustc::middle=debug
|
||||
|
||||
fn main() {
|
||||
let b = 1isize;
|
||||
println!("{}", b);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue