Auto merge of #24195 - steveklabnik:rollup, r=steveklabnik

- Successful merges: #24143, #24149, #24167, #24178
- Failed merges:
This commit is contained in:
bors 2015-04-08 15:59:10 +00:00
commit 30e7e6e8b0
52 changed files with 974 additions and 2036 deletions

View File

@ -163,13 +163,17 @@ This is to make the language easier to parse for humans, especially in the face
of higher-order functions. `fn foo<T>(f: fn(int): int, fn(T): U): U` is not
particularly easy to read.
## `let` is used to introduce variables
## Why is `let` used to introduce variables?
`let` not only defines variables, but can do pattern matching. One can also
redeclare immutable variables with `let`. This is useful to avoid unnecessary
`mut` annotations. An interesting historical note is that Rust comes,
syntactically, most closely from ML, which also uses `let` to introduce
bindings.
We don't use the term "variable", instead, we use "variable bindings". The
simplest way for binding is the `let` syntax, other ways including `if let`,
`while let` and `match`. Bindings also exist in function arguments positions.
Bindings always happen in pattern matching positions, and it's also Rust's way
to declare mutability. One can also redeclare mutability of a binding in
pattern matching. This is useful to avoid unnecessary `mut` annotations. An
interesting historical note is that Rust comes, syntactically, most closely
from ML, which also uses `let` to introduce bindings.
See also [a long thread][alt] on renaming `let mut` to `var`.

View File

@ -1,42 +1,64 @@
# Summary
* [The Basics](basic.md)
* [Getting Started](getting-started.md)
* [Installing Rust](installing-rust.md)
* [Hello, world!](hello-world.md)
* [Hello, Cargo!](hello-cargo.md)
* [Variable Bindings](variable-bindings.md)
* [If](if.md)
* [Functions](functions.md)
* [Comments](comments.md)
* [Compound Data Types](compound-data-types.md)
* [Match](match.md)
* [Looping](looping.md)
* [Strings](strings.md)
* [Arrays, Vectors, and Slices](arrays-vectors-and-slices.md)
* [Intermediate Rust](intermediate.md)
* [Crates and Modules](crates-and-modules.md)
* [Learn Rust](learn-rust.md)
* [Effective Rust](effective-rust.md)
* [The Stack and the Heap](the-stack-and-the-heap.md)
* [`Debug` and `Display`](debug-and-display.md)
* [Testing](testing.md)
* [Pointers](pointers.md)
* [Ownership](ownership.md)
* [More Strings](more-strings.md)
* [Patterns](patterns.md)
* [Method Syntax](method-syntax.md)
* [Associated Types](associated-types.md)
* [Closures](closures.md)
* [Documentation](documentation.md)
* [Iterators](iterators.md)
* [Generics](generics.md)
* [Traits](traits.md)
* [Static and Dynamic Dispatch](static-and-dynamic-dispatch.md)
* [Macros](macros.md)
* [Concurrency](concurrency.md)
* [Error Handling](error-handling.md)
* [Documentation](documentation.md)
* [Advanced Topics](advanced.md)
* [FFI](ffi.md)
* [Unsafe Code](unsafe.md)
* [Advanced Macros](advanced-macros.md)
* [Unstable Rust](unstable.md)
* [Compiler Plugins](plugins.md)
* [`Deref` coercions](deref-coercions.md)
* [Syntax and Semantics](syntax-and-semantics.md)
* [Variable Bindings](variable-bindings.md)
* [Primitive Types](primitive-types.md)
* [Functions](functions.md)
* [Comments](comments.md)
* [Structs](structs.md)
* [Mutability](mutability.md)
* [Method Syntax](method-syntax.md)
* [Enums](enums.md)
* [`if`](if.md)
* [Match](match.md)
* [Patterns](patterns.md)
* [`for` loops](for-loops.md)
* [`while` loops](while-loops.md)
* [Ownership](ownership.md)
* [References and Borrowing](references-and-borrowing.md)
* [Lifetimes](lifetimes.md)
* [Move semantics](move-semantics.md)
* [Drop](drop.md)
* [Vectors](vectors.md)
* [Arrays](arrays.md)
* [Slices](slices.md)
* [Strings](strings.md)
* [Traits](traits.md)
* [Operators and Overloading](operators-and-overloading.md)
* [Generics](generics.md)
* [Trait Objects](trait-objects.md)
* [Closures](closures.md)
* [Universal Function Call Syntax](ufcs.md)
* [Crates and Modules](crates-and-modules.md)
* [`static`](static.md)
* [`const`](const.md)
* [Tuples](tuples.md)
* [Tuple Structs](tuple-structs.md)
* [Attributes](attributes.md)
* [Conditional Compilation](conditional-compilation.md)
* [`type` aliases](type-aliases.md)
* [Casting between types](casting-between-types.md)
* [Associated Types](associated-types.md)
* [Unsized Types](unsized-types.md)
* [Macros](macros.md)
* [`unsafe` Code](unsafe-code.md)
* [Nightly Rust](nightly-rust.md)
* [Compiler Plugins](compiler-plugins.md)
* [Inline Assembly](inline-assembly.md)
* [No stdlib](no-stdlib.md)
* [Intrinsics](intrinsics.md)
@ -44,5 +66,4 @@
* [Link args](link-args.md)
* [Benchmark Tests](benchmark-tests.md)
* [Box Syntax and Patterns](box-syntax-and-patterns.md)
* [Conclusion](conclusion.md)
* [Glossary](glossary.md)

View File

