Auto merge of #29648 - steveklabnik:rollup, r=steveklabnik
- Successful merges: #29609, #29611, #29613, #29614, #29619, #29624, #29630 - Failed merges:
This commit is contained in:
commit
1dac3adc34
|
@ -547,9 +547,20 @@ a `$` literally, including delimiters. For parsing reasons, delimiters must be
|
|||
balanced, but they are otherwise not special.
|
||||
|
||||
In the matcher, `$` _name_ `:` _designator_ matches the nonterminal in the Rust
|
||||
syntax named by _designator_. Valid designators are `item`, `block`, `stmt`,
|
||||
`pat`, `expr`, `ty` (type), `ident`, `path`, `tt` (either side of the `=>`
|
||||
in macro rules), and `meta` (contents of an attribute). In the transcriber, the
|
||||
syntax named by _designator_. Valid designators are:
|
||||
|
||||
* `item`: an [item](#items)
|
||||
* `block`: a [block](#block-expressions)
|
||||
* `stmt`: a [statement](#statements)
|
||||
* `pat`: a [pattern](#match-expressions)
|
||||
* `expr`: an [expression](#expressions)
|
||||
* `ty`: a [type](#types)
|
||||
* `ident`: an [identifier](#identifiers)
|
||||
* `path`: a [path](#paths)
|
||||
* `tt`: either side of the `=>` in macro rules
|
||||
* `meta`: the contents of an [attribute](#attributes)
|
||||
|
||||
In the transcriber, the
|
||||
designator is already known, and so only the name of a matched nonterminal comes
|
||||
after the dollar sign.
|
||||
|
||||
|
|
|
@ -41,158 +41,8 @@ Copious cross-linking connects these parts together.
|
|||
|
||||
### Contributing
|
||||
|
||||
The source files from which this book is generated can be found on GitHub:
|
||||
[github.com/rust-lang/rust/tree/master/src/doc/trpl](https://github.com/rust-lang/rust/tree/master/src/doc/trpl)
|
||||
The source files from which this book is generated can be found on
|
||||
[GitHub][trpl].
|
||||
|
||||
## A brief introduction to Rust
|
||||
[trpl]: https://github.com/rust-lang/rust/tree/master/src/doc/trpl
|
||||
|
||||
Is Rust a language you might be interested in? Let’s examine a few small code
|
||||
samples to show off a few of its strengths.
|
||||
|
||||
The main concept that makes Rust unique is called ‘ownership’. Consider this
|
||||
small example:
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
let mut x = vec!["Hello", "world"];
|
||||
}
|
||||
```
|
||||
|
||||
This program makes a [variable binding][var] named `x`. The value of this
|
||||
binding is a `Vec<T>`, a ‘vector’, that we create through a [macro][macro]
|
||||
defined in the standard library. This macro is called `vec`, and we invoke
|
||||
macros with a `!`. This follows a general principle of Rust: make things
|
||||
explicit. Macros can do significantly more complicated things than function
|
||||
calls, and so they’re visually distinct. The `!` also helps with parsing,
|
||||
making tooling easier to write, which is also important.
|
||||
|
||||
We used `mut` to make `x` mutable: bindings are immutable by default in Rust.
|
||||
We’ll be mutating this vector later in the example.
|
||||
|
||||
It’s also worth noting that we didn’t need a type annotation here: while Rust
|
||||
is statically typed, we didn’t need to explicitly annotate the type. Rust has
|
||||
type inference to balance out the power of static typing with the verbosity of
|
||||
annotating types.
|
||||
|
||||
Rust prefers stack allocation to heap allocation: `x` is placed directly on the
|
||||
stack. However, the `Vec<T>` type allocates space for the elements of the vector
|
||||
on the heap. If you’re not familiar with this distinction, you can ignore it for
|
||||
now, or check out [‘The Stack and the Heap’][heap]. As a systems programming
|
||||
language, Rust gives us the ability to control how our memory is allocated, but
|
||||
when we’re getting started, it’s less of a big deal.
|
||||
|
||||
[var]: variable-bindings.html
|
||||
[macro]: macros.html
|
||||
[heap]: the-stack-and-the-heap.html
|
||||
|
||||
Earlier, we mentioned that ‘ownership’ is the key new concept in Rust. In Rust
|
||||
parlance, `x` is said to ‘own’ the vector. This means that when `x` goes out of
|
||||
scope, the vector’s memory will be de-allocated. This is done deterministically
|
||||
by the Rust compiler, rather than through a mechanism such as a garbage
|
||||
collector. In other words, in Rust, we don’t call functions like `malloc` and
|
||||
`free` ourselves: the compiler statically determines when we need to allocate or
|
||||
deallocate memory, and inserts those calls itself. To err is to be human, but
|
||||
compilers never forget.
|
||||
|
||||
Let’s add another line to our example:
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
let mut x = vec!["Hello", "world"];
|
||||
|
||||
let y = &x[0];
|
||||
}
|
||||
```
|
||||
|
||||
We’ve introduced another binding, `y`. In this case, `y` is a ‘reference’ to the
|
||||
first element of the vector. Rust’s references are similar to pointers in other
|
||||
languages, but with additional compile-time safety checks. References interact
|
||||
with the ownership system by [‘borrowing’][borrowing] what they point to, rather
|
||||
than owning it. The difference is, when the reference goes out of scope, it
|
||||
won't deallocate the underlying memory. If it did, we’d de-allocate twice, which
|
||||
is bad!
|
||||
|
||||
[borrowing]: references-and-borrowing.html
|
||||
|
||||
Let’s add a third line. It looks innocent enough, but causes a compiler error:
|
||||
|
||||
```rust,ignore
|
||||
fn main() {
|
||||
let mut x = vec!["Hello", "world"];
|
||||
|
||||
let y = &x[0];
|
||||
|
||||
x.push("foo");
|
||||
}
|
||||
```
|
||||
|
||||
`push` is a method on vectors that appends another element to the end of the
|
||||
vector. When we try to compile this program, we get an error:
|
||||
|
||||
```text
|
||||
error: cannot borrow `x` as mutable because it is also borrowed as immutable
|
||||
x.push("foo");
|
||||
^
|
||||
note: previous borrow of `x` occurs here; the immutable borrow prevents
|
||||
subsequent moves or mutable borrows of `x` until the borrow ends
|
||||
let y = &x[0];
|
||||
^
|
||||
note: previous borrow ends here
|
||||
fn main() {
|
||||
|
||||
}
|
||||
^
|
||||
```
|
||||
|
||||
Whew! The Rust compiler gives quite detailed errors at times, and this is one
|
||||
of those times. As the error explains, while we made our binding mutable, we
|
||||
still can't call `push`. This is because we already have a reference to an
|
||||
element of the vector, `y`. Mutating something while another reference exists
|
||||
is dangerous, because we may invalidate the reference. In this specific case,
|
||||
when we create the vector, we may have only allocated space for two elements.
|
||||
Adding a third would mean allocating a new chunk of memory for all those elements,
|
||||
copying the old values over, and updating the internal pointer to that memory.
|
||||
That all works just fine. The problem is that `y` wouldn’t get updated, and so
|
||||
we’d have a ‘dangling pointer’. That’s bad. Any use of `y` would be an error in
|
||||
this case, and so the compiler has caught this for us.
|
||||
|
||||
So how do we solve this problem? There are two approaches we can take. The first
|
||||
is making a copy rather than using a reference:
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
let mut x = vec!["Hello", "world"];
|
||||
|
||||
let y = x[0].clone();
|
||||
|
||||
x.push("foo");
|
||||
}
|
||||
```
|
||||
|
||||
Rust has [move semantics][move] by default, so if we want to make a copy of some
|
||||
data, we call the `clone()` method. In this example, `y` is no longer a reference
|
||||
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]: 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:
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
let mut x = vec!["Hello", "world"];
|
||||
|
||||
{
|
||||
let y = &x[0];
|
||||
}
|
||||
|
||||
x.push("foo");
|
||||
}
|
||||
```
|
||||
|
||||
We created an inner scope with an additional set of curly braces. `y` will go out of
|
||||
scope before we call `push()`, and so we’re all good.
|
||||
|
||||
This concept of ownership isn’t just good for preventing dangling pointers, but an
|
||||
entire set of related problems, like iterator invalidation, concurrency, and more.
|
||||
|
|
|
@ -83,7 +83,6 @@ fn main() {
|
|||
let mut guess = String::new();
|
||||
|
||||
io::stdin().read_line(&mut guess)
|
||||
.ok()
|
||||
.expect("Failed to read line");
|
||||
|
||||
println!("You guessed: {}", guess);
|
||||
|
@ -189,7 +188,6 @@ Let’s move forward:
|
|||
|
||||
```rust,ignore
|
||||
io::stdin().read_line(&mut guess)
|
||||
.ok()
|
||||
.expect("Failed to read line");
|
||||
```
|
||||
|
||||
|
@ -245,7 +243,6 @@ a single line of text, it’s only the first part of the single logical line of
|
|||
code:
|
||||
|
||||
```rust,ignore
|
||||
.ok()
|
||||
.expect("Failed to read line");
|
||||
```
|
||||
|
||||
|
@ -254,33 +251,27 @@ and other whitespace. This helps you split up long lines. We _could_ have
|
|||
done:
|
||||
|
||||
```rust,ignore
|
||||
io::stdin().read_line(&mut guess).ok().expect("failed to read line");
|
||||
io::stdin().read_line(&mut guess).expect("failed to read line");
|
||||
```
|
||||
|
||||
But that gets hard to read. So we’ve split it up, three lines for three
|
||||
method calls. We already talked about `read_line()`, but what about `ok()`
|
||||
and `expect()`? Well, we already mentioned that `read_line()` puts what
|
||||
the user types into the `&mut String` we pass it. But it also returns
|
||||
a value: in this case, an [`io::Result`][ioresult]. Rust has a number of
|
||||
types named `Result` in its standard library: a generic [`Result`][result],
|
||||
and then specific versions for sub-libraries, like `io::Result`.
|
||||
But that gets hard to read. So we’ve split it up, three lines for three method
|
||||
calls. We already talked about `read_line()`, but what about `expect()`? Well,
|
||||
we already mentioned that `read_line()` puts what the user types into the `&mut
|
||||
String` we pass it. But it also returns a value: in this case, an
|
||||
[`io::Result`][ioresult]. Rust has a number of types named `Result` in its
|
||||
standard library: a generic [`Result`][result], and then specific versions for
|
||||
sub-libraries, like `io::Result`.
|
||||
|
||||
[ioresult]: ../std/io/type.Result.html
|
||||
[result]: ../std/result/enum.Result.html
|
||||
|
||||
The purpose of these `Result` types is to encode error handling information.
|
||||
Values of the `Result` type, like any type, have methods defined on them. In
|
||||
this case, `io::Result` has an `ok()` method, which says ‘we want to assume
|
||||
this value is a successful one. If not, just throw away the error
|
||||
information’. Why throw it away? Well, for a basic program, we just want to
|
||||
print a generic error, as basically any issue means we can’t continue. The
|
||||
[`ok()` method][ok] returns a value which has another method defined on it:
|
||||
`expect()`. The [`expect()` method][expect] takes a value it’s called on, and
|
||||
if it isn’t a successful one, [`panic!`][panic]s with a message you
|
||||
passed it. A `panic!` like this will cause our program to crash, displaying
|
||||
the message.
|
||||
this case, `io::Result` has an [`expect()` method][expect] that takes a value
|
||||
it’s called on, and if it isn’t a successful one, [`panic!`][panic]s with a
|
||||
message you passed it. A `panic!` like this will cause our program to crash,
|
||||
displaying the message.
|
||||
|
||||
[ok]: ../std/result/enum.Result.html#method.ok
|
||||
[expect]: ../std/option/enum.Option.html#method.expect
|
||||
[panic]: error-handling.html
|
||||
|
||||
|
@ -468,7 +459,6 @@ fn main() {
|
|||
let mut guess = String::new();
|
||||
|
||||
io::stdin().read_line(&mut guess)
|
||||
.ok()
|
||||
.expect("failed to read line");
|
||||
|
||||
println!("You guessed: {}", guess);
|
||||
|
@ -557,7 +547,6 @@ fn main() {
|
|||
let mut guess = String::new();
|
||||
|
||||
io::stdin().read_line(&mut guess)
|
||||
.ok()
|
||||
.expect("failed to read line");
|
||||
|
||||
println!("You guessed: {}", guess);
|
||||
|
@ -668,11 +657,9 @@ fn main() {
|
|||
let mut guess = String::new();
|
||||
|
||||
io::stdin().read_line(&mut guess)
|
||||
.ok()
|
||||
.expect("failed to read line");
|
||||
|
||||
let guess: u32 = guess.trim().parse()
|
||||
.ok()
|
||||
.expect("Please type a number!");
|
||||
|
||||
println!("You guessed: {}", guess);
|
||||
|
@ -689,7 +676,6 @@ The new three lines:
|
|||
|
||||
```rust,ignore
|
||||
let guess: u32 = guess.trim().parse()
|
||||
.ok()
|
||||
.expect("Please type a number!");
|
||||
```
|
||||
|
||||
|
@ -706,27 +692,26 @@ We bind `guess` to an expression that looks like something we wrote earlier:
|
|||
guess.trim().parse()
|
||||
```
|
||||
|
||||
Followed by an `ok().expect()` invocation. Here, `guess` refers to the old
|
||||
`guess`, the one that was a `String` with our input in it. The `trim()`
|
||||
method on `String`s will eliminate any white space at the beginning and end of
|
||||
our string. This is important, as we had to press the ‘return’ key to satisfy
|
||||
`read_line()`. This means that if we type `5` and hit return, `guess` looks
|
||||
like this: `5\n`. The `\n` represents ‘newline’, the enter key. `trim()` gets
|
||||
rid of this, leaving our string with just the `5`. The [`parse()` method on
|
||||
strings][parse] parses a string into some kind of number. Since it can parse a
|
||||
variety of numbers, we need to give Rust a hint as to the exact type of number
|
||||
we want. Hence, `let guess: u32`. The colon (`:`) after `guess` tells Rust
|
||||
we’re going to annotate its type. `u32` is an unsigned, thirty-two bit
|
||||
integer. Rust has [a number of built-in number types][number], but we’ve
|
||||
chosen `u32`. It’s a good default choice for a small positive number.
|
||||
Here, `guess` refers to the old `guess`, the one that was a `String` with our
|
||||
input in it. The `trim()` method on `String`s will eliminate any white space at
|
||||
the beginning and end of our string. This is important, as we had to press the
|
||||
‘return’ key to satisfy `read_line()`. This means that if we type `5` and hit
|
||||
return, `guess` looks like this: `5\n`. The `\n` represents ‘newline’, the
|
||||
enter key. `trim()` gets rid of this, leaving our string with just the `5`. The
|
||||
[`parse()` method on strings][parse] parses a string into some kind of number.
|
||||
Since it can parse a variety of numbers, we need to give Rust a hint as to the
|
||||
exact type of number we want. Hence, `let guess: u32`. The colon (`:`) after
|
||||
`guess` tells Rust we’re going to annotate its type. `u32` is an unsigned,
|
||||
thirty-two bit integer. Rust has [a number of built-in number types][number],
|
||||
but we’ve chosen `u32`. It’s a good default choice for a small positive number.
|
||||
|
||||
[parse]: ../std/primitive.str.html#method.parse
|
||||
[number]: primitive-types.html#numeric-types
|
||||
|
||||
Just like `read_line()`, our call to `parse()` could cause an error. What if
|
||||
our string contained `A👍%`? There’d be no way to convert that to a number. As
|
||||
such, we’ll do the same thing we did with `read_line()`: use the `ok()` and
|
||||
`expect()` methods to crash if there’s an error.
|
||||
such, we’ll do the same thing we did with `read_line()`: use the `expect()`
|
||||
method to crash if there’s an error.
|
||||
|
||||
Let’s try our program out!
|
||||
|
||||
|
@ -773,11 +758,9 @@ fn main() {
|
|||
let mut guess = String::new();
|
||||
|
||||
io::stdin().read_line(&mut guess)
|
||||
.ok()
|
||||
.expect("failed to read line");
|
||||
|
||||
let guess: u32 = guess.trim().parse()
|
||||
.ok()
|
||||
.expect("Please type a number!");
|
||||
|
||||
println!("You guessed: {}", guess);
|
||||
|
@ -841,11 +824,9 @@ fn main() {
|
|||
let mut guess = String::new();
|
||||
|
||||
io::stdin().read_line(&mut guess)
|
||||
.ok()
|
||||
.expect("failed to read line");
|
||||
|
||||
let guess: u32 = guess.trim().parse()
|
||||
.ok()
|
||||
.expect("Please type a number!");
|
||||
|
||||
println!("You guessed: {}", guess);
|
||||
|
@ -888,7 +869,6 @@ fn main() {
|
|||
let mut guess = String::new();
|
||||
|
||||
io::stdin().read_line(&mut guess)
|
||||
.ok()
|
||||
.expect("failed to read line");
|
||||
|
||||
let guess: u32 = match guess.trim().parse() {
|
||||
|
@ -920,7 +900,6 @@ let guess: u32 = match guess.trim().parse() {
|
|||
```
|
||||
|
||||
This is how you generally move from ‘crash on error’ to ‘actually handle the
|
||||
error’, by switching from `ok().expect()` to a `match` statement. The `Result`
|
||||
returned by `parse()` is an `enum` just like `Ordering`, but in this case, each
|
||||
variant has some data associated with it: `Ok` is a success, and `Err` is a
|
||||
failure. Each contains more information: the successfully parsed integer, or an
|
||||
|
@ -977,7 +956,6 @@ fn main() {
|
|||
let mut guess = String::new();
|
||||
|
||||
io::stdin().read_line(&mut guess)
|
||||
.ok()
|
||||
.expect("failed to read line");
|
||||
|
||||
let guess: u32 = match guess.trim().parse() {
|
||||
|
|
|
@ -1384,10 +1384,6 @@ impl<T: Ord> Ord for Vec<T> {
|
|||
impl<T> Drop for Vec<T> {
|
||||
#[unsafe_destructor_blind_to_params]
|
||||
fn drop(&mut self) {
|
||||
// NOTE: this is currently abusing the fact that ZSTs can't impl Drop.
|
||||
// Or rather, that impl'ing Drop makes them not zero-sized. This is
|
||||
// OK because exactly when this stops being a valid assumption, we
|
||||
// don't need unsafe_no_drop_flag shenanigans anymore.
|
||||
if self.buf.unsafe_no_drop_flag_needs_drop() {
|
||||
unsafe {
|
||||
// The branch on needs_drop() is an -O1 performance optimization.
|
||||
|
|
|
@ -23,7 +23,7 @@ use option::Option;
|
|||
use hash::Hash;
|
||||
use hash::Hasher;
|
||||
|
||||
/// Types able to be transferred across thread boundaries.
|
||||
/// Types that can be transferred across thread boundaries.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[lang = "send"]
|
||||
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
|
||||
|
@ -382,7 +382,7 @@ mod impls {
|
|||
unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {}
|
||||
}
|
||||
|
||||
/// A marker trait indicates a type that can be reflected over.
|
||||
/// Types that can be reflected over.
|
||||
///
|
||||
/// This trait is implemented for all types. Its purpose is to ensure
|
||||
/// that when you write a generic function that will employ
|
||||
|
|
|
@ -101,6 +101,10 @@
|
|||
if (document.activeElement.tagName == "INPUT")
|
||||
return;
|
||||
|
||||
// Don't interfere with browser shortcuts
|
||||
if (ev.ctrlKey || ev.altKey || ev.metaKey)
|
||||
return;
|
||||
|
||||
switch (getVirtualKey(ev)) {
|
||||
case "Escape":
|
||||
if (!$("#help").hasClass("hidden")) {
|
||||
|
|
|
@ -76,7 +76,7 @@
|
|||
//! `i32`](primitive.i32.html) that lists all the methods that can be called on
|
||||
//! 32-bit integers (very useful), and there is a [page for the module
|
||||
//! `std::i32`](i32/index.html) that documents the constant values [`MIN`] and
|
||||
//! [`MAX`] (rarely useful).
|
||||
//! [`MAX`](i32/constant.MAX.html) (rarely useful).
|
||||
//!
|
||||
//! Note the documentation for the primitives [`str`] and [`[T]`][slice] (also
|
||||
//! called 'slice'). Many method calls on [`String`] and [`Vec<T>`] are actually
|
||||
|
@ -153,7 +153,6 @@
|
|||
//!
|
||||
//! [I/O]: io/index.html
|
||||
//! [MIN]: i32/constant.MIN.html
|
||||
//! [MAX]: i32/constant.MAX.html
|
||||
//! [TCP]: net/struct.TcpStream.html
|
||||
//! [The Rust Prelude]: prelude/index.html
|
||||
//! [UDP]: net/struct.UdpSocket.html
|
||||
|
|
Loading…
Reference in New Issue