Skip to content

Commit

Permalink
Auto merge of #29648 - steveklabnik:rollup, r=steveklabnik
Browse files Browse the repository at this point in the history
- Successful merges: #29609, #29611, #29613, #29614, #29619, #29624, #29630
- Failed merges:
  • Loading branch information
bors committed Nov 5, 2015
2 parents 96c95f1 + 1036d64 commit 1dac3ad
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 213 deletions.
17 changes: 14 additions & 3 deletions src/doc/reference.md
Expand Up @@ -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.

Expand Down
156 changes: 3 additions & 153 deletions src/doc/trpl/README.md
Expand Up @@ -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.
76 changes: 27 additions & 49 deletions src/doc/trpl/guessing-game.md
Expand Up @@ -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);
Expand Down Expand Up @@ -189,7 +188,6 @@ Let’s move forward:

```rust,ignore
io::stdin().read_line(&mut guess)
.ok()
.expect("Failed to read line");
```

Expand Down Expand Up @@ -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");
```

Expand All @@ -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.

[ok]: ../std/result/enum.Result.html#method.ok
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.

[expect]: ../std/option/enum.Option.html#method.expect
[panic]: error-handling.html

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -689,7 +676,6 @@ The new three lines:
```rust,ignore
let guess: u32 = guess.trim().parse()
.ok()
.expect("Please type a number!");
```
Expand All @@ -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!
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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() {
Expand Down
4 changes: 0 additions & 4 deletions src/libcollections/vec.rs
Expand Up @@ -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.
Expand Down

0 comments on commit 1dac3ad

Please sign in to comment.