@ -1,242 +0,0 @@
% Advanced macros
This chapter picks up where the [introductory macro chapter](macros.html) left
off.
# Syntactic requirements
Even when Rust code contains un-expanded macros, it can be parsed as a full
[syntax tree][ast]. This property can be very useful for editors and other
tools that process code. It also has a few consequences for the design of
Rust's macro system.
[ast]: glossary.html#abstract-syntax-tree
One consequence is that Rust must determine, when it parses a macro invocation,
whether the macro stands in for
* zero or more items,
* zero or more methods,
* an expression,
* a statement, or
* a pattern.
A macro invocation within a block could stand for some items, or for an
expression / statement. Rust uses a simple rule to resolve this ambiguity. A
macro invocation that stands for items must be either
* delimited by curly braces, e.g. `foo! { ... }`, or
* terminated by a semicolon, e.g. `foo!(...);`
Another consequence of pre-expansion parsing is that the macro invocation must
consist of valid Rust tokens. Furthermore, parentheses, brackets, and braces
must be balanced within a macro invocation. For example, `foo!([)` is
forbidden. This allows Rust to know where the macro invocation ends.
More formally, the macro invocation body must be a sequence of *token trees*.
A token tree is defined recursively as either
* a sequence of token trees surrounded by matching `()`, `[]`, or `{}`, or
* any other single token.
Within a matcher, each metavariable has a *fragment specifier*, identifying
which syntactic form it matches.
* `ident`: an identifier. Examples: `x`; `foo`.
* `path`: a qualified name. Example: `T::SpecialA`.
* `expr`: an expression. Examples: `2 + 2`; `if true then { 1 } else { 2 }`; `f(42)`.
* `ty`: a type. Examples: `i32`; `Vec<(char, String)>`; `&T`.
* `pat`: a pattern. Examples: `Some(t)`; `(17, 'a')`; `_`.
* `stmt`: a single statement. Example: `let x = 3`.
* `block`: a brace-delimited sequence of statements. Example:
`{ log(error, "hi"); return 12; }`.
* `item`: an [item][]. Examples: `fn foo() { }`; `struct Bar;`.
* `meta`: a "meta item", as found in attributes. Example: `cfg(target_os = "windows")`.
* `tt`: a single token tree.
There are additional rules regarding the next token after a metavariable:
* `expr` variables must be followed by one of: `=> , ;`
* `ty` and `path` variables must be followed by one of: `=> , : = > as`
* `pat` variables must be followed by one of: `=> , =`
* Other variables may be followed by any token.
These rules provide some flexibility for Rust's syntax to evolve without
breaking existing macros.
The macro system does not deal with parse ambiguity at all. For example, the
grammar `$($t:ty)* $e:expr` will always fail to parse, because the parser would
be forced to choose between parsing `$t` and parsing `$e`. Changing the
invocation syntax to put a distinctive token in front can solve the problem. In
this case, you can write `$(T $t:ty)* E $e:exp`.
[item]: ../reference.html#items
# Scoping and macro import/export
Macros are expanded at an early stage in compilation, before name resolution.
One downside is that scoping works differently for macros, compared to other
constructs in the language.
Definition and expansion of macros both happen in a single depth-first,
lexical-order traversal of a crate's source. So a macro defined at module scope
is visible to any subsequent code in the same module, which includes the body
of any subsequent child `mod` items.
A macro defined within the body of a single `fn`, or anywhere else not at
module scope, is visible only within that item.
If a module has the `macro_use` attribute, its macros are also visible in its
parent module after the child's `mod` item. If the parent also has `macro_use`
then the macros will be visible in the grandparent after the parent's `mod`
item, and so forth.
The `macro_use` attribute can also appear on `extern crate`. In this context
it controls which macros are loaded from the external crate, e.g.
```rust,ignore
#[macro_use(foo, bar)]
extern crate baz;
```
If the attribute is given simply as `#[macro_use]`, all macros are loaded. If
there is no `#[macro_use]` attribute then no macros are loaded. Only macros
defined with the `#[macro_export]` attribute may be loaded.
To load a crate's macros *without* linking it into the output, use `#[no_link]`
as well.
An example:
```rust
macro_rules! m1 { () => (()) }
// visible here: m1
mod foo {
// visible here: m1
#[macro_export]
macro_rules! m2 { () => (()) }
// visible here: m1, m2
}
// visible here: m1
macro_rules! m3 { () => (()) }
// visible here: m1, m3
#[macro_use]
mod bar {
// visible here: m1, m3
macro_rules! m4 { () => (()) }
// visible here: m1, m3, m4
}
// visible here: m1, m3, m4
# fn main() { }
```
When this library is loaded with `#[macro_use] extern crate`, only `m2` will
be imported.
The Rust Reference has a [listing of macro-related
attributes](../reference.html#macro--and-plugin-related-attributes).
# The variable `$crate`
A further difficulty occurs when a macro is used in multiple crates. Say that
`mylib` defines
```rust
pub fn increment(x: u32) -> u32 {
x + 1
}
#[macro_export]
macro_rules! inc_a {
($x:expr) => ( ::increment($x) )
}
#[macro_export]
macro_rules! inc_b {
($x:expr) => ( ::mylib::increment($x) )
}
# fn main() { }
```
`inc_a` only works within `mylib`, while `inc_b` only works outside the
library. Furthermore, `inc_b` will break if the user imports `mylib` under
another name.
Rust does not (yet) have a hygiene system for crate references, but it does
provide a simple workaround for this problem. Within a macro imported from a
crate named `foo`, the special macro variable `$crate` will expand to `::foo`.
By contrast, when a macro is defined and then used in the same crate, `$crate`
will expand to nothing. This means we can write
```rust
#[macro_export]
macro_rules! inc {
($x:expr) => ( $crate::increment($x) )
}
# fn main() { }
```
to define a single macro that works both inside and outside our library. The
function name will expand to either `::increment` or `::mylib::increment`.
To keep this system simple and correct, `#[macro_use] extern crate ...` may
only appear at the root of your crate, not inside `mod`. This ensures that
`$crate` is a single identifier.
# The deep end
The introductory chapter mentioned recursive macros, but it did not give the
full story. Recursive macros are useful for another reason: Each recursive
invocation gives you another opportunity to pattern-match the macro's
arguments.
As an extreme example, it is possible, though hardly advisable, to implement
the [Bitwise Cyclic Tag](http://esolangs.org/wiki/Bitwise_Cyclic_Tag) automaton
within Rust's macro system.
```rust
macro_rules! bct {
// cmd 0: d ... => ...
(0, $($ps:tt),* ; $_d:tt)
=> (bct!($($ps),*, 0 ; ));
(0, $($ps:tt),* ; $_d:tt, $($ds:tt),*)
=> (bct!($($ps),*, 0 ; $($ds),*));
// cmd 1p: 1 ... => 1 ... p
(1, $p:tt, $($ps:tt),* ; 1)
=> (bct!($($ps),*, 1, $p ; 1, $p));
(1, $p:tt, $($ps:tt),* ; 1, $($ds:tt),*)
=> (bct!($($ps),*, 1, $p ; 1, $($ds),*, $p));
// cmd 1p: 0 ... => 0 ...
(1, $p:tt, $($ps:tt),* ; $($ds:tt),*)
=> (bct!($($ps),*, 1, $p ; $($ds),*));
// halt on empty data string
( $($ps:tt),* ; )
=> (());
}
```
Exercise: use macros to reduce duplication in the above definition of the
`bct!` macro.
# Procedural macros
If Rust's macro system can't do what you need, you may want to write a
[compiler plugin](plugins.html) instead. Compared to `macro_rules!`
macros, this is significantly more work, the interfaces are much less stable,
and bugs can be much harder to track down. In exchange you get the
flexibility of running arbitrary Rust code within the compiler. Syntax
extension plugins are sometimes called *procedural macros* for this reason.

View File

@ -1,8 +0,0 @@
% Advanced
In a similar fashion to "Intermediate," this section is full of individual,
deep-dive chapters, which stand alone and can be read in any order. These
chapters focus on the most complex features, as well as some things that
are only available in upcoming versions of Rust.
After reading "Advanced," you'll be a Rust expert!

View File

@ -1,102 +0,0 @@
% Arrays, Vectors, and Slices
Like many programming languages, Rust has list types to represent a sequence of
things. The most basic is the *array*, a fixed-size list of elements of the
same type. By default, arrays are immutable.
```{rust}
let a = [1, 2, 3]; // a: [i32; 3]
let mut m = [1, 2, 3]; // mut m: [i32; 3]
```
There's a shorthand for initializing each element of an array to the same
value. In this example, each element of `a` will be initialized to `0`:
```{rust}
let a = [0; 20]; // a: [i32; 20]
```
Arrays have type `[T; N]`. We'll talk about this `T` notation later, when we
cover generics.
You can get the number of elements in an array `a` with `a.len()`, and use
`a.iter()` to iterate over them with a for loop. This code will print each
number in order:
```{rust}
let a = [1, 2, 3];
println!("a has {} elements", a.len());
for e in a.iter() {
println!("{}", e);
}
```
You can access a particular element of an array with *subscript notation*:
```{rust}
let names = ["Graydon", "Brian", "Niko"]; // names: [&str; 3]
println!("The second name is: {}", names[1]);
```
Subscripts start at zero, like in most programming languages, so the first name
is `names[0]` and the second name is `names[1]`. The above example prints
`The second name is: Brian`. If you try to use a subscript that is not in the
array, you will get an error: array access is bounds-checked at run-time. Such
errant access is the source of many bugs in other systems programming
languages.
A *vector* is a dynamic or "growable" array, implemented as the standard
library type [`Vec<T>`](../std/vec/) (we'll talk about what the `<T>` means
later). Vectors always allocate their data on the heap. Vectors are to slices
what `String` is to `&str`. You can create them with the `vec!` macro:
```{rust}
let v = vec![1, 2, 3]; // v: Vec<i32>
```
(Notice that unlike the `println!` macro we've used in the past, we use square
brackets `[]` with `vec!`. Rust allows you to use either in either situation,
this is just convention.)
There's an alternate form of `vec!` for repeating an initial value:
```
let v = vec![0; 10]; // ten zeroes
```
You can get the length of, iterate over, and subscript vectors just like
arrays. In addition, (mutable) vectors can grow automatically:
```{rust}
let mut nums = vec![1, 2, 3]; // mut nums: Vec<i32>
nums.push(4);
println!("The length of nums is now {}", nums.len()); // Prints 4
```
Vectors have many more useful methods.
A *slice* is a reference to (or "view" into) an array. They are useful for
allowing safe, efficient access to a portion of an array without copying. For
example, you might want to reference just one line of a file read into memory.
By nature, a slice is not created directly, but from an existing variable.
Slices have a length, can be mutable or not, and in many ways behave like
arrays:
```{rust}
let a = [0, 1, 2, 3, 4];
let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3
for e in middle.iter() {
println!("{}", e); // Prints 1, 2, 3
}
```
You can also take a slice of a vector, `String`, or `&str`, because they are
backed by arrays. Slices have type `&[T]`, which we'll talk about when we cover
generics.
We have now learned all of the most basic Rust concepts.

48
src/doc/trpl/arrays.md Normal file
View File

@ -0,0 +1,48 @@
% Arrays
Like many programming languages, Rust has list types to represent a sequence of
things. The most basic is the *array*, a fixed-size list of elements of the
same type. By default, arrays are immutable.
```{rust}
let a = [1, 2, 3]; // a: [i32; 3]
let mut m = [1, 2, 3]; // mut m: [i32; 3]
```
There's a shorthand for initializing each element of an array to the same
value. In this example, each element of `a` will be initialized to `0`:
```{rust}
let a = [0; 20]; // a: [i32; 20]
```
Arrays have type `[T; N]`. We'll talk about this `T` notation later, when we
cover generics.
You can get the number of elements in an array `a` with `a.len()`, and use
`a.iter()` to iterate over them with a for loop. This code will print each
number in order:
```{rust}
let a = [1, 2, 3];
println!("a has {} elements", a.len());
for e in a.iter() {
println!("{}", e);
}
```
You can access a particular element of an array with *subscript notation*:
```{rust}
let names = ["Graydon", "Brian", "Niko"]; // names: [&str; 3]
println!("The second name is: {}", names[1]);
```
Subscripts start at zero, like in most programming languages, so the first name
is `names[0]` and the second name is `names[1]`. The above example prints
`The second name is: Brian`. If you try to use a subscript that is not in the
array, you will get an error: array access is bounds-checked at run-time. Such
errant access is the source of many bugs in other systems programming
languages.

View File

@ -0,0 +1,3 @@
% Attributes
Coming Soon!

View File

@ -1,7 +0,0 @@
% Basics
This section is a linear introduction to the basic syntax and semantics of
Rust. It has individual sections on each part of Rust's syntax.
After reading "Basics," you will have a good foundation to learn more about
Rust, and can write very simple programs.

View File

@ -0,0 +1,3 @@
% Casting Between Types
Coming Soon

View File

@ -1,364 +0,0 @@
% Compound Data Types
Rust, like many programming languages, has a number of different data types
that are built-in. You've already done some simple work with integers and
strings, but next, let's talk about some more complicated ways of storing data.
## Tuples
The first compound data type we're going to talk about is called the *tuple*.
A tuple is an ordered list of fixed size. Like this:
```rust
let x = (1, "hello");
```
The parentheses and commas form this two-length tuple. Here's the same code, but
with the type annotated:
```rust
let x: (i32, &str) = (1, "hello");
```
As you can see, the type of a tuple looks just like the tuple, but with each
position having a type name rather than the value. Careful readers will also
note that tuples are heterogeneous: we have an `i32` and a `&str` in this tuple.
You have briefly seen `&str` used as a type before, and we'll discuss the
details of strings later. In systems programming languages, strings are a bit
more complex than in other languages. For now, just read `&str` as a *string
slice*, and we'll learn more soon.
You can access the fields in a tuple through a *destructuring let*. Here's
an example:
```rust
let (x, y, z) = (1, 2, 3);
println!("x is {}", x);
```
Remember before when I said the left-hand side of a `let` statement was more
powerful than just assigning a binding? Here we are. We can put a pattern on
the left-hand side of the `let`, and if it matches up to the right-hand side,
we can assign multiple bindings at once. In this case, `let` "destructures,"
or "breaks up," the tuple, and assigns the bits to three bindings.
This pattern is very powerful, and we'll see it repeated more later.
There are also a few things you can do with a tuple as a whole, without
destructuring. You can assign one tuple into another, if they have the same
contained types and [arity]. Tuples have the same arity when they have the same
length.
```rust
let mut x = (1, 2); // x: (i32, i32)
let y = (2, 3); // y: (i32, i32)
x = y;
```
You can also check for equality with `==`. Again, this will only compile if the
tuples have the same type.
```rust
let x = (1, 2, 3);
let y = (2, 2, 4);
if x == y {
println!("yes");
} else {
println!("no");
}
```
This will print `no`, because some of the values aren't equal.
Note that the order of the values is considered when checking for equality,
so the following example will also print `no`.
```rust
let x = (1, 2, 3);
let y = (2, 1, 3);
if x == y {
println!("yes");
} else {
println!("no");
}
```
One other use of tuples is to return multiple values from a function:
```rust
fn next_two(x: i32) -> (i32, i32) { (x + 1, x + 2) }
fn main() {
let (x, y) = next_two(5);
println!("x, y = {}, {}", x, y);
}
```
Even though Rust functions can only return one value, a tuple *is* one value,
that happens to be made up of more than one value. You can also see in this
example how you can destructure a pattern returned by a function, as well.
Tuples are a very simple data structure, and so are not often what you want.
Let's move on to their bigger sibling, structs.
## Structs
A struct is another form of a *record type*, just like a tuple. There's a
difference: structs give each element that they contain a name, called a
*field* or a *member*. Check it out:
```rust
struct Point {
x: i32,
y: i32,
}
fn main() {
let origin = Point { x: 0, y: 0 }; // origin: Point
println!("The origin is at ({}, {})", origin.x, origin.y);
}
```
There's a lot going on here, so let's break it down. We declare a struct with
the `struct` keyword, and then with a name. By convention, structs begin with a
capital letter and are also camel cased: `PointInSpace`, not `Point_In_Space`.
We can create an instance of our struct via `let`, as usual, but we use a `key:
value` style syntax to set each field. The order doesn't need to be the same as
in the original declaration.
Finally, because fields have names, we can access the field through dot
notation: `origin.x`.
The values in structs are immutable by default, like other bindings in Rust.
Use `mut` to make them mutable:
```{rust}
struct Point {
x: i32,
y: i32,
}
fn main() {
let mut point = Point { x: 0, y: 0 };
point.x = 5;
println!("The point is at ({}, {})", point.x, point.y);
}
```
This will print `The point is at (5, 0)`.
## Tuple Structs and Newtypes
Rust has another data type that's like a hybrid between a tuple and a struct,
called a *tuple struct*. Tuple structs do have a name, but their fields don't:
```{rust}
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
```
These two will not be equal, even if they have the same values:
```{rust}
# struct Color(i32, i32, i32);
# struct Point(i32, i32, i32);
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
```
It is almost always better to use a struct than a tuple struct. We would write
`Color` and `Point` like this instead:
```{rust}
struct Color {
red: i32,
blue: i32,
green: i32,
}
struct Point {
x: i32,
y: i32,
z: i32,
}
```
Now, we have actual names, rather than positions. Good names are important,
and with a struct, we have actual names.
There _is_ one case when a tuple struct is very useful, though, and that's a
tuple struct with only one element. We call this the *newtype* pattern, because
it allows you to create a new type, distinct from that of its contained value
and expressing its own semantic meaning:
```{rust}
struct Inches(i32);
let length = Inches(10);
let Inches(integer_length) = length;
println!("length is {} inches", integer_length);
```
As you can see here, you can extract the inner integer type through a
destructuring `let`, as we discussed previously in 'tuples.' In this case, the
`let Inches(integer_length)` assigns `10` to `integer_length`.
## Enums
Finally, Rust has a "sum type", an *enum*. Enums are an incredibly useful
feature of Rust, and are used throughout the standard library. An `enum` is
a type which relates a set of alternates to a specific name. For example, below
we define `Character` to be either a `Digit` or something else. These
can be used via their fully scoped names: `Character::Other` (more about `::`
below).
```rust
enum Character {
Digit(i32),
Other,
}
```
Most normal types are allowed as the variant components of an `enum`. Here are
some examples:
```rust
struct Empty;
struct Color(i32, i32, i32);
struct Length(i32);
struct Status { Health: i32, Mana: i32, Attack: i32, Defense: i32 }
struct HeightDatabase(Vec<i32>);
```
You see that, depending on its type, an `enum` variant may or may not hold data.
In `Character`, for instance, `Digit` gives a meaningful name for an `i32`
value, where `Other` is only a name. However, the fact that they represent
distinct categories of `Character` is a very useful property.
As with structures, the variants of an enum by default are not comparable with
equality operators (`==`, `!=`), have no ordering (`<`, `>=`, etc.), and do not
support other binary operations such as `*` and `+`. As such, the following code
is invalid for the example `Character` type:
```{rust,ignore}
// These assignments both succeed
let ten = Character::Digit(10);
let four = Character::Digit(4);
// Error: `*` is not implemented for type `Character`
let forty = ten * four;
// Error: `<=` is not implemented for type `Character`
let four_is_smaller = four <= ten;
// Error: `==` is not implemented for type `Character`
let four_equals_ten = four == ten;
```
This may seem rather limiting, but it's a limitation which we can overcome.
There are two ways: by implementing equality ourselves, or by pattern matching
variants with [`match`][match] expressions, which you'll learn in the next
chapter. We don't know enough about Rust to implement equality yet, but we can
use the `Ordering` enum from the standard library, which does:
```
enum Ordering {
Less,
Equal,
Greater,
}
```
Because `Ordering` has already been defined for us, we will import it with the
`use` keyword. Here's an example of how it is used:
```{rust}
use std::cmp::Ordering;
fn cmp(a: i32, b: i32) -> Ordering {
if a < b { Ordering::Less }
else if a > b { Ordering::Greater }
else { Ordering::Equal }
}
fn main() {
let x = 5;
let y = 10;
let ordering = cmp(x, y); // ordering: Ordering
if ordering == Ordering::Less {
println!("less");
} else if ordering == Ordering::Greater {
println!("greater");
} else if ordering == Ordering::Equal {
println!("equal");
}
}
```
The `::` symbol is used to indicate a namespace. In this case, `Ordering` lives
in the `cmp` submodule of the `std` module. We'll talk more about modules later
in the guide. For now, all you need to know is that you can `use` things from
the standard library if you need them.
Okay, let's talk about the actual code in the example. `cmp` is a function that
compares two things, and returns an `Ordering`. We return either
`Ordering::Less`, `Ordering::Greater`, or `Ordering::Equal`, depending on
whether the first value is less than, greater than, or equal to the second. Note
that each variant of the `enum` is namespaced under the `enum` itself: it's
`Ordering::Greater`, not `Greater`.
The `ordering` variable has the type `Ordering`, and so contains one of the
three values. We then do a bunch of `if`/`else` comparisons to check which
one it is.
This `Ordering::Greater` notation is too long. Let's use another form of `use`
to import the `enum` variants instead. This will avoid full scoping:
```{rust}
use std::cmp::Ordering::{self, Equal, Less, Greater};
fn cmp(a: i32, b: i32) -> Ordering {
if a < b { Less }
else if a > b { Greater }
else { Equal }
}
fn main() {
let x = 5;
let y = 10;
let ordering = cmp(x, y); // ordering: Ordering
if ordering == Less { println!("less"); }
else if ordering == Greater { println!("greater"); }
else if ordering == Equal { println!("equal"); }
}
```
Importing variants is convenient and compact, but can also cause name conflicts,
so do this with caution. For this reason, it's normally considered better style
to `use` an enum rather than its variants directly.
As you can see, `enum`s are quite a powerful tool for data representation, and
are even more useful when they're [generic][generics] across types. Before we
get to generics, though, let's talk about how to use enums with pattern
matching, a tool that will let us deconstruct sum types (the type theory term
for enums) like `Ordering` in a very elegant way that avoids all these messy
and brittle `if`/`else`s.
[arity]: ./glossary.html#arity
[match]: ./match.html
[generics]: ./generics.html

View File

@ -1,11 +0,0 @@
% Conclusion
We covered a lot of ground here. When you've mastered everything in this Guide,
you will have a firm grasp of Rust development. There's a whole lot more
out there, though, we've just covered the surface. There's tons of topics that
you can dig deeper into, e.g. by reading the API documentation of the
[standard library](http://doc.rust-lang.org/std/), by discovering solutions for
common problems on [Rust by Example](http://rustbyexample.com/), or by browsing
crates written by the community on [crates.io](https://crates.io/).
Happy hacking!

View File

@ -0,0 +1,3 @@
% Conditional Compilation
Coming Soon!

3
src/doc/trpl/const.md Normal file
View File

@ -0,0 +1,3 @@
% `const`
Coming soon!

View File

@ -0,0 +1,3 @@
% `Debug` and `Display`
Coming soon!

View File

@ -0,0 +1,3 @@
% `Deref` coercions
Coming soon!

3
src/doc/trpl/drop.md Normal file
View File

@ -0,0 +1,3 @@
% `Drop`
Coming soon!

View File

@ -0,0 +1 @@
% Effective Rust

149
src/doc/trpl/enums.md Normal file
View File

@ -0,0 +1,149 @@
% Enums
Finally, Rust has a "sum type", an *enum*. Enums are an incredibly useful
feature of Rust, and are used throughout the standard library. An `enum` is
a type which relates a set of alternates to a specific name. For example, below
we define `Character` to be either a `Digit` or something else. These
can be used via their fully scoped names: `Character::Other` (more about `::`
below).
```rust
enum Character {
Digit(i32),
Other,
}
```
Most normal types are allowed as the variant components of an `enum`. Here are
some examples:
```rust
struct Empty;
struct Color(i32, i32, i32);
struct Length(i32);
struct Status { Health: i32, Mana: i32, Attack: i32, Defense: i32 }
struct HeightDatabase(Vec<i32>);
```
You see that, depending on its type, an `enum` variant may or may not hold data.
In `Character`, for instance, `Digit` gives a meaningful name for an `i32`
value, where `Other` is only a name. However, the fact that they represent
distinct categories of `Character` is a very useful property.
As with structures, the variants of an enum by default are not comparable with
equality operators (`==`, `!=`), have no ordering (`<`, `>=`, etc.), and do not
support other binary operations such as `*` and `+`. As such, the following code
is invalid for the example `Character` type:
```{rust,ignore}
// These assignments both succeed
let ten = Character::Digit(10);
let four = Character::Digit(4);
// Error: `*` is not implemented for type `Character`
let forty = ten * four;
// Error: `<=` is not implemented for type `Character`
let four_is_smaller = four <= ten;
// Error: `==` is not implemented for type `Character`
let four_equals_ten = four == ten;
```
This may seem rather limiting, but it's a limitation which we can overcome.
There are two ways: by implementing equality ourselves, or by pattern matching
variants with [`match`][match] expressions, which you'll learn in the next
chapter. We don't know enough about Rust to implement equality yet, but we can
use the `Ordering` enum from the standard library, which does:
```
enum Ordering {
Less,
Equal,
Greater,
}
```
Because `Ordering` has already been defined for us, we will import it with the
`use` keyword. Here's an example of how it is used:
```{rust}
use std::cmp::Ordering;
fn cmp(a: i32, b: i32) -> Ordering {
if a < b { Ordering::Less }
else if a > b { Ordering::Greater }
else { Ordering::Equal }
}
fn main() {
let x = 5;
let y = 10;
let ordering = cmp(x, y); // ordering: Ordering
if ordering == Ordering::Less {
println!("less");
} else if ordering == Ordering::Greater {
println!("greater");
} else if ordering == Ordering::Equal {
println!("equal");
}
}
```
The `::` symbol is used to indicate a namespace. In this case, `Ordering` lives
in the `cmp` submodule of the `std` module. We'll talk more about modules later
in the guide. For now, all you need to know is that you can `use` things from
the standard library if you need them.
Okay, let's talk about the actual code in the example. `cmp` is a function that
compares two things, and returns an `Ordering`. We return either
`Ordering::Less`, `Ordering::Greater`, or `Ordering::Equal`, depending on
whether the first value is less than, greater than, or equal to the second. Note
that each variant of the `enum` is namespaced under the `enum` itself: it's
`Ordering::Greater`, not `Greater`.
The `ordering` variable has the type `Ordering`, and so contains one of the
three values. We then do a bunch of `if`/`else` comparisons to check which
one it is.
This `Ordering::Greater` notation is too long. Let's use another form of `use`
to import the `enum` variants instead. This will avoid full scoping:
```{rust}
use std::cmp::Ordering::{self, Equal, Less, Greater};
fn cmp(a: i32, b: i32) -> Ordering {
if a < b { Less }
else if a > b { Greater }
else { Equal }
}
fn main() {
let x = 5;
let y = 10;
let ordering = cmp(x, y); // ordering: Ordering
if ordering == Less { println!("less"); }
else if ordering == Greater { println!("greater"); }
else if ordering == Equal { println!("equal"); }
}
```
Importing variants is convenient and compact, but can also cause name conflicts,
so do this with caution. For this reason, it's normally considered better style
to `use` an enum rather than its variants directly.
As you can see, `enum`s are quite a powerful tool for data representation, and
are even more useful when they're [generic][generics] across types. Before we
get to generics, though, let's talk about how to use enums with pattern
matching, a tool that will let us deconstruct sum types (the type theory term
for enums) like `Ordering` in a very elegant way that avoids all these messy
and brittle `if`/`else`s.
[arity]: ./glossary.html#arity
[match]: ./match.html
[generics]: ./generics.html

44
src/doc/trpl/for-loops.md Normal file
View File

@ -0,0 +1,44 @@
% `for` Loops
The `for` loop is used to loop a particular number of times. Rust's `for` loops
work a bit differently than in other systems languages, however. Rust's `for`
loop doesn't look like this "C-style" `for` loop:
```{c}
for (x = 0; x < 10; x++) {
printf( "%d\n", x );
}
```
Instead, it looks like this:
```{rust}
for x in 0..10 {
println!("{}", x); // x: i32
}
```
In slightly more abstract terms,
```{ignore}
for var in expression {
code
}
```
The expression is an iterator, which we will discuss in more depth later in the
guide. The iterator gives back a series of elements. Each element is one
iteration of the loop. That value is then bound to the name `var`, which is
valid for the loop body. Once the body is over, the next value is fetched from
the iterator, and we loop another time. When there are no more values, the
`for` loop is over.
In our example, `0..10` is an expression that takes a start and an end position,
and gives an iterator over those values. The upper bound is exclusive, though,
so our loop will print `0` through `9`, not `10`.
Rust does not have the "C-style" `for` loop on purpose. Manually controlling
each element of the loop is complicated and error prone, even for experienced C
developers.
We'll talk more about `for` when we cover *iterators*, later in the Guide.

View File

@ -0,0 +1 @@
% Getting Started

View File

@ -1,4 +1,4 @@
% If
% `if`
Rust's take on `if` is not particularly complex, but it's much more like the
`if` you'll find in a dynamically typed language than in a more traditional
@ -153,3 +153,5 @@ instead.
There's one more time in which you won't see a semicolon at the end of a line
of Rust code. For that, we'll need our next concept: functions.
TODO: `if let`

View File

@ -1,7 +0,0 @@
% Intermediate
This section contains individual chapters, which are self-contained. They focus
on specific topics, and can be read in any order.
After reading "Intermediate," you will have a solid understanding of Rust,
and will be able to understand most Rust code and write more complex programs.

View File

@ -0,0 +1 @@
% Learn Rust

View File

@ -0,0 +1,3 @@
% Lifetimes
Coming soon!

View File

@ -424,9 +424,240 @@ they are unstable and require feature gates.
* `trace_macros!(true)` will enable a compiler message every time a macro is
expanded. Use `trace_macros!(false)` later in expansion to turn it off.
# Further reading
# Syntactic requirements
The [advanced macros chapter][] goes into more detail about macro syntax. It
also describes how to share macros between different modules or crates.
Even when Rust code contains un-expanded macros, it can be parsed as a full
[syntax tree][ast]. This property can be very useful for editors and other
tools that process code. It also has a few consequences for the design of
Rust's macro system.
[advanced macros chapter]: advanced-macros.html
[ast]: glossary.html#abstract-syntax-tree
One consequence is that Rust must determine, when it parses a macro invocation,
whether the macro stands in for
* zero or more items,
* zero or more methods,
* an expression,
* a statement, or
* a pattern.
A macro invocation within a block could stand for some items, or for an
expression / statement. Rust uses a simple rule to resolve this ambiguity. A
macro invocation that stands for items must be either
* delimited by curly braces, e.g. `foo! { ... }`, or
* terminated by a semicolon, e.g. `foo!(...);`
Another consequence of pre-expansion parsing is that the macro invocation must
consist of valid Rust tokens. Furthermore, parentheses, brackets, and braces
must be balanced within a macro invocation. For example, `foo!([)` is
forbidden. This allows Rust to know where the macro invocation ends.
More formally, the macro invocation body must be a sequence of *token trees*.
A token tree is defined recursively as either
* a sequence of token trees surrounded by matching `()`, `[]`, or `{}`, or
* any other single token.
Within a matcher, each metavariable has a *fragment specifier*, identifying
which syntactic form it matches.
* `ident`: an identifier. Examples: `x`; `foo`.
* `path`: a qualified name. Example: `T::SpecialA`.
* `expr`: an expression. Examples: `2 + 2`; `if true then { 1 } else { 2 }`; `f(42)`.
* `ty`: a type. Examples: `i32`; `Vec<(char, String)>`; `&T`.
* `pat`: a pattern. Examples: `Some(t)`; `(17, 'a')`; `_`.
* `stmt`: a single statement. Example: `let x = 3`.
* `block`: a brace-delimited sequence of statements. Example:
`{ log(error, "hi"); return 12; }`.
* `item`: an [item][]. Examples: `fn foo() { }`; `struct Bar;`.
* `meta`: a "meta item", as found in attributes. Example: `cfg(target_os = "windows")`.
* `tt`: a single token tree.
There are additional rules regarding the next token after a metavariable:
* `expr` variables must be followed by one of: `=> , ;`
* `ty` and `path` variables must be followed by one of: `=> , : = > as`
* `pat` variables must be followed by one of: `=> , =`
* Other variables may be followed by any token.
These rules provide some flexibility for Rust's syntax to evolve without
breaking existing macros.
The macro system does not deal with parse ambiguity at all. For example, the
grammar `$($t:ty)* $e:expr` will always fail to parse, because the parser would
be forced to choose between parsing `$t` and parsing `$e`. Changing the
invocation syntax to put a distinctive token in front can solve the problem. In
this case, you can write `$(T $t:ty)* E $e:exp`.
[item]: ../reference.html#items
# Scoping and macro import/export
Macros are expanded at an early stage in compilation, before name resolution.
One downside is that scoping works differently for macros, compared to other
constructs in the language.
Definition and expansion of macros both happen in a single depth-first,
lexical-order traversal of a crate's source. So a macro defined at module scope
is visible to any subsequent code in the same module, which includes the body
of any subsequent child `mod` items.
A macro defined within the body of a single `fn`, or anywhere else not at
module scope, is visible only within that item.
If a module has the `macro_use` attribute, its macros are also visible in its
parent module after the child's `mod` item. If the parent also has `macro_use`
then the macros will be visible in the grandparent after the parent's `mod`
item, and so forth.
The `macro_use` attribute can also appear on `extern crate`. In this context
it controls which macros are loaded from the external crate, e.g.
```rust,ignore
#[macro_use(foo, bar)]
extern crate baz;
```
If the attribute is given simply as `#[macro_use]`, all macros are loaded. If
there is no `#[macro_use]` attribute then no macros are loaded. Only macros
defined with the `#[macro_export]` attribute may be loaded.
To load a crate's macros *without* linking it into the output, use `#[no_link]`
as well.
An example:
```rust
macro_rules! m1 { () => (()) }
// visible here: m1
mod foo {
// visible here: m1
#[macro_export]
macro_rules! m2 { () => (()) }
// visible here: m1, m2
}
// visible here: m1
macro_rules! m3 { () => (()) }
// visible here: m1, m3
#[macro_use]
mod bar {
// visible here: m1, m3
macro_rules! m4 { () => (()) }
// visible here: m1, m3, m4
}
// visible here: m1, m3, m4
# fn main() { }
```
When this library is loaded with `#[macro_use] extern crate`, only `m2` will
be imported.
The Rust Reference has a [listing of macro-related
attributes](../reference.html#macro--and-plugin-related-attributes).
# The variable `$crate`
A further difficulty occurs when a macro is used in multiple crates. Say that
`mylib` defines
```rust
pub fn increment(x: u32) -> u32 {
x + 1
}
#[macro_export]
macro_rules! inc_a {
($x:expr) => ( ::increment($x) )
}
#[macro_export]
macro_rules! inc_b {
($x:expr) => ( ::mylib::increment($x) )
}
# fn main() { }
```
`inc_a` only works within `mylib`, while `inc_b` only works outside the
library. Furthermore, `inc_b` will break if the user imports `mylib` under
another name.
Rust does not (yet) have a hygiene system for crate references, but it does
provide a simple workaround for this problem. Within a macro imported from a
crate named `foo`, the special macro variable `$crate` will expand to `::foo`.
By contrast, when a macro is defined and then used in the same crate, `$crate`
will expand to nothing. This means we can write
```rust
#[macro_export]
macro_rules! inc {
($x:expr) => ( $crate::increment($x) )
}
# fn main() { }
```
to define a single macro that works both inside and outside our library. The
function name will expand to either `::increment` or `::mylib::increment`.
To keep this system simple and correct, `#[macro_use] extern crate ...` may
only appear at the root of your crate, not inside `mod`. This ensures that
`$crate` is a single identifier.
# The deep end
The introductory chapter mentioned recursive macros, but it did not give the
full story. Recursive macros are useful for another reason: Each recursive
invocation gives you another opportunity to pattern-match the macro's
arguments.
As an extreme example, it is possible, though hardly advisable, to implement
the [Bitwise Cyclic Tag](http://esolangs.org/wiki/Bitwise_Cyclic_Tag) automaton
within Rust's macro system.
```rust
macro_rules! bct {
// cmd 0: d ... => ...
(0, $($ps:tt),* ; $_d:tt)
=> (bct!($($ps),*, 0 ; ));
(0, $($ps:tt),* ; $_d:tt, $($ds:tt),*)
=> (bct!($($ps),*, 0 ; $($ds),*));
// cmd 1p: 1 ... => 1 ... p
(1, $p:tt, $($ps:tt),* ; 1)
=> (bct!($($ps),*, 1, $p ; 1, $p));
(1, $p:tt, $($ps:tt),* ; 1, $($ds:tt),*)
=> (bct!($($ps),*, 1, $p ; 1, $($ds),*, $p));
// cmd 1p: 0 ... => 0 ...
(1, $p:tt, $($ps:tt),* ; $($ds:tt),*)
=> (bct!($($ps),*, 1, $p ; $($ds),*));
// halt on empty data string
( $($ps:tt),* ; )
=> (());
}
```
Exercise: use macros to reduce duplication in the above definition of the
`bct!` macro.
# Procedural macros
If Rust's macro system can't do what you need, you may want to write a
[compiler plugin](plugins.html) instead. Compared to `macro_rules!`
macros, this is significantly more work, the interfaces are much less stable,
and bugs can be much harder to track down. In exchange you get the
flexibility of running arbitrary Rust code within the compiler. Syntax
extension plugins are sometimes called *procedural macros* for this reason.

View File

@ -1,325 +0,0 @@
% More Strings
Strings are an important concept to master in any programming language. If you
come from a managed language background, you may be surprised at the complexity
of string handling in a systems programming language. Efficient access and
allocation of memory for a dynamically sized structure involves a lot of
details. Luckily, Rust has lots of tools to help us here.
A **string** is a sequence of unicode scalar values encoded as a stream of
UTF-8 bytes. All strings are guaranteed to be validly-encoded UTF-8 sequences.
Additionally, strings are not null-terminated and can contain null bytes.
Rust has two main types of strings: `&str` and `String`.
# `&str`
The first kind is a `&str`. This is pronounced a 'string slice'.
String literals are of the type `&str`:
```
let string = "Hello there.";
```
Like any Rust reference, string slices have an associated lifetime. A string
literal is a `&'static str`. A string slice can be written without an explicit
lifetime in many cases, such as in function arguments. In these cases the
lifetime will be inferred:
```
fn takes_slice(slice: &str) {
println!("Got: {}", slice);
}
```
Like vector slices, string slices are simply a pointer plus a length. This
means that they're a 'view' into an already-allocated string, such as a
string literal or a `String`.
## `str`
You may occasionally see references to a `str` type, without the `&`. While
this type does exist, its not something you want to use yourself. Sometimes,
people confuse `str` for `String`, and write this:
```rust
struct S {
s: str,
}
```
This leads to ugly errors:
```text
error: the trait `core::marker::Sized` is not implemented for the type `str` [E0277]
note: `str` does not have a constant size known at compile-time
```
Instead, this `struct` should be
```rust
struct S {
s: String,
}
```
So lets talk about `String`s.
# `String`
A `String` is a heap-allocated string. This string is growable, and is
also guaranteed to be UTF-8. `String`s are commonly created by
converting from a string slice using the `to_string` method.
```
let mut s = "Hello".to_string();
println!("{}", s);
s.push_str(", world.");
println!("{}", s);
```
A reference to a `String` will automatically coerce to a string slice:
```
fn takes_slice(slice: &str) {
println!("Got: {}", slice);
}
fn main() {
let s = "Hello".to_string();
takes_slice(&s);
}
```
You can also get a `&str` from a stack-allocated array of bytes:
```
use std::str;
let x: &[u8] = &[b'a', b'b'];
let stack_str: &str = str::from_utf8(x).unwrap();
```
# Best Practices
## `String` vs. `&str`
In general, you should prefer `String` when you need ownership, and `&str` when
you just need to borrow a string. This is very similar to using `Vec<T>` vs. `&[T]`,
and `T` vs `&T` in general.
This means starting off with this:
```{rust,ignore}
fn foo(s: &str) {
```
and only moving to this:
```{rust,ignore}
fn foo(s: String) {
```
if you have good reason. It's not polite to hold on to ownership you don't
need, and it can make your lifetimes more complex.
## Generic functions
To write a function that's generic over types of strings, use `&str`.
```
fn some_string_length(x: &str) -> usize {
x.len()
}
fn main() {
let s = "Hello, world";
println!("{}", some_string_length(s));
let s = "Hello, world".to_string();
println!("{}", some_string_length(&s));
}
```
Both of these lines will print `12`.
## Indexing strings
You may be tempted to try to access a certain character of a `String`, like
this:
```{rust,ignore}
let s = "hello".to_string();
println!("{}", s[0]);
```
This does not compile. This is on purpose. In the world of UTF-8, direct
indexing is basically never what you want to do. The reason is that each
character can be a variable number of bytes. This means that you have to iterate
through the characters anyway, which is an O(n) operation.
There's 3 basic levels of unicode (and its encodings):
- code units, the underlying data type used to store everything
- code points/unicode scalar values (char)
- graphemes (visible characters)
Rust provides iterators for each of these situations:
- `.bytes()` will iterate over the underlying bytes
- `.chars()` will iterate over the code points
- `.graphemes()` will iterate over each grapheme
Usually, the `graphemes()` method on `&str` is what you want:
```
# #![feature(unicode)]
let s = "u͔n͈̰̎i̙̮͚̦c͚̉o̼̩̰͗d͔̆̓ͥé";
for l in s.graphemes(true) {
println!("{}", l);
}
```
This prints:
```text
n͈̰̎
i̙̮͚̦
c͚̉
o̼̩̰͗
d͔̆̓ͥ
```
Note that `l` has the type `&str` here, since a single grapheme can consist of
multiple codepoints, so a `char` wouldn't be appropriate.
This will print out each visible character in turn, as you'd expect: first `u͔`, then
`n͈̰̎`, etc. If you wanted each individual codepoint of each grapheme, you can use `.chars()`:
```
let s = "u͔n͈̰̎i̙̮͚̦c͚̉o̼̩̰͗d͔̆̓ͥé";
for l in s.chars() {
println!("{}", l);
}
```
This prints:
```text
u
͔
n
̎
͈
̰
i
̙
̮
͚
̦
c
̉
͚
o
͗
̼
̩
̰
d
̆
̓
ͥ
͔
e
́
```
You can see how some of them are combining characters, and therefore the output
looks a bit odd.
If you want the individual byte representation of each codepoint, you can use
`.bytes()`:
```
let s = "u͔n͈̰̎i̙̮͚̦c͚̉o̼̩̰͗d͔̆̓ͥé";
for l in s.bytes() {
println!("{}", l);
}
```
This will print:
```text
117
205
148
110
204
142
205
136
204
176
105
204
153
204
174
205
154
204
166
99
204
137
205
154
111
205
151
204
188
204
169
204
176
100
204
134
205
131
205
165
205
148
101
204
129
```
Many more bytes than graphemes!
# `Deref` coercions
References to `String`s will automatically coerce into `&str`s. Like this:
```
fn hello(s: &str) {
println!("Hello, {}!", s);
}
let slice = "Steve";
let string = "Steve".to_string();
hello(slice);
hello(&string);
```

View File

@ -0,0 +1,3 @@
% Move Semantics
Coming Soon

View File

@ -0,0 +1,3 @@
% Mutability
Coming Soon

View File

@ -1,4 +1,4 @@
% Unstable Rust
% Nightly Rust
Rust provides three distribution channels for Rust: nightly, beta, and stable.
Unstable features are only available on nightly Rust. For more details on this

View File

@ -0,0 +1,3 @@
% Operators and Overloading
Coming soon!

View File

@ -1,699 +0,0 @@
% Pointers
Rust's pointers are one of its more unique and compelling features. Pointers
are also one of the more confusing topics for newcomers to Rust. They can also
be confusing for people coming from other languages that support pointers, such
as C++. This guide will help you understand this important topic.
Be sceptical of non-reference pointers in Rust: use them for a deliberate
purpose, not just to make the compiler happy. Each pointer type comes with an
explanation about when they are appropriate to use. Default to references
unless you're in one of those specific situations.
You may be interested in the [cheat sheet](#cheat-sheet), which gives a quick
overview of the types, names, and purpose of the various pointers.
# An introduction
If you aren't familiar with the concept of pointers, here's a short
introduction. Pointers are a very fundamental concept in systems programming
languages, so it's important to understand them.
## Pointer Basics
When you create a new variable binding, you're giving a name to a value that's
stored at a particular location on the stack. (If you're not familiar with the
*heap* vs. *stack*, please check out [this Stack Overflow
question](http://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap),
as the rest of this guide assumes you know the difference.) Like this:
```{rust}
let x = 5;
let y = 8;
```
| location | value |
|----------|-------|
| 0xd3e030 | 5 |
| 0xd3e028 | 8 |
We're making up memory locations here, they're just sample values. Anyway, the
point is that `x`, the name we're using for our variable, corresponds to the
memory location `0xd3e030`, and the value at that location is `5`. When we
refer to `x`, we get the corresponding value. Hence, `x` is `5`.
Let's introduce a pointer. In some languages, there is just one type of
'pointer,' but in Rust, we have many types. In this case, we'll use a Rust
*reference*, which is the simplest kind of pointer.
```{rust}
let x = 5;
let y = 8;
let z = &y;
```
|location | value |
|-------- |----------|
|0xd3e030 | 5 |
|0xd3e028 | 8 |
|0xd3e020 | 0xd3e028 |
See the difference? Rather than contain a value, the value of a pointer is a
location in memory. In this case, the location of `y`. `x` and `y` have the
type `i32`, but `z` has the type `&i32`. We can print this location using the
`{:p}` format string:
```{rust}
let x = 5;
let y = 8;
let z = &y;
println!("{:p}", z);
```
This would print `0xd3e028`, with our fictional memory addresses.
Because `i32` and `&i32` are different types, we can't, for example, add them
together:
```{rust,ignore}
let x = 5;
let y = 8;
let z = &y;
println!("{}", x + z);
```
This gives us an error:
```text
hello.rs:6:24: 6:25 error: mismatched types: expected `_`, found `&_` (expected integral variable, found &-ptr)
hello.rs:6 println!("{}", x + z);
^
```
We can *dereference* the pointer by using the `*` operator. Dereferencing a
pointer means accessing the value at the location stored in the pointer. This
will work:
```{rust}
let x = 5;
let y = 8;
let z = &y;
println!("{}", x + *z);
```
It prints `13`.
That's it! That's all pointers are: they point to some memory location. Not
much else to them. Now that we've discussed the *what* of pointers, let's
talk about the *why*.
## Pointer uses
Rust's pointers are quite useful, but in different ways than in other systems
languages. We'll talk about best practices for Rust pointers later in
the guide, but here are some ways that pointers are useful in other languages:
In C, strings are a pointer to a list of `char`s, ending with a null byte.
The only way to use strings is to get quite familiar with pointers.
Pointers are useful to point to memory locations that are not on the stack. For
example, our example used two stack variables, so we were able to give them
names. But if we allocated some heap memory, we wouldn't have that name
available. In C, `malloc` is used to allocate heap memory, and it returns a
pointer.
As a more general variant of the previous two points, any time you have a
structure that can change in size, you need a pointer. You can't tell at
compile time how much memory to allocate, so you've gotta use a pointer to
point at the memory where it will be allocated, and deal with it at run time.
Pointers are useful in languages that are pass-by-value, rather than
pass-by-reference. Basically, languages can make two choices (this is made
up syntax, it's not Rust):
```text
func foo(x) {
x = 5
}
func main() {
i = 1
foo(i)
// what is the value of i here?
}
```
In languages that are pass-by-value, `foo` will get a copy of `i`, and so
the original version of `i` is not modified. At the comment, `i` will still be
`1`. In a language that is pass-by-reference, `foo` will get a reference to `i`,
and therefore, can change its value. At the comment, `i` will be `5`.
So what do pointers have to do with this? Well, since pointers point to a
location in memory...
```text
func foo(&i32 x) {
*x = 5
}
func main() {
i = 1
foo(&i)
// what is the value of i here?
}
```
Even in a language which is pass by value, `i` will be `5` at the comment. You
see, because the argument `x` is a pointer, we do send a copy over to `foo`,
but because it points at a memory location, which we then assign to, the
original value is still changed. This pattern is called
*pass-reference-by-value*. Tricky!
## Common pointer problems
We've talked about pointers, and we've sung their praises. So what's the
downside? Well, Rust attempts to mitigate each of these kinds of problems,
but here are problems with pointers in other languages:
Uninitialized pointers can cause a problem. For example, what does this program
do?
```{ignore}
&int x;
*x = 5; // whoops!
```
Who knows? We just declare a pointer, but don't point it at anything, and then
set the memory location that it points at to be `5`. But which location? Nobody
knows. This might be harmless, and it might be catastrophic.
When you combine pointers and functions, it's easy to accidentally invalidate
the memory the pointer is pointing to. For example:
```text
func make_pointer(): &int {
x = 5;
return &x;
}
func main() {
&int i = make_pointer();
*i = 5; // uh oh!
}
```
`x` is local to the `make_pointer` function, and therefore, is invalid as soon
as `make_pointer` returns. But we return a pointer to its memory location, and
so back in `main`, we try to use that pointer, and it's a very similar
situation to our first one. Setting invalid memory locations is bad.
As one last example of a big problem with pointers, *aliasing* can be an
issue. Two pointers are said to alias when they point at the same location
in memory. Like this:
```text
func mutate(&int i, int j) {
*i = j;
}
func main() {
x = 5;
y = &x;
z = &x; //y and z are aliased
run_in_new_thread(mutate, y, 1);
run_in_new_thread(mutate, z, 100);
// what is the value of x here?
}
```
In this made-up example, `run_in_new_thread` spins up a new thread, and calls
the given function name with its arguments. Since we have two threads, and
they're both operating on aliases to `x`, we can't tell which one finishes
first, and therefore, the value of `x` is actually non-deterministic. Worse,
what if one of them had invalidated the memory location they pointed to? We'd
have the same problem as before, where we'd be setting an invalid location.
## Conclusion
That's a basic overview of pointers as a general concept. As we alluded to
before, Rust has different kinds of pointers, rather than just one, and
mitigates all of the problems that we talked about, too. This does mean that
Rust pointers are slightly more complicated than in other languages, but
it's worth it to not have the problems that simple pointers have.
# References
The most basic type of pointer that Rust has is called a *reference*. Rust
references look like this:
```{rust}
let x = 5;
let y = &x;
println!("{}", *y);
println!("{:p}", y);
println!("{}", y);
```
We'd say "`y` is a reference to `x`." The first `println!` prints out the
value of `y`'s referent by using the dereference operator, `*`. The second
one prints out the memory location that `y` points to, by using the pointer
format string. The third `println!` *also* prints out the value of `y`'s
referent, because `println!` will automatically dereference it for us.
Here's a function that takes a reference:
```{rust}
fn succ(x: &i32) -> i32 { *x + 1 }
```
You can also use `&` as an operator to create a reference, so we can
call this function in two different ways:
```{rust}
fn succ(x: &i32) -> i32 { *x + 1 }
fn main() {
let x = 5;
let y = &x;
println!("{}", succ(y));
println!("{}", succ(&x));
}
```
Both of these `println!`s will print out `6`.
Of course, if this were real code, we wouldn't bother with the reference, and
just write:
```{rust}
fn succ(x: i32) -> i32 { x + 1 }
```
References are immutable by default:
```{rust,ignore}
let x = 5;
let y = &x;
*y = 5; // error: cannot assign to immutable borrowed content `*y`
```
They can be made mutable with `mut`, but only if its referent is also mutable.
This works:
```{rust}
let mut x = 5;
let y = &mut x;
```
This does not:
```{rust,ignore}
let x = 5;
let y = &mut x; // error: cannot borrow immutable local variable `x` as mutable
```
Immutable pointers are allowed to alias:
```{rust}
let x = 5;
let y = &x;
let z = &x;
```
Mutable ones, however, are not:
```{rust,ignore}
let mut x = 5;
let y = &mut x;
let z = &mut x; // error: cannot borrow `x` as mutable more than once at a time
```
Despite their complete safety, a reference's representation at runtime is the
same as that of an ordinary pointer in a C program. They introduce zero
overhead. The compiler does all safety checks at compile time. The theory that
allows for this was originally called *region pointers*. Region pointers
evolved into what we know today as *lifetimes*.
Here's the simple explanation: would you expect this code to compile?
```{rust,ignore}
fn main() {
println!("{}", x);
let x = 5;
}
```
Probably not. That's because you know that the name `x` is valid from where
it's declared to when it goes out of scope. In this case, that's the end of
the `main` function. So you know this code will cause an error. We call this
duration a *lifetime*. Let's try a more complex example:
```{rust}
fn main() {
let mut x = 5;
if x < 10 {
let y = &x;
println!("Oh no: {}", y);
return;
}
x -= 1;
println!("Oh no: {}", x);
}
```
Here, we're borrowing a pointer to `x` inside of the `if`. The compiler, however,
is able to determine that that pointer will go out of scope without `x` being
mutated, and therefore, lets us pass. This wouldn't work:
```{rust,ignore}
fn main() {
let mut x = 5;
if x < 10 {
let y = &x;
x -= 1;
println!("Oh no: {}", y);
return;
}
x -= 1;
println!("Oh no: {}", x);
}
```
It gives this error:
```text
test.rs:7:9: 7:15 error: cannot assign to `x` because it is borrowed
test.rs:7 x -= 1;
^~~~~~
test.rs:5:18: 5:19 note: borrow of `x` occurs here
test.rs:5 let y = &x;
^
```
As you might guess, this kind of analysis is complex for a human, and therefore
hard for a computer, too! There is an entire [guide devoted to references, ownership,
and lifetimes](ownership.html) that goes into this topic in
great detail, so if you want the full details, check that out.
## Best practices
In general, prefer stack allocation over heap allocation. Using references to
stack allocated information is preferred whenever possible. Therefore,
references are the default pointer type you should use, unless you have a
specific reason to use a different type. The other types of pointers cover when
they're appropriate to use in their own best practices sections.
Use references when you want to use a pointer, but do not want to take ownership.
References just borrow ownership, which is more polite if you don't need the
ownership. In other words, prefer:
```{rust}
fn succ(x: &i32) -> i32 { *x + 1 }
```
to
```{rust}
fn succ(x: Box<i32>) -> i32 { *x + 1 }
```
As a corollary to that rule, references allow you to accept a wide variety of
other pointers, and so are useful so that you don't have to write a number
of variants per pointer. In other words, prefer:
```{rust}
fn succ(x: &i32) -> i32 { *x + 1 }
```
to
```{rust}
use std::rc::Rc;
fn box_succ(x: Box<i32>) -> i32 { *x + 1 }
fn rc_succ(x: Rc<i32>) -> i32 { *x + 1 }
```
Note that the caller of your function will have to modify their calls slightly:
```{rust}
use std::rc::Rc;
fn succ(x: &i32) -> i32 { *x + 1 }
let ref_x = &5;
let box_x = Box::new(5);
let rc_x = Rc::new(5);
succ(ref_x);
succ(&*box_x);
succ(&*rc_x);
```
The initial `*` dereferences the pointer, and then `&` takes a reference to
those contents.
# Boxes
`Box<T>` is Rust's *boxed pointer* type. Boxes provide the simplest form of
heap allocation in Rust. Creating a box looks like this:
```{rust}
let x = Box::new(5);
```
Boxes are heap allocated and they are deallocated automatically by Rust when
they go out of scope:
```{rust}
{
let x = Box::new(5);
// stuff happens
} // x is destructed and its memory is free'd here
```
However, boxes do _not_ use reference counting or garbage collection. Boxes are
what's called an *affine type*. This means that the Rust compiler, at compile
time, determines when the box comes into and goes out of scope, and inserts the
appropriate calls there.
You don't need to fully grok the theory of affine types to grok boxes, though.
As a rough approximation, you can treat this Rust code:
```{rust}
{
let x = Box::new(5);
// stuff happens
}
```
As being similar to this C code:
```c
{
int *x;
x = (int *)malloc(sizeof(int));
*x = 5;
// stuff happens
free(x);
}
```
Of course, this is a 10,000 foot view. It leaves out destructors, for example.
But the general idea is correct: you get the semantics of `malloc`/`free`, but
with some improvements:
1. It's impossible to allocate the incorrect amount of memory, because Rust
figures it out from the types.
2. You cannot forget to `free` memory you've allocated, because Rust does it
for you.
3. Rust ensures that this `free` happens at the right time, when it is truly
not used. Use-after-free is not possible.
4. Rust enforces that no other writeable pointers alias to this heap memory,
which means writing to an invalid pointer is not possible.
See the section on references or the [ownership guide](ownership.html)
for more detail on how lifetimes work.
Using boxes and references together is very common. For example:
```{rust}
fn add_one(x: &i32) -> i32 {
*x + 1
}
fn main() {
let x = Box::new(5);
println!("{}", add_one(&*x));
}
```
In this case, Rust knows that `x` is being *borrowed* by the `add_one()`
function, and since it's only reading the value, allows it.
We can borrow `x` as read-only multiple times, even simultaneously:
```{rust}
fn add(x: &i32, y: &i32) -> i32 {
*x + *y
}
fn main() {
let x = Box::new(5);
println!("{}", add(&*x, &*x));
println!("{}", add(&*x, &*x));
}
```
We can mutably borrow `x` multiple times, but only if x itself is mutable, and
it may not be *simultaneously* borrowed:
```{rust,ignore}
fn increment(x: &mut i32) {
*x += 1;
}
fn main() {
// If variable x is not "mut", this will not compile
let mut x = Box::new(5);
increment(&mut x);
increment(&mut x);
println!("{}", x);
}
```
Notice the signature of `increment()` requests a mutable reference.
## Best practices
Boxes are most appropriate to use when defining recursive data structures.
### Recursive data structures
Sometimes, you need a recursive data structure. The simplest is known as a
*cons list*:
```{rust}
#[derive(Debug)]
enum List<T> {
Cons(T, Box<List<T>>),
Nil,
}
fn main() {
let list: List<i32> = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Cons(3, Box::new(List::Nil))))));
println!("{:?}", list);
}
```
This prints:
```text
Cons(1, Box(Cons(2, Box(Cons(3, Box(Nil))))))
```
The reference to another `List` inside of the `Cons` enum variant must be a box,
because we don't know the length of the list. Because we don't know the length,
we don't know the size, and therefore, we need to heap allocate our list.
Working with recursive or other unknown-sized data structures is the primary
use-case for boxes.
# Rc and Arc
This part is coming soon.
## Best practices
This part is coming soon.
# Raw Pointers
This part is coming soon.
## Best practices
This part is coming soon.
# Creating your own Pointers
This part is coming soon.
## Best practices
This part is coming soon.
# Patterns and `ref`
When you're trying to match something that's stored in a pointer, there may be
a situation where matching directly isn't the best option available. Let's see
how to properly handle this:
```{rust,ignore}
fn possibly_print(x: &Option<String>) {
match *x {
// BAD: cannot move out of a `&`
Some(s) => println!("{}", s)
// GOOD: instead take a reference into the memory of the `Option`
Some(ref s) => println!("{}", *s),
None => {}
}
}
```
The `ref s` here means that `s` will be of type `&String`, rather than type
`String`.
This is important when the type you're trying to get access to has a destructor
and you don't want to move it, you just want a reference to it.
# Cheat Sheet
Here's a quick rundown of Rust's pointer types:
| Type | Name | Summary |
|--------------|---------------------|---------------------------------------------------------------------|
| `&T` | Reference | Allows one or more references to read `T` |
| `&mut T` | Mutable Reference | Allows a single reference to read and write `T` |
| `Box<T>` | Box | Heap allocated `T` with a single owner that may read and write `T`. |
| `Rc<T>` | "arr cee" pointer | Heap allocated `T` with many readers |
| `Arc<T>` | Arc pointer | Same as above, but safe sharing across threads |
| `*const T` | Raw pointer | Unsafe read access to `T` |
| `*mut T` | Mutable raw pointer | Unsafe read and write access to `T` |
# Related resources
* [API documentation for Box](../std/boxed/index.html)
* [Ownership guide](ownership.html)
* [Cyclone paper on regions](http://www.cs.umd.edu/projects/cyclone/papers/cyclone-regions.pdf), which inspired Rust's lifetime system

View File

@ -0,0 +1,3 @@
% Primitive Types
Coming Soon!

View File

@ -0,0 +1,3 @@
% References and Borrowing
Coming Soon!

21
src/doc/trpl/slices.md Normal file
View File

@ -0,0 +1,21 @@
% Slices
A *slice* is a reference to (or "view" into) an array. They are useful for
allowing safe, efficient access to a portion of an array without copying. For
example, you might want to reference just one line of a file read into memory.
By nature, a slice is not created directly, but from an existing variable.
Slices have a length, can be mutable or not, and in many ways behave like
arrays:
```{rust}
let a = [0, 1, 2, 3, 4];
let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3
for e in middle.iter() {
println!("{}", e); // Prints 1, 2, 3
}
```
You can also take a slice of a vector, `String`, or `&str`, because they are
backed by arrays. Slices have type `&[T]`, which we'll talk about when we cover
generics.

3
src/doc/trpl/static.md Normal file
View File

@ -0,0 +1,3 @@
% `static`
Coming soon!

49
src/doc/trpl/structs.md Normal file
View File

@ -0,0 +1,49 @@
% Structs
A struct is another form of a *record type*, just like a tuple. There's a
difference: structs give each element that they contain a name, called a
*field* or a *member*. Check it out:
```rust
struct Point {
x: i32,
y: i32,
}
fn main() {
let origin = Point { x: 0, y: 0 }; // origin: Point
println!("The origin is at ({}, {})", origin.x, origin.y);
}
```
There's a lot going on here, so let's break it down. We declare a struct with
the `struct` keyword, and then with a name. By convention, structs begin with a
capital letter and are also camel cased: `PointInSpace`, not `Point_In_Space`.
We can create an instance of our struct via `let`, as usual, but we use a `key:
value` style syntax to set each field. The order doesn't need to be the same as
in the original declaration.
Finally, because fields have names, we can access the field through dot
notation: `origin.x`.
The values in structs are immutable by default, like other bindings in Rust.
Use `mut` to make them mutable:
```{rust}
struct Point {
x: i32,
y: i32,
}
fn main() {
let mut point = Point { x: 0, y: 0 };
point.x = 5;
println!("The point is at ({}, {})", point.x, point.y);
}
```
This will print `The point is at (5, 0)`.

View File

@ -0,0 +1 @@
% Syntax and Semantics

View File

@ -0,0 +1,3 @@
% The Stack and the Heap
Coming Soon

View File

@ -1,91 +0,0 @@
% Tracing Macros
The `trace_macros` feature allows you to use a special feature: tracing macro
invocations.
In the advanced macros chapter, we defined a `bct` macro:
```rust
macro_rules! bct {
// cmd 0: d ... => ...
(0, $($ps:tt),* ; $_d:tt)
=> (bct!($($ps),*, 0 ; ));
(0, $($ps:tt),* ; $_d:tt, $($ds:tt),*)
=> (bct!($($ps),*, 0 ; $($ds),*));
// cmd 1p: 1 ... => 1 ... p
(1, $p:tt, $($ps:tt),* ; 1)
=> (bct!($($ps),*, 1, $p ; 1, $p));
(1, $p:tt, $($ps:tt),* ; 1, $($ds:tt),*)
=> (bct!($($ps),*, 1, $p ; 1, $($ds),*, $p));
// cmd 1p: 0 ... => 0 ...
(1, $p:tt, $($ps:tt),* ; $($ds:tt),*)
=> (bct!($($ps),*, 1, $p ; $($ds),*));
// halt on empty data string
( $($ps:tt),* ; )
=> (());
}
```
This is pretty complex! we can see the output
```rust,ignore
#![feature(trace_macros)]
macro_rules! bct {
// cmd 0: d ... => ...
(0, $($ps:tt),* ; $_d:tt)
=> (bct!($($ps),*, 0 ; ));
(0, $($ps:tt),* ; $_d:tt, $($ds:tt),*)
=> (bct!($($ps),*, 0 ; $($ds),*));
// cmd 1p: 1 ... => 1 ... p
(1, $p:tt, $($ps:tt),* ; 1)
=> (bct!($($ps),*, 1, $p ; 1, $p));
(1, $p:tt, $($ps:tt),* ; 1, $($ds:tt),*)
=> (bct!($($ps),*, 1, $p ; 1, $($ds),*, $p));
// cmd 1p: 0 ... => 0 ...
(1, $p:tt, $($ps:tt),* ; $($ds:tt),*)
=> (bct!($($ps),*, 1, $p ; $($ds),*));
// halt on empty data string
( $($ps:tt),* ; )
=> (());
}
fn main() {
trace_macros!(true);
bct!(0, 0, 1, 1, 1 ; 1, 0, 1);
}
```
This will print out a wall of text:
```text
bct! { 0 , 0 , 1 , 1 , 1 ; 1 , 0 , 1 }
bct! { 0 , 1 , 1 , 1 , 0 ; 0 , 1 }
bct! { 1 , 1 , 1 , 0 , 0 ; 1 }
bct! { 1 , 0 , 0 , 1 , 1 ; 1 , 1 }
bct! { 0 , 1 , 1 , 1 , 0 ; 1 , 1 , 0 }
bct! { 1 , 1 , 1 , 0 , 0 ; 1 , 0 }
bct! { 1 , 0 , 0 , 1 , 1 ; 1 , 0 , 1 }
bct! { 0 , 1 , 1 , 1 , 0 ; 1 , 0 , 1 , 0 }
bct! { 1 , 1 , 1 , 0 , 0 ; 0 , 1 , 0 }
bct! { 1 , 0 , 0 , 1 , 1 ; 0 , 1 , 0 }
bct! { 0 , 1 , 1 , 1 , 0 ; 0 , 1 , 0 }
```
And eventually, error:
```text
18:45 error: recursion limit reached while expanding the macro `bct`
=> (bct!($($ps),*, 1, $p ; $($ds),*));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
The `trace_macros!` call is what produces this output, showing how we match
each time.

View File

@ -1,4 +1,4 @@
% Static and Dynamic Dispatch
% Trait Objects
When code involves polymorphism, there needs to be a mechanism to determine
which specific version is actually run. This is called 'dispatch.' There are

View File

@ -0,0 +1,56 @@
% Tuple Structs
Rust has another data type that's like a hybrid between a tuple and a struct,
called a *tuple struct*. Tuple structs do have a name, but their fields don't:
```{rust}
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
```
These two will not be equal, even if they have the same values:
```{rust}
# struct Color(i32, i32, i32);
# struct Point(i32, i32, i32);
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
```
It is almost always better to use a struct than a tuple struct. We would write
`Color` and `Point` like this instead:
```{rust}
struct Color {
red: i32,
blue: i32,
green: i32,
}
struct Point {
x: i32,
y: i32,
z: i32,
}
```
Now, we have actual names, rather than positions. Good names are important,
and with a struct, we have actual names.
There _is_ one case when a tuple struct is very useful, though, and that's a
tuple struct with only one element. We call this the *newtype* pattern, because
it allows you to create a new type, distinct from that of its contained value
and expressing its own semantic meaning:
```{rust}
struct Inches(i32);
let length = Inches(10);
let Inches(integer_length) = length;
println!("length is {} inches", integer_length);
```
As you can see here, you can extract the inner integer type through a
destructuring `let`, as we discussed previously in 'tuples.' In this case, the
`let Inches(integer_length)` assigns `10` to `integer_length`.

97
src/doc/trpl/tuples.md Normal file
View File

@ -0,0 +1,97 @@
% Tuples
The first compound data type we're going to talk about is called the *tuple*.
A tuple is an ordered list of fixed size. Like this:
```rust
let x = (1, "hello");
```
The parentheses and commas form this two-length tuple. Here's the same code, but
with the type annotated:
```rust
let x: (i32, &str) = (1, "hello");
```
As you can see, the type of a tuple looks just like the tuple, but with each
position having a type name rather than the value. Careful readers will also
note that tuples are heterogeneous: we have an `i32` and a `&str` in this tuple.
You have briefly seen `&str` used as a type before, and we'll discuss the
details of strings later. In systems programming languages, strings are a bit
more complex than in other languages. For now, just read `&str` as a *string
slice*, and we'll learn more soon.
You can access the fields in a tuple through a *destructuring let*. Here's
an example:
```rust
let (x, y, z) = (1, 2, 3);
println!("x is {}", x);
```
Remember before when I said the left-hand side of a `let` statement was more
powerful than just assigning a binding? Here we are. We can put a pattern on
the left-hand side of the `let`, and if it matches up to the right-hand side,
we can assign multiple bindings at once. In this case, `let` "destructures,"
or "breaks up," the tuple, and assigns the bits to three bindings.
This pattern is very powerful, and we'll see it repeated more later.
There are also a few things you can do with a tuple as a whole, without
destructuring. You can assign one tuple into another, if they have the same
contained types and [arity]. Tuples have the same arity when they have the same
length.
```rust
let mut x = (1, 2); // x: (i32, i32)
let y = (2, 3); // y: (i32, i32)
x = y;
```
You can also check for equality with `==`. Again, this will only compile if the
tuples have the same type.
```rust
let x = (1, 2, 3);
let y = (2, 2, 4);
if x == y {
println!("yes");
} else {
println!("no");
}
```
This will print `no`, because some of the values aren't equal.
Note that the order of the values is considered when checking for equality,
so the following example will also print `no`.
```rust
let x = (1, 2, 3);
let y = (2, 1, 3);
if x == y {
println!("yes");
} else {
println!("no");
}
```
One other use of tuples is to return multiple values from a function:
```rust
fn next_two(x: i32) -> (i32, i32) { (x + 1, x + 2) }
fn main() {
let (x, y) = next_two(5);
println!("x, y = {}, {}", x, y);
}
```
Even though Rust functions can only return one value, a tuple *is* one value,
that happens to be made up of more than one value. You can also see in this
example how you can destructure a pattern returned by a function, as well.

View File

@ -0,0 +1,3 @@
% `type` Aliases
Coming soon

3
src/doc/trpl/ufcs.md Normal file
View File

@ -0,0 +1,3 @@
% Universal Function Call Syntax
Coming soon

View File

@ -1,4 +1,4 @@
% Unsafe and Low-Level Code
% Unsafe Code
# Introduction

View File

@ -0,0 +1,3 @@
% Unsized Types
Coming Soon!

33
src/doc/trpl/vectors.md Normal file
View File

@ -0,0 +1,33 @@
% Vectors
A *vector* is a dynamic or "growable" array, implemented as the standard
library type [`Vec<T>`](../std/vec/) (we'll talk about what the `<T>` means
later). Vectors always allocate their data on the heap. Vectors are to slices
what `String` is to `&str`. You can create them with the `vec!` macro:
```{rust}
let v = vec![1, 2, 3]; // v: Vec<i32>
```
(Notice that unlike the `println!` macro we've used in the past, we use square
brackets `[]` with `vec!`. Rust allows you to use either in either situation,
this is just convention.)
There's an alternate form of `vec!` for repeating an initial value:
```
let v = vec![0; 10]; // ten zeroes
```
You can get the length of, iterate over, and subscript vectors just like
arrays. In addition, (mutable) vectors can grow automatically:
```{rust}
let mut nums = vec![1, 2, 3]; // mut nums: Vec<i32>
nums.push(4);
println!("The length of nums is now {}", nums.len()); // Prints 4
```
Vectors have many more useful methods.

View File

@ -1,54 +1,4 @@
% Looping
Looping is the last basic construct that we haven't learned yet in Rust. Rust has
two main looping constructs: `for` and `while`.
## `for`
The `for` loop is used to loop a particular number of times. Rust's `for` loops
work a bit differently than in other systems languages, however. Rust's `for`
loop doesn't look like this "C-style" `for` loop:
```{c}
for (x = 0; x < 10; x++) {
printf( "%d\n", x );
}
```
Instead, it looks like this:
```{rust}
for x in 0..10 {
println!("{}", x); // x: i32
}
```
In slightly more abstract terms,
```{ignore}
for var in expression {
code
}
```
The expression is an iterator, which we will discuss in more depth later in the
guide. The iterator gives back a series of elements. Each element is one
iteration of the loop. That value is then bound to the name `var`, which is
valid for the loop body. Once the body is over, the next value is fetched from
the iterator, and we loop another time. When there are no more values, the
`for` loop is over.
In our example, `0..10` is an expression that takes a start and an end position,
and gives an iterator over those values. The upper bound is exclusive, though,
so our loop will print `0` through `9`, not `10`.
Rust does not have the "C-style" `for` loop on purpose. Manually controlling
each element of the loop is complicated and error prone, even for experienced C
developers.
We'll talk more about `for` when we cover *iterators*, later in the Guide.
## `while`
% `while` loops
The other kind of looping construct in Rust is the `while` loop. It looks like
this:

View File

@ -10,51 +10,134 @@
#![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! {
E0001: r##"
This error suggests that the expression arm corresponding to the noted pattern
will never be reached as for all possible values of the expression being matched,
one of the preceding patterns will match.
This means that perhaps some of the preceding patterns are too general, this
one is too specific or the ordering is incorrect.
E0001: r##"
This error suggests that the expression arm corresponding to the noted pattern
will never be reached as for all possible values of the expression being
matched, one of the preceding patterns will match.
This means that perhaps some of the preceding patterns are too general, this one
is too specific or the ordering is incorrect.
"##,
E0003: r##"
Not-a-Number (NaN) values can not be compared for equality and hence can never match
the input to a match expression. To match against NaN values, you should instead use
the `is_nan` method in a guard, as in: x if x.is_nan() => ...
E0002: r##"
This error indicates that an empty match expression is illegal because the type
it is matching on is non-empty (there exist values of this type). In safe code
it is impossible to create an instance of an empty type, so empty match
expressions are almost never desired. This error is typically fixed by adding
one or more cases to the match expression.
An example of an empty type is `enum Empty { }`.
"##,
E0004: r##"
This error indicates that the compiler can not guarantee a matching pattern for one
or more possible inputs to a match expression. Guaranteed matches are required in order
to assign values to match expressions, or alternatively, determine the flow of execution.
If you encounter this error you must alter your patterns so that every possible value of
the input type is matched. For types with a small number of variants (like enums) you
should probably cover all cases explicitly. Alternatively, the underscore `_` wildcard
pattern can be added after all other patterns to match "anything else".
E0003: r##"
Not-a-Number (NaN) values cannot be compared for equality and hence can never
match the input to a match expression. To match against NaN values, you should
instead use the `is_nan` method in a guard, as in: x if x.is_nan() => ...
"##,
// FIXME: Remove duplication here?
E0005: r##"
Patterns used to bind names must be irrefutable, that is, they must guarantee that a
name will be extracted in all cases. If you encounter this error you probably need
to use a `match` or `if let` to deal with the possibility of failure.
E0004: r##"
This error indicates that the compiler cannot guarantee a matching pattern for
one or more possible inputs to a match expression. Guaranteed matches are
required in order to assign values to match expressions, or alternatively,
determine the flow of execution.
If you encounter this error you must alter your patterns so that every possible
value of the input type is matched. For types with a small number of variants
(like enums) you should probably cover all cases explicitly. Alternatively, the
underscore `_` wildcard pattern can be added after all other patterns to match
"anything else".
"##,
E0006: r##"
Patterns used to bind names must be irrefutable, that is, they must guarantee that a
name will be extracted in all cases. If you encounter this error you probably need
to use a `match` or `if let` to deal with the possibility of failure.
// FIXME: Remove duplication here?
E0005: r##"
Patterns used to bind names must be irrefutable, that is, they must guarantee that a
name will be extracted in all cases. If you encounter this error you probably need
to use a `match` or `if let` to deal with the possibility of failure.
"##,
E0006: r##"
Patterns used to bind names must be irrefutable, that is, they must guarantee that a
name will be extracted in all cases. If you encounter this error you probably need
to use a `match` or `if let` to deal with the possibility of failure.
"##,
E0007: r##"
This error indicates that the bindings in a match arm would require a value to
be moved into more than one location, thus violating unique ownership. Code like
the following is invalid as it requires the entire Option<String> to be moved
into a variable called `op_string` while simultaneously requiring the inner
String to be moved into a variable called `s`.
let x = Some("s".to_string());
match x {
op_string @ Some(s) => ...
None => ...
}
See also Error 303.
"##,
E0008: r##"
Names bound in match arms retain their type in pattern guards. As such, if a
name is bound by move in a pattern, it should also be moved to wherever it is
referenced in the pattern guard code. Doing so however would prevent the name
from being available in the body of the match arm. Consider the following:
match Some("hi".to_string()) {
Some(s) if s.len() == 0 => // use s.
...
}
The variable `s` has type String, and its use in the guard is as a variable of
type String. The guard code effectively executes in a separate scope to the body
of the arm, so the value would be moved into this anonymous scope and therefore
become unavailable in the body of the arm. Although this example seems
innocuous, the problem is most clear when considering functions that take their
argument by value.
match Some("hi".to_string()) {
Some(s) if { drop(s); false } => (),
Some(s) => // use s.
...
}
The value would be dropped in the guard then become unavailable not only in the
body of that arm but also in all subsequent arms! The solution is to bind by
reference when using guards or refactor the entire expression, perhaps by
putting the condition inside the body of the arm.
"##,
E0303: r##"
In certain cases it is possible for sub-bindings to violate memory safety.
Updates to the borrow checker in a future version of Rust may remove this
restriction, but for now patterns must be rewritten without sub-bindings.
// Code like this...
match Some(5) {
ref op_num @ Some(num) => ...
None => ...
}
// ... should be updated to code like this.
match Some(5) {
Some(num) => {
let op_num = &Some(num);
...
}
None => ...
}
See also https://github.com/rust-lang/rust/issues/14587
"##
}
register_diagnostics! {
E0002,
E0007,
E0008,
E0009,
E0010,
E0011,
@ -117,7 +200,6 @@ register_diagnostics! {
E0300, // unexpanded macro
E0301, // cannot mutable borrow in a pattern guard
E0302, // cannot assign in a pattern guard
E0303, // pattern bindings are not allowed after an `@`
E0304, // expected signed integer constant
E0305, // expected constant
E0306, // expected positive integer for repeat count

View File

@ -277,7 +277,8 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
Some(ref code) => {
match descriptions.find_description(&code[..]) {
Some(ref description) => {
println!("{}", description);
// Slice off the leading newline and print.
print!("{}", &description[1..]);
}
None => {
early_error(&format!("no extended information for {}", code));

View File

@ -112,58 +112,6 @@
//! });
//! rx.recv().unwrap();
//! ```
//!
//! Reading from a channel with a timeout requires to use a Timer together
//! with the channel. You can use the `select!` macro to select either and
//! handle the timeout case. This first example will break out of the loop
//! after 10 seconds no matter what:
//!
//! ```no_run
//! # #![feature(std_misc, old_io)]
//! use std::sync::mpsc::channel;
//! use std::old_io::timer::Timer;
//! use std::time::Duration;
//!
//! let (tx, rx) = channel::<i32>();
//! let mut timer = Timer::new().unwrap();
//! let timeout = timer.oneshot(Duration::seconds(10));
//!
//! loop {
//! select! {
//! val = rx.recv() => println!("Received {}", val.unwrap()),
//! _ = timeout.recv() => {
//! println!("timed out, total time was more than 10 seconds");
//! break;
//! }
//! }
//! }
//! ```
//!
//! This second example is more costly since it allocates a new timer every
//! time a message is received, but it allows you to timeout after the channel
//! has been inactive for 5 seconds:
//!
//! ```no_run
//! # #![feature(std_misc, old_io)]
//! use std::sync::mpsc::channel;
//! use std::old_io::timer::Timer;
//! use std::time::Duration;
//!
//! let (tx, rx) = channel::<i32>();
//! let mut timer = Timer::new().unwrap();
//!
//! loop {
//! let timeout = timer.oneshot(Duration::seconds(5));
//!
//! select! {
//! val = rx.recv() => println!("Received {}", val.unwrap()),
//! _ = timeout.recv() => {
//! println!("timed out, no message received in 5 seconds");
//! break;
//! }
//! }
//! }
//! ```
#![stable(feature = "rust1", since = "1.0.0")]