remove first edition content

This commit is contained in:
Steve Klabnik 2018-11-20 16:20:32 -05:00
parent fc4274d906
commit 768a389337
58 changed files with 343 additions and 16954 deletions

View File

@ -1,39 +1,10 @@
# The Rust Programming Language
Welcome! This book will teach you about the [Rust Programming Language][rust].
Rust is a systems programming language focused on three goals: safety, speed,
and concurrency. It maintains these goals without having a garbage collector,
making it a useful language for a number of use cases other languages arent
good at: embedding in other languages, programs with specific space and time
requirements, and writing low-level code, like device drivers and operating
systems. It improves on current languages targeting this space by having a
number of compile-time safety checks that produce no runtime overhead, while
eliminating all data races. Rust also aims to achieve zero-cost abstractions
even though some of these abstractions feel like those of a high-level language.
Even then, Rust still allows precise control like a low-level language would.
The first edition of the book is no longer distributed with Rust's documentation.
[rust]: https://www.rust-lang.org
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
“The Rust Programming Language” is split into chapters. This introduction
is the first. After this:
* [Getting started][gs] - Set up your computer for Rust development.
* [Tutorial: Guessing Game][gg] - Learn some Rust with a small project.
* [Syntax and Semantics][ss] - Each bit of Rust, broken down into small chunks.
* [Effective Rust][er] - Higher-level concepts for writing excellent Rust code.
* [Glossary][gl] - A reference of terms used in the book.
* [Bibliography][bi] - Background on Rust's influences, papers about Rust.
[gs]: getting-started.html
[gg]: guessing-game.html
[er]: effective-rust.html
[ss]: syntax-and-semantics.html
[gl]: glossary.html
[bi]: bibliography.html
## Source Code
The source files from which this book is generated can be found on
[GitHub][book].
[book]: https://github.com/rust-lang/book/tree/master/first-edition/src
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/README.html).

View File

@ -1,202 +1,10 @@
# Associated Types
Associated types are a powerful part of Rusts type system. Theyre related to
the idea of a type family, in other words, grouping multiple types together. That
description is a bit abstract, so lets dive right into an example. If you want
to write a `Graph` trait, you have two types to be generic over: the node type
and the edge type. So you might write a trait, `Graph<N, E>`, that looks like
this:
The first edition of the book is no longer distributed with Rust's documentation.
```rust
trait Graph<N, E> {
fn has_edge(&self, &N, &N) -> bool;
fn edges(&self, &N) -> Vec<E>;
// Etc.
}
```
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
While this sort of works, it ends up being awkward. For example, any function
that wants to take a `Graph` as a parameter now _also_ needs to be generic over
the `N`ode and `E`dge types too:
```rust,ignore
fn distance<N, E, G: Graph<N, E>>(graph: &G, start: &N, end: &N) -> u32 { ... }
```
Our distance calculation works regardless of our `Edge` type, so the `E` stuff in
this signature is a distraction.
What we really want to say is that a certain `E`dge and `N`ode type come together
to form each kind of `Graph`. We can do that with associated types:
```rust
trait Graph {
type N;
type E;
fn has_edge(&self, &Self::N, &Self::N) -> bool;
fn edges(&self, &Self::N) -> Vec<Self::E>;
// Etc.
}
```
Now, our clients can be abstract over a given `Graph`:
```rust,ignore
fn distance<G: Graph>(graph: &G, start: &G::N, end: &G::N) -> u32 { ... }
```
No need to deal with the `E`dge type here!
Lets go over all this in more detail.
## Defining associated types
Lets build that `Graph` trait. Heres the definition:
```rust
trait Graph {
type N;
type E;
fn has_edge(&self, &Self::N, &Self::N) -> bool;
fn edges(&self, &Self::N) -> Vec<Self::E>;
}
```
Simple enough. Associated types use the `type` keyword, and go inside the body
of the trait, with the functions.
These type declarations work the same way as those for functions. For example,
if we wanted our `N` type to implement `Display`, so we can print the nodes out,
we could do this:
```rust
use std::fmt;
trait Graph {
type N: fmt::Display;
type E;
fn has_edge(&self, &Self::N, &Self::N) -> bool;
fn edges(&self, &Self::N) -> Vec<Self::E>;
}
```
## Implementing associated types
Just like any trait, traits that use associated types use the `impl` keyword to
provide implementations. Heres a simple implementation of Graph:
```rust
# trait Graph {
# type N;
# type E;
# fn has_edge(&self, &Self::N, &Self::N) -> bool;
# fn edges(&self, &Self::N) -> Vec<Self::E>;
# }
struct Node;
struct Edge;
struct MyGraph;
impl Graph for MyGraph {
type N = Node;
type E = Edge;
fn has_edge(&self, n1: &Node, n2: &Node) -> bool {
true
}
fn edges(&self, n: &Node) -> Vec<Edge> {
Vec::new()
}
}
```
This silly implementation always returns `true` and an empty `Vec<Edge>`, but it
gives you an idea of how to implement this kind of thing. We first need three
`struct`s, one for the graph, one for the node, and one for the edge. If it made
more sense to use a different type, that would work as well, were going to
use `struct`s for all three here.
Next is the `impl` line, which is an implementation like any other trait.
From here, we use `=` to define our associated types. The name the trait uses
goes on the left of the `=`, and the concrete type were `impl`ementing this
for goes on the right. Finally, we use the concrete types in our function
declarations.
## Trait objects with associated types
Theres one more bit of syntax we should talk about: trait objects. If you
try to create a trait object from a trait with an associated type, like this:
```rust,ignore
# trait Graph {
# type N;
# type E;
# fn has_edge(&self, &Self::N, &Self::N) -> bool;
# fn edges(&self, &Self::N) -> Vec<Self::E>;
# }
# struct Node;
# struct Edge;
# struct MyGraph;
# impl Graph for MyGraph {
# type N = Node;
# type E = Edge;
# fn has_edge(&self, n1: &Node, n2: &Node) -> bool {
# true
# }
# fn edges(&self, n: &Node) -> Vec<Edge> {
# Vec::new()
# }
# }
let graph = MyGraph;
let obj = Box::new(graph) as Box<Graph>;
```
Youll get two errors:
```text
error: the value of the associated type `E` (from the trait `main::Graph`) must
be specified [E0191]
let obj = Box::new(graph) as Box<Graph>;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24:44 error: the value of the associated type `N` (from the trait
`main::Graph`) must be specified [E0191]
let obj = Box::new(graph) as Box<Graph>;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
We cant create a trait object like this, because we dont know the associated
types. Instead, we can write this:
```rust
# trait Graph {
# type N;
# type E;
# fn has_edge(&self, &Self::N, &Self::N) -> bool;
# fn edges(&self, &Self::N) -> Vec<Self::E>;
# }
# struct Node;
# struct Edge;
# struct MyGraph;
# impl Graph for MyGraph {
# type N = Node;
# type E = Edge;
# fn has_edge(&self, n1: &Node, n2: &Node) -> bool {
# true
# }
# fn edges(&self, n: &Node) -> Vec<Edge> {
# Vec::new()
# }
# }
let graph = MyGraph;
let obj = Box::new(graph) as Box<Graph<N=Node, E=Edge>>;
```
The `N=Node` syntax allows us to provide a concrete type, `Node`, for the `N`
type parameter. Same with `E=Edge`. If we didnt provide this constraint, we
couldnt be sure which `impl` to match this trait object to.
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/associated-types.html).

View File

@ -1,70 +1,10 @@
# Attributes
Declarations can be annotated with attributes in Rust. They look like this:
The first edition of the book is no longer distributed with Rust's documentation.
```rust
#[test]
# fn foo() {}
```
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
or like this:
```rust
# mod foo {
#![test]
# }
```
The difference between the two is the `!`, which changes what the attribute
applies to:
```rust,ignore
#[foo]
struct Foo;
mod bar {
#![bar]
}
```
The `#[foo]` attribute applies to the next item, which is the `struct`
declaration. The `#![bar]` attribute applies to the item enclosing it, which is
the `mod` declaration. Otherwise, theyre the same. Both change the meaning of
the item theyre attached to somehow.
For example, consider a function like this:
```rust
#[test]
fn check() {
assert_eq!(2, 1 + 1);
}
```
It is marked with `#[test]`. This means its special: when you run
[tests][tests], this function will execute. When you compile as usual, it wont
even be included. This function is now a test function.
[tests]: testing.html
Attributes may also have additional data:
```rust
#[inline(always)]
fn super_fast_fn() {
# }
```
Or even keys and values:
```rust
#[cfg(target_os = "macos")]
mod macos_only {
# }
```
Rust attributes are used for a number of different things. There is a full list
of attributes [in the reference][reference]. Currently, you are not allowed to
create your own attributes, the Rust compiler defines them.
[reference]: ../../reference/attributes.html
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/attributes.html).

View File

@ -1,83 +1,10 @@
# Bibliography
This is a reading list of material relevant to Rust. It includes prior
research that has - at one time or another - influenced the design of
Rust, as well as publications about Rust.
The first edition of the book is no longer distributed with Rust's documentation.
### Type system
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
* [Region based memory management in Cyclone](http://209.68.42.137/ucsd-pages/Courses/cse227.w03/handouts/cyclone-regions.pdf)
* [Safe manual memory management in Cyclone](http://www.cs.umd.edu/projects/PL/cyclone/scp.pdf)
* [Typeclasses: making ad-hoc polymorphism less ad hoc](http://www.ps.uni-sb.de/courses/typen-ws99/class.ps.gz)
* [Macros that work together](https://www.cs.utah.edu/plt/publications/jfp12-draft-fcdf.pdf)
* [Traits: composable units of behavior](http://scg.unibe.ch/archive/papers/Scha03aTraits.pdf)
* [Alias burying](http://www.cs.uwm.edu/faculty/boyland/papers/unique-preprint.ps) - We tried something similar and abandoned it.
* [External uniqueness is unique enough](http://www.cs.uu.nl/research/techreps/UU-CS-2002-048.html)
* [Uniqueness and Reference Immutability for Safe Parallelism](https://research.microsoft.com/pubs/170528/msr-tr-2012-79.pdf)
* [Region Based Memory Management](http://www.cs.ucla.edu/~palsberg/tba/papers/tofte-talpin-iandc97.pdf)
### Concurrency
* [Singularity: rethinking the software stack](https://research.microsoft.com/pubs/69431/osr2007_rethinkingsoftwarestack.pdf)
* [Language support for fast and reliable message passing in singularity OS](https://research.microsoft.com/pubs/67482/singsharp.pdf)
* [Scheduling multithreaded computations by work stealing](http://supertech.csail.mit.edu/papers/steal.pdf)
* [Thread scheduling for multiprogramming multiprocessors](http://www.eecis.udel.edu/%7Ecavazos/cisc879-spring2008/papers/arora98thread.pdf)
* [The data locality of work stealing](http://www.aladdin.cs.cmu.edu/papers/pdfs/y2000/locality_spaa00.pdf)
* [Dynamic circular work stealing deque](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.170.1097&rep=rep1&type=pdf) - The Chase/Lev deque
* [Work-first and help-first scheduling policies for async-finish task parallelism](http://www.cs.rice.edu/%7Eyguo/pubs/PID824943.pdf) - More general than fully-strict work stealing
* [A Java fork/join calamity](http://www.coopsoft.com/ar/CalamityArticle.html) - critique of Java's fork/join library, particularly its application of work stealing to non-strict computation
* [Scheduling techniques for concurrent systems](http://www.stanford.edu/~ouster/cgi-bin/papers/coscheduling.pdf)
* [Contention aware scheduling](http://www.blagodurov.net/files/a8-blagodurov.pdf)
* [Balanced work stealing for time-sharing multicores](http://www.cse.ohio-state.edu/hpcs/WWW/HTML/publications/papers/TR-12-1.pdf)
* [Three layer cake for shared-memory programming](http://dl.acm.org/citation.cfm?id=1953616&dl=ACM&coll=DL&CFID=524387192&CFTOKEN=44362705)
* [Non-blocking steal-half work queues](http://www.cs.bgu.ac.il/%7Ehendlerd/papers/p280-hendler.pdf)
* [Reagents: expressing and composing fine-grained concurrency](http://www.mpi-sws.org/~turon/reagents.pdf)
* [Algorithms for scalable synchronization of shared-memory multiprocessors](https://www.cs.rochester.edu/u/scott/papers/1991_TOCS_synch.pdf)
* [Epoch-based reclamation](https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-579.pdf).
### Others
* [Crash-only software](https://www.usenix.org/legacy/events/hotos03/tech/full_papers/candea/candea.pdf)
* [Composing High-Performance Memory Allocators](http://people.cs.umass.edu/~emery/pubs/berger-pldi2001.pdf)
* [Reconsidering Custom Memory Allocation](http://people.cs.umass.edu/~emery/pubs/berger-oopsla2002.pdf)
### Papers *about* Rust
* [GPU Programming in Rust: Implementing High Level Abstractions in a
Systems Level
Language](http://www.cs.indiana.edu/~eholk/papers/hips2013.pdf). Early GPU work by Eric Holk.
* [Parallel closures: a new twist on an old
idea](https://www.usenix.org/conference/hotpar12/parallel-closures-new-twist-old-idea)
- not exactly about Rust, but by nmatsakis
* [Patina: A Formalization of the Rust Programming
Language](ftp://ftp.cs.washington.edu/tr/2015/03/UW-CSE-15-03-02.pdf). Early
formalization of a subset of the type system, by Eric Reed.
* [Experience Report: Developing the Servo Web Browser Engine using
Rust](http://arxiv.org/abs/1505.07383). By Lars Bergstrom.
* [Implementing a Generic Radix Trie in
Rust](https://michaelsproul.github.io/rust_radix_paper/rust-radix-sproul.pdf). Undergrad
paper by Michael Sproul.
* [Reenix: Implementing a Unix-Like Operating System in
Rust](http://scialex.github.io/reenix.pdf). Undergrad paper by Alex
Light.
* [Evaluation of performance and productivity metrics of potential
programming languages in the HPC environment](http://octarineparrot.com/assets/mrfloya-thesis-ba.pdf).
Bachelor's thesis by Florian Wilkens. Compares C, Go and Rust.
* [Nom, a byte oriented, streaming, zero copy, parser combinators library
in Rust](http://spw15.langsec.org/papers/couprie-nom.pdf). By
Geoffroy Couprie, research for VLC.
* [Graph-Based Higher-Order Intermediate
Representation](http://compilers.cs.uni-saarland.de/papers/lkh15_cgo.pdf). An
experimental IR implemented in Impala, a Rust-like language.
* [Code Refinement of Stencil
Codes](http://compilers.cs.uni-saarland.de/papers/ppl14_web.pdf). Another
paper using Impala.
* [Parallelization in Rust with fork-join and
friends](http://publications.lib.chalmers.se/records/fulltext/219016/219016.pdf). Linus
Farnstrand's master's thesis.
* [Session Types for
Rust](http://munksgaard.me/papers/laumann-munksgaard-larsen.pdf). Philip
Munksgaard's master's thesis. Research for Servo.
* [Ownership is Theft: Experiences Building an Embedded OS in Rust - Amit Levy, et. al.](http://amitlevy.com/papers/tock-plos2015.pdf)
* [You can't spell trust without Rust](https://raw.githubusercontent.com/Gankro/thesis/master/thesis.pdf). Alexis Beingessner's master's thesis.
* [Rust as a Language for High Performance GC Implementation](http://users.cecs.anu.edu.au/~steveb/downloads/pdf/rust-ismm-2016.pdf)
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/bibliography.html).

View File

@ -1,93 +1,10 @@
# Borrow and AsRef
The [`Borrow`][borrow] and [`AsRef`][asref] traits are very similar, but
different. Heres a quick refresher on what these two traits mean.
The first edition of the book is no longer distributed with Rust's documentation.
[borrow]: ../../std/borrow/trait.Borrow.html
[asref]: ../../std/convert/trait.AsRef.html
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
# Borrow
The `Borrow` trait is used when youre writing a data structure, and you want to
use either an owned or borrowed type as synonymous for some purpose.
For example, [`HashMap`][hashmap] has a [`get` method][get] which uses `Borrow`:
```rust,ignore
fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
where K: Borrow<Q>,
Q: Hash + Eq
```
[hashmap]: ../../std/collections/struct.HashMap.html
[get]: ../../std/collections/struct.HashMap.html#method.get
This signature is pretty complicated. The `K` parameter is what were interested
in here. It refers to a parameter of the `HashMap` itself:
```rust,ignore
struct HashMap<K, V, S = RandomState> {
```
The `K` parameter is the type of _key_ the `HashMap` uses. So, looking at
the signature of `get()` again, we can use `get()` when the key implements
`Borrow<Q>`. That way, we can make a `HashMap` which uses `String` keys,
but use `&str`s when were searching:
```rust
use std::collections::HashMap;
let mut map = HashMap::new();
map.insert("Foo".to_string(), 42);
assert_eq!(map.get("Foo"), Some(&42));
```
This is because the standard library has `impl Borrow<str> for String`.
For most types, when you want to take an owned or borrowed type, a `&T` is
enough. But one area where `Borrow` is effective is when theres more than one
kind of borrowed value. This is especially true of references and slices: you
can have both an `&T` or a `&mut T`. If we wanted to accept both of these types,
`Borrow` is up for it:
```rust
use std::borrow::Borrow;
use std::fmt::Display;
fn foo<T: Borrow<i32> + Display>(a: T) {
println!("a is borrowed: {}", a);
}
let mut i = 5;
foo(&i);
foo(&mut i);
```
This will print out `a is borrowed: 5` twice.
# AsRef
The `AsRef` trait is a conversion trait. Its used for converting some value to
a reference in generic code. Like this:
```rust
let s = "Hello".to_string();
fn foo<T: AsRef<str>>(s: T) {
let slice = s.as_ref();
}
```
# Which should I use?
We can see how theyre kind of the same: they both deal with owned and borrowed
versions of some type. However, theyre a bit different.
Choose `Borrow` when you want to abstract over different kinds of borrowing, or
when youre building a data structure that treats owned and borrowed values in
equivalent ways, such as hashing and comparison.
Choose `AsRef` when you want to convert something to a reference directly, and
youre writing generic code.
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/borrow-and-asref.html).

View File

@ -1,204 +1,10 @@
# Casting Between Types
Rust, with its focus on safety, provides two different ways of casting
different types between each other. The first, `as`, is for safe casts.
In contrast, `transmute` allows for arbitrary casting, and is one of the
most dangerous features of Rust!
The first edition of the book is no longer distributed with Rust's documentation.
# Coercion
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
Coercion between types is implicit and has no syntax of its own, but can
be spelled out with [`as`](#explicit-coercions).
Coercion occurs in `let`, `const`, and `static` statements; in
function call arguments; in field values in struct initialization; and in a
function result.
The most common case of coercion is removing mutability from a reference:
* `&mut T` to `&T`
An analogous conversion is to remove mutability from a
[raw pointer](raw-pointers.html):
* `*mut T` to `*const T`
References can also be coerced to raw pointers:
* `&T` to `*const T`
* `&mut T` to `*mut T`
Custom coercions may be defined using [`Deref`](deref-coercions.html).
Coercion is transitive.
# `as`
The `as` keyword does safe casting:
```rust
let x: i32 = 5;
let y = x as i64;
```
There are three major categories of safe cast: explicit coercions, casts
between numeric types, and pointer casts.
Casting is not transitive: even if `e as U1 as U2` is a valid
expression, `e as U2` is not necessarily so (in fact it will only be valid if
`U1` coerces to `U2`).
## Explicit coercions
A cast `e as U` is valid if `e` has type `T` and `T` *coerces* to `U`.
## Numeric casts
A cast `e as U` is also valid in any of the following cases:
* `e` has type `T` and `T` and `U` are any numeric types; *numeric-cast*
* `e` is an enum with no data attached to the variants (a "field-less enumeration"),
and `U` is an integer type; *enum-cast*
* `e` has type `bool` or `char` and `U` is an integer type; *prim-int-cast*
* `e` has type `u8` and `U` is `char`; *u8-char-cast*
For example
```rust
let one = true as u8;
let at_sign = 64 as char;
let two_hundred = -56i8 as u8;
```
The semantics of numeric casts are:
* Casting between two integers of the same size (e.g. i32 -> u32) is a no-op
* Casting from a larger integer to a smaller integer (e.g. u32 -> u8) will
truncate
* Casting from a smaller integer to a larger integer (e.g. u8 -> u32) will
* zero-extend if the source is unsigned
* sign-extend if the source is signed
* Casting from a float to an integer will round the float towards zero
* **[NOTE: currently this will cause Undefined Behavior if the rounded
value cannot be represented by the target integer type][float-int]**.
This includes Inf and NaN. This is a bug and will be fixed.
* Casting from an integer to float will produce the floating point
representation of the integer, rounded if necessary (rounding strategy
unspecified)
* Casting from an f32 to an f64 is perfect and lossless
* Casting from an f64 to an f32 will produce the closest possible value
(rounding strategy unspecified)
* **[NOTE: currently this will cause Undefined Behavior if the value
is finite but larger or smaller than the largest or smallest finite
value representable by f32][float-float]**. This is a bug and will
be fixed.
[float-int]: https://github.com/rust-lang/rust/issues/10184
[float-float]: https://github.com/rust-lang/rust/issues/15536
## Pointer casts
Perhaps surprisingly, it is safe to cast [raw pointers](raw-pointers.html) to and
from integers, and to cast between pointers to different types subject to
some constraints. It is only unsafe to dereference the pointer:
```rust
let a = 300 as *const char; // `a` is a pointer to location 300.
let b = a as u32;
```
`e as U` is a valid pointer cast in any of the following cases:
* `e` has type `*T`, `U` has type `*U_0`, and either `U_0: Sized` or
`unsize_kind(T) == unsize_kind(U_0)`; a *ptr-ptr-cast*
* `e` has type `*T` and `U` is a numeric type, while `T: Sized`; *ptr-addr-cast*
* `e` is an integer and `U` is `*U_0`, while `U_0: Sized`; *addr-ptr-cast*
* `e` has type `&[T; n]` and `U` is `*const T`; *array-ptr-cast*
* `e` is a function pointer type and `U` has type `*T`,
while `T: Sized`; *fptr-ptr-cast*
* `e` is a function pointer type and `U` is an integer; *fptr-addr-cast*
# `transmute`
`as` only allows safe casting, and will for example reject an attempt to
cast four bytes into a `u32`:
```rust,ignore
let a = [0u8, 0u8, 0u8, 0u8];
let b = a as u32; // Four u8s makes a u32.
```
This errors with:
```text
error: non-scalar cast: `[u8; 4]` as `u32`
let b = a as u32; // Four u8s makes a u32.
^~~~~~~~
```
This is a non-scalar cast because we have multiple values here: the four
elements of the array. These kinds of casts are very dangerous, because they
make assumptions about the way that multiple underlying structures are
implemented. For this, we need something more dangerous.
The `transmute` function is very simple, but very scary. It tells Rust to treat
a value of one type as though it were another type. It does this regardless of
the typechecking system, and completely trusts you.
In our previous example, we know that an array of four `u8`s represents a `u32`
properly, and so we want to do the cast. Using `transmute` instead of `as`,
Rust lets us:
```rust
use std::mem;
fn main() {
unsafe {
let a = [0u8, 1u8, 0u8, 0u8];
let b = mem::transmute::<[u8; 4], u32>(a);
println!("{}", b); // 256
// Or, more concisely:
let c: u32 = mem::transmute(a);
println!("{}", c); // 256
}
}
```
We have to wrap the operation in an `unsafe` block for this to compile
successfully. Technically, only the `mem::transmute` call itself needs to be in
the block, but it's nice in this case to enclose everything related, so you
know where to look. In this case, the details about `a` are also important, and
so they're in the block. You'll see code in either style, sometimes the context
is too far away, and wrapping all of the code in `unsafe` isn't a great idea.
While `transmute` does very little checking, it will at least make sure that
the types are the same size. This errors:
```rust,ignore
use std::mem;
unsafe {
let a = [0u8, 0u8, 0u8, 0u8];
let b = mem::transmute::<[u8; 4], u64>(a);
}
```
with:
```text
error: transmute called with differently sized types: [u8; 4] (32 bits) to u64
(64 bits)
```
Other than that, you're on your own!
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/casting-between-types.html).

View File

@ -1 +0,0 @@
# Chapter 1

View File

@ -1,360 +1,10 @@
# Choosing your Guarantees
One important feature of Rust is that it lets us control the costs and guarantees
of a program.
The first edition of the book is no longer distributed with Rust's documentation.
There are various &ldquo;wrapper type&rdquo; abstractions in the Rust standard library which embody
a multitude of trade-offs between cost, ergonomics, and guarantees. Many let one choose between
run-time and compile-time enforcement. This section will explain a few selected abstractions in
detail.
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
Before proceeding, it is highly recommended that one reads about [ownership][ownership] and
[borrowing][borrowing] in Rust.
[ownership]: ownership.html
[borrowing]: references-and-borrowing.html
# Basic pointer types
## `Box<T>`
[`Box<T>`][box] is an &ldquo;owned&rdquo; pointer, or a &ldquo;box&rdquo;. While it can hand
out references to the contained data, it is the only owner of the data. In particular, consider
the following:
```rust
let x = Box::new(1);
let y = x;
// `x` is no longer accessible here.
```
Here, the box was _moved_ into `y`. As `x` no longer owns it, the compiler will no longer allow the
programmer to use `x` after this. A box can similarly be moved _out_ of a function by returning it.
When a box (that hasn't been moved) goes out of scope, destructors are run. These destructors take
care of deallocating the inner data.
This is a zero-cost abstraction for dynamic allocation. If you want to allocate some memory on the
heap and safely pass around a pointer to that memory, this is ideal. Note that you will only be
allowed to share references to this by the regular borrowing rules, checked at compile time.
[box]: ../../std/boxed/struct.Box.html
## `&T` and `&mut T`
These are immutable and mutable references respectively. They follow the &ldquo;read-write lock&rdquo;
pattern, such that one may either have only one mutable reference to some data, or any number of
immutable ones, but not both. This guarantee is enforced at compile time, and has no visible cost at
runtime. In most cases these two pointer types suffice for sharing cheap references between sections
of code.
These pointers cannot be copied in such a way that they outlive the lifetime associated with them.
## `*const T` and `*mut T`
These are C-like raw pointers with no lifetime or ownership attached to them. They point to
some location in memory with no other restrictions. The only guarantee that these provide is that
they cannot be dereferenced except in code marked `unsafe`.
These are useful when building safe, low cost abstractions like `Vec<T>`, but should be avoided in
safe code.
## `Rc<T>`
This is the first wrapper we will cover that has a runtime cost.
[`Rc<T>`][rc] is a reference counted pointer. In other words, this lets us have multiple "owning"
pointers to the same data, and the data will be dropped (destructors will be run) when all pointers
are out of scope.
Internally, it contains a shared &ldquo;reference count&rdquo; (also called &ldquo;refcount&rdquo;),
which is incremented each time the `Rc` is cloned, and decremented each time one of the `Rc`s goes
out of scope. The main responsibility of `Rc<T>` is to ensure that destructors are called for shared
data.
The internal data here is immutable, and if a cycle of references is created, the data will be
leaked. If we want data that doesn't leak when there are cycles, we need a garbage collector.
#### Guarantees
The main guarantee provided here is that the data will not be destroyed until all references to it
are out of scope.
This should be used when we wish to dynamically allocate and share some data (read-only) between
various portions of your program, where it is not certain which portion will finish using the pointer
last. It's a viable alternative to `&T` when `&T` is either impossible to statically check for
correctness, or creates extremely unergonomic code where the programmer does not wish to spend the
development cost of working with.
This pointer is _not_ thread-safe, and Rust will not let it be sent or shared with other threads.
This lets one avoid the cost of atomics in situations where they are unnecessary.
There is a sister smart pointer to this one, `Weak<T>`. This is a non-owning, but also non-borrowed,
smart pointer. It is also similar to `&T`, but it is not restricted in lifetime&mdash;a `Weak<T>`
can be held on to forever. However, it is possible that an attempt to access the inner data may fail
and return `None`, since this can outlive the owned `Rc`s. This is useful for cyclic
data structures and other things.
#### Cost
As far as memory goes, `Rc<T>` is a single allocation, though it will allocate two extra words (i.e.
two `usize` values) as compared to a regular `Box<T>` (for "strong" and "weak" refcounts).
`Rc<T>` has the computational cost of incrementing/decrementing the refcount whenever it is cloned
or goes out of scope respectively. Note that a clone will not do a deep copy, rather it will simply
increment the inner reference count and return a copy of the `Rc<T>`.
[rc]: ../../std/rc/struct.Rc.html
# Cell types
`Cell`s provide interior mutability. In other words, they contain data which can be manipulated even
if the type cannot be obtained in a mutable form (for example, when it is behind an `&`-ptr or
`Rc<T>`).
[The documentation for the `cell` module has a pretty good explanation for these][cell-mod].
These types are _generally_ found in struct fields, but they may be found elsewhere too.
## `Cell<T>`
[`Cell<T>`][cell] is a type that provides zero-cost interior mutability by moving data in and
out of the cell.
Since the compiler knows that all the data owned by the contained value is on the stack, there's
no worry of leaking any data behind references (or worse!) by simply replacing the data.
It is still possible to violate your own invariants using this wrapper, so be careful when using it.
If a field is wrapped in `Cell`, it's a nice indicator that the chunk of data is mutable and may not
stay the same between the time you first read it and when you intend to use it.
```rust
use std::cell::Cell;
let x = Cell::new(1);
let y = &x;
let z = &x;
x.set(2);
y.set(3);
z.set(4);
println!("{}", x.get());
```
Note that here we were able to mutate the same value from various immutable references.
This has the same runtime cost as the following:
```rust,ignore
let mut x = 1;
let y = &mut x;
let z = &mut x;
x = 2;
*y = 3;
*z = 4;
println!("{}", x);
```
but it has the added benefit of actually compiling successfully.
#### Guarantees
This relaxes the &ldquo;no aliasing with mutability&rdquo; restriction in places where it's
unnecessary. However, this also relaxes the guarantees that the restriction provides; so if your
invariants depend on data stored within `Cell`, you should be careful.
This is useful for mutating primitives and other types when there is no easy way of
doing it in line with the static rules of `&` and `&mut`.
`Cell` does not let you obtain interior references to the data, which makes it safe to freely
mutate.
#### Cost
There is no runtime cost to using `Cell<T>`, however if you are using it to wrap larger
structs, it might be worthwhile to instead wrap individual fields in `Cell<T>` since each write is
otherwise a full copy of the struct.
## `RefCell<T>`
[`RefCell<T>`][refcell] also provides interior mutability, but doesn't move data in and out of the
cell.
However, it has a runtime cost. `RefCell<T>` enforces the read-write lock pattern at runtime (it's
like a single-threaded mutex), unlike `&T`/`&mut T` which do so at compile time. This is done by the
`borrow()` and `borrow_mut()` functions, which modify an internal reference count and return smart
pointers which can be dereferenced immutably and mutably respectively. The refcount is restored when
the smart pointers go out of scope. With this system, we can dynamically ensure that there are never
any other borrows active when a mutable borrow is active. If the programmer attempts to make such a
borrow, the thread will panic.
```rust
use std::cell::RefCell;
let x = RefCell::new(vec![1,2,3,4]);
{
println!("{:?}", *x.borrow())
}
{
let mut my_ref = x.borrow_mut();
my_ref.push(1);
}
```
Similar to `Cell`, this is mainly useful for situations where it's hard or impossible to satisfy the
borrow checker. Generally we know that such mutations won't happen in a nested form, but it's good
to check.
For large, complicated programs, it becomes useful to put some things in `RefCell`s to make things
simpler. For example, a lot of the maps in the `ctxt` struct in the Rust compiler internals
are inside this wrapper. These are only modified once (during creation, which is not right after
initialization) or a couple of times in well-separated places. However, since this struct is
pervasively used everywhere, juggling mutable and immutable pointers would be hard (perhaps
impossible) and probably form a soup of `&`-ptrs which would be hard to extend. On the other hand,
the `RefCell` provides a cheap (not zero-cost) way of safely accessing these. In the future, if
someone adds some code that attempts to modify the cell when it's already borrowed, it will cause a
(usually deterministic) panic which can be traced back to the offending borrow.
Similarly, in Servo's DOM there is a lot of mutation, most of which is local to a DOM type, but some
of which crisscrosses the DOM and modifies various things. Using `RefCell` and `Cell` to guard all
mutation lets us avoid worrying about mutability everywhere, and it simultaneously highlights the
places where mutation is _actually_ happening.
Note that `RefCell` should be avoided if a mostly simple solution is possible with `&` pointers.
#### Guarantees
`RefCell` relaxes the _static_ restrictions preventing aliased mutation, and replaces them with
_dynamic_ ones. As such the guarantees have not changed.
#### Cost
`RefCell` does not allocate, but it contains an additional "borrow state"
indicator (one word in size) along with the data.
At runtime each borrow causes a modification/check of the refcount.
[cell-mod]: ../../std/cell/index.html
[cell]: ../../std/cell/struct.Cell.html
[refcell]: ../../std/cell/struct.RefCell.html
# Synchronous types
Many of the types above cannot be used in a threadsafe manner. Particularly, `Rc<T>` and
`RefCell<T>`, which both use non-atomic reference counts (_atomic_ reference counts are those which
can be incremented from multiple threads without causing a data race), cannot be used this way. This
makes them cheaper to use, but we need thread-safe versions of these too. They exist, in the form of
`Arc<T>` and `Mutex<T>`/`RwLock<T>`
Note that the non-threadsafe types _cannot_ be sent between threads, and this is checked at compile
time.
There are many useful wrappers for concurrent programming in the [sync][sync] module, but only the
major ones will be covered below.
[sync]: ../../std/sync/index.html
## `Arc<T>`
[`Arc<T>`][arc] is a version of `Rc<T>` that uses an atomic reference count (hence, "Arc").
This can be sent freely between threads.
C++'s `shared_ptr` is similar to `Arc`, however in the case of C++ the inner data is always mutable.
For semantics similar to that from C++, we should use `Arc<Mutex<T>>`, `Arc<RwLock<T>>`, or
`Arc<UnsafeCell<T>>`[^4] (`UnsafeCell<T>` is a cell type that can be used to hold any data and has
no runtime cost, but accessing it requires `unsafe` blocks). The last one should only be used if we
are certain that the usage won't cause any memory unsafety. Remember that writing to a struct is not
an atomic operation, and many functions like `vec.push()` can reallocate internally and cause unsafe
behavior, so even monotonicity may not be enough to justify `UnsafeCell`.
[^4]: `Arc<UnsafeCell<T>>` actually won't compile since `UnsafeCell<T>` isn't `Send` or `Sync`, but we can wrap it in a type and implement `Send`/`Sync` for it manually to get `Arc<Wrapper<T>>` where `Wrapper` is `struct Wrapper<T>(UnsafeCell<T>)`.
#### Guarantees
Like `Rc`, this provides the (thread-safe) guarantee that the destructor for the internal data will
be run when the last `Arc` goes out of scope (barring any cycles).
#### Cost
This has the added cost of using atomics for changing the refcount (which will happen whenever it is
cloned or goes out of scope). When sharing data from an `Arc` in a single thread, it is preferable
to share `&` pointers whenever possible.
[arc]: ../../std/sync/struct.Arc.html
## `Mutex<T>` and `RwLock<T>`
[`Mutex<T>`][mutex] and [`RwLock<T>`][rwlock] provide mutual-exclusion via RAII guards (guards are
objects which maintain some state, like a lock, until their destructor is called). For both of
these, the mutex is opaque until we call `lock()` on it, at which point the thread will block
until a lock can be acquired, and then a guard will be returned. This guard can be used to access
the inner data (mutably), and the lock will be released when the guard goes out of scope.
```rust,ignore
{
let guard = mutex.lock();
// `guard` dereferences mutably to the inner type.
*guard += 1;
} // Lock is released when destructor runs.
```
`RwLock` has the added benefit of being efficient for multiple reads. It is always safe to have
multiple readers to shared data as long as there are no writers; and `RwLock` lets readers acquire a
"read lock". Such locks can be acquired concurrently and are kept track of via a reference count.
Writers must obtain a "write lock" which can only be obtained when all readers have gone out of
scope.
#### Guarantees
Both of these provide safe shared mutability across threads, however they are prone to deadlocks.
Some level of additional protocol safety can be obtained via the type system.
#### Costs
These use internal atomic-like types to maintain the locks, which are pretty costly (they can block
all memory reads across processors till they're done). Waiting on these locks can also be slow when
there's a lot of concurrent access happening.
[rwlock]: ../../std/sync/struct.RwLock.html
[mutex]: ../../std/sync/struct.Mutex.html
[sessions]: https://github.com/Munksgaard/rust-sessions
# Composition
A common gripe when reading Rust code is with types like `Rc<RefCell<Vec<T>>>` (or even more
complicated compositions of such types). It's not always clear what the composition does, or why the
author chose one like this (and when one should be using such a composition in one's own code)
Usually, it's a case of composing together the guarantees that you need, without paying for stuff
that is unnecessary.
For example, `Rc<RefCell<T>>` is one such composition. `Rc<T>` itself can't be dereferenced mutably;
because `Rc<T>` provides sharing and shared mutability can lead to unsafe behavior, so we put
`RefCell<T>` inside to get dynamically verified shared mutability. Now we have shared mutable data,
but it's shared in a way that there can only be one mutator (and no readers) or multiple readers.
Now, we can take this a step further, and have `Rc<RefCell<Vec<T>>>` or `Rc<Vec<RefCell<T>>>`. These
are both shareable, mutable vectors, but they're not the same.
With the former, the `RefCell<T>` is wrapping the `Vec<T>`, so the `Vec<T>` in its entirety is
mutable. At the same time, there can only be one mutable borrow of the whole `Vec` at a given time.
This means that your code cannot simultaneously work on different elements of the vector from
different `Rc` handles. However, we are able to push and pop from the `Vec<T>` at will. This is
similar to a `&mut Vec<T>` with the borrow checking done at runtime.
With the latter, the borrowing is of individual elements, but the overall vector is immutable. Thus,
we can independently borrow separate elements, but we cannot push or pop from the vector. This is
similar to a `&mut [T]`[^3], but, again, the borrow checking is at runtime.
In concurrent programs, we have a similar situation with `Arc<Mutex<T>>`, which provides shared
mutability and ownership.
When reading code that uses these, go in step by step and look at the guarantees/costs provided.
When choosing a composed type, we must do the reverse; figure out which guarantees we want, and at
which point of the composition we need them. For example, if there is a choice between
`Vec<RefCell<T>>` and `RefCell<Vec<T>>`, we should figure out the trade-offs as done above and pick
one.
[^3]: `&[T]` and `&mut [T]` are _slices_; they consist of a pointer and a length and can refer to a portion of a vector or array. `&mut [T]` can have its elements mutated, however its length cannot be touched.
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/choosing-your-guarantees.html).

View File

@ -1,537 +1,10 @@
# Closures
Sometimes it is useful to wrap up a function and _free variables_ for better
clarity and reuse. The free variables that can be used come from the
enclosing scope and are closed over when used in the function. From this, we
get the name closures and Rust provides a really great implementation of
them, as well see.
The first edition of the book is no longer distributed with Rust's documentation.
# Syntax
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
Closures look like this:
```rust
let plus_one = |x: i32| x + 1;
assert_eq!(2, plus_one(1));
```
We create a binding, `plus_one`, and assign it to a closure. The closures
arguments go between the pipes (`|`), and the body is an expression, in this
case, `x + 1`. Remember that `{ }` is an expression, so we can have multi-line
closures too:
```rust
let plus_two = |x| {
let mut result: i32 = x;
result += 1;
result += 1;
result
};
assert_eq!(4, plus_two(2));
```
Youll notice a few things about closures that are a bit different from regular
named functions defined with `fn`. The first is that we did not need to
annotate the types of arguments the closure takes or the values it returns. We
can:
```rust
let plus_one = |x: i32| -> i32 { x + 1 };
assert_eq!(2, plus_one(1));
```
But we dont have to. Why is this? Basically, it was chosen for ergonomic
reasons. While specifying the full type for named functions is helpful with
things like documentation and type inference, the full type signatures of
closures are rarely documented since theyre anonymous, and they dont cause
the kinds of error-at-a-distance problems that inferring named function types
can.
The second is that the syntax is similar, but a bit different. Ive added
spaces here for easier comparison:
```rust
fn plus_one_v1 (x: i32) -> i32 { x + 1 }
let plus_one_v2 = |x: i32| -> i32 { x + 1 };
let plus_one_v3 = |x: i32| x + 1 ;
```
Small differences, but theyre similar.
# Closures and their environment
The environment for a closure can include bindings from its enclosing scope in
addition to parameters and local bindings. It looks like this:
```rust
let num = 5;
let plus_num = |x: i32| x + num;
assert_eq!(10, plus_num(5));
```
This closure, `plus_num`, refers to a `let` binding in its scope: `num`. More
specifically, it borrows the binding. If we do something that would conflict
with that binding, we get an error. Like this one:
```rust,ignore
let mut num = 5;
let plus_num = |x: i32| x + num;
let y = &mut num;
```
Which errors with:
```text
error: cannot borrow `num` as mutable because it is also borrowed as immutable
let y = &mut num;
^~~
note: previous borrow of `num` occurs here due to use in closure; the immutable
borrow prevents subsequent moves or mutable borrows of `num` until the borrow
ends
let plus_num = |x| x + num;
^~~~~~~~~~~
note: previous borrow ends here
fn main() {
let mut num = 5;
let plus_num = |x| x + num;
let y = &mut num;
}
^
```
A verbose yet helpful error message! As it says, we cant take a mutable borrow
on `num` because the closure is already borrowing it. If we let the closure go
out of scope, we can:
```rust
let mut num = 5;
{
let plus_num = |x: i32| x + num;
} // `plus_num` goes out of scope; borrow of `num` ends.
let y = &mut num;
```
If your closure requires it, however, Rust will take ownership and move
the environment instead. This doesnt work:
```rust,ignore
let nums = vec![1, 2, 3];
let takes_nums = || nums;
println!("{:?}", nums);
```
We get this error:
```text
note: `nums` moved into closure environment here because it has type
`[closure(()) -> collections::vec::Vec<i32>]`, which is non-copyable
let takes_nums = || nums;
^~~~~~~
```
`Vec<T>` has ownership over its contents, and therefore, when we refer to it
in our closure, we have to take ownership of `nums`. Its the same as if wed
passed `nums` to a function that took ownership of it.
## `move` closures
We can force our closure to take ownership of its environment with the `move`
keyword:
```rust
let num = 5;
let owns_num = move |x: i32| x + num;
```
Now, even though the keyword is `move`, the variables follow normal move semantics.
In this case, `5` implements `Copy`, and so `owns_num` takes ownership of a copy
of `num`. So whats the difference?
```rust
let mut num = 5;
{
let mut add_num = |x: i32| num += x;
add_num(5);
}
assert_eq!(10, num);
```
So in this case, our closure took a mutable reference to `num`, and then when
we called `add_num`, it mutated the underlying value, as wed expect. We also
needed to declare `add_num` as `mut` too, because were mutating its
environment.
If we change to a `move` closure, its different:
```rust
let mut num = 5;
{
let mut add_num = move |x: i32| num += x;
add_num(5);
}
assert_eq!(5, num);
```
We only get `5`. Rather than taking a mutable borrow out on our `num`, we took
ownership of a copy.
Another way to think about `move` closures: they give a closure its own stack
frame. Without `move`, a closure may be tied to the stack frame that created
it, while a `move` closure is self-contained. This means that you cannot
generally return a non-`move` closure from a function, for example.
But before we talk about taking and returning closures, we should talk some
more about the way that closures are implemented. As a systems language, Rust
gives you tons of control over what your code does, and closures are no
different.
# Closure implementation
Rusts implementation of closures is a bit different than other languages. They
are effectively syntax sugar for traits. Youll want to make sure to have read
the [traits][traits] section before this one, as well as the section on [trait
objects][trait-objects].
[traits]: traits.html
[trait-objects]: trait-objects.html
Got all that? Good.
The key to understanding how closures work under the hood is something a bit
strange: Using `()` to call a function, like `foo()`, is an overloadable
operator. From this, everything else clicks into place. In Rust, we use the
trait system to overload operators. Calling functions is no different. We have
three separate traits to overload with:
* `Fn`
* `FnMut`
* `FnOnce`
There are a few differences between these traits, but a big one is `self`:
`Fn` takes `&self`, `FnMut` takes `&mut self`, and `FnOnce` takes `self`. This
covers all three kinds of `self` via the usual method call syntax. But weve
split them up into three traits, rather than having a single one. This gives us
a large amount of control over what kind of closures we can take.
The `|| {}` syntax for closures is sugar for these three traits. Rust will
generate a struct for the environment, `impl` the appropriate trait, and then
use it.
# Taking closures as arguments
Now that we know that closures are traits, we already know how to accept and
return closures: the same as any other trait!
This also means that we can choose static vs dynamic dispatch as well. First,
lets write a function which takes something callable, calls it, and returns
the result:
```rust
fn call_with_one<F>(some_closure: F) -> i32
where F: Fn(i32) -> i32 {
some_closure(1)
}
let answer = call_with_one(|x| x + 2);
assert_eq!(3, answer);
```
We pass our closure, `|x| x + 2`, to `call_with_one`. It does what it
suggests: it calls the closure, giving it `1` as an argument.
Lets examine the signature of `call_with_one` in more depth:
```rust
fn call_with_one<F>(some_closure: F) -> i32
# where F: Fn(i32) -> i32 {
# some_closure(1) }
```
We take one parameter, and it has the type `F`. We also return an `i32`. This part
isnt interesting. The next part is:
```rust
# fn call_with_one<F>(some_closure: F) -> i32
where F: Fn(i32) -> i32 {
# some_closure(1) }
```
Because `Fn` is a trait, we can use it as a bound for our generic type. In
this case, our closure takes an `i32` as an argument and returns an `i32`, and
so the generic bound we use is `Fn(i32) -> i32`.
Theres one other key point here: because were bounding a generic with a
trait, this will get monomorphized, and therefore, well be doing static
dispatch into the closure. Thats pretty neat. In many languages, closures are
inherently heap allocated, and will always involve dynamic dispatch. In Rust,
we can stack allocate our closure environment, and statically dispatch the
call. This happens quite often with iterators and their adapters, which often
take closures as arguments.
Of course, if we want dynamic dispatch, we can get that too. A trait object
handles this case, as usual:
```rust
fn call_with_one(some_closure: &Fn(i32) -> i32) -> i32 {
some_closure(1)
}
let answer = call_with_one(&|x| x + 2);
assert_eq!(3, answer);
```
Now we take a trait object, a `&Fn`. And we have to make a reference
to our closure when we pass it to `call_with_one`, so we use `&||`.
A quick note about closures that use explicit lifetimes. Sometimes you might have a closure
that takes a reference like so:
```rust
fn call_with_ref<F>(some_closure:F) -> i32
where F: Fn(&i32) -> i32 {
let value = 0;
some_closure(&value)
}
```
Normally you can specify the lifetime of the parameter to our closure. We
could annotate it on the function declaration:
```rust,ignore
fn call_with_ref<'a, F>(some_closure:F) -> i32
where F: Fn(&'a i32) -> i32 {
```
However, this presents a problem in our case. When a function has an explicit
lifetime parameter, that lifetime must be at least as long as the *entire*
call to that function. The borrow checker will complain that `value` doesn't
live long enough, because it is only in scope after its declaration inside the
function body.
What we need is a closure that can borrow its argument only for its own
invocation scope, not for the outer function's scope. In order to say that,
we can use Higher-Ranked Trait Bounds with the `for<...>` syntax:
```ignore
fn call_with_ref<F>(some_closure:F) -> i32
where F: for<'a> Fn(&'a i32) -> i32 {
```
This lets the Rust compiler find the minimum lifetime to invoke our closure and
satisfy the borrow checker's rules. Our function then compiles and executes as we
expect.
```rust
fn call_with_ref<F>(some_closure:F) -> i32
where F: for<'a> Fn(&'a i32) -> i32 {
let value = 0;
some_closure(&value)
}
```
# Function pointers and closures
A function pointer is kind of like a closure that has no environment. As such,
you can pass a function pointer to any function expecting a closure argument,
and it will work:
```rust
fn call_with_one(some_closure: &Fn(i32) -> i32) -> i32 {
some_closure(1)
}
fn add_one(i: i32) -> i32 {
i + 1
}
let f = add_one;
let answer = call_with_one(&f);
assert_eq!(2, answer);
```
In this example, we dont strictly need the intermediate variable `f`,
the name of the function works just fine too:
```rust,ignore
let answer = call_with_one(&add_one);
```
# Returning closures
Its very common for functional-style code to return closures in various
situations. If you try to return a closure, you may run into an error. At
first, it may seem strange, but well figure it out. Heres how youd probably
try to return a closure from a function:
```rust,ignore
fn factory() -> (Fn(i32) -> i32) {
let num = 5;
|x| x + num
}
let f = factory();
let answer = f(1);
assert_eq!(6, answer);
```
This gives us these long, related errors:
```text
error: the trait bound `core::ops::Fn(i32) -> i32 : core::marker::Sized` is not satisfied [E0277]
fn factory() -> (Fn(i32) -> i32) {
^~~~~~~~~~~~~~~~
note: `core::ops::Fn(i32) -> i32` does not have a constant size known at compile-time
fn factory() -> (Fn(i32) -> i32) {
^~~~~~~~~~~~~~~~
error: the trait bound `core::ops::Fn(i32) -> i32 : core::marker::Sized` is not satisfied [E0277]
let f = factory();
^
note: `core::ops::Fn(i32) -> i32` does not have a constant size known at compile-time
let f = factory();
^
```
In order to return something from a function, Rust needs to know what
size the return type is. But since `Fn` is a trait, it could be various
things of various sizes: many different types can implement `Fn`. An easy
way to give something a size is to take a reference to it, as references
have a known size. So wed write this:
```rust,ignore
fn factory() -> &(Fn(i32) -> i32) {
let num = 5;
|x| x + num
}
let f = factory();
let answer = f(1);
assert_eq!(6, answer);
```
But we get another error:
```text
error: missing lifetime specifier [E0106]
fn factory() -> &(Fn(i32) -> i32) {
^~~~~~~~~~~~~~~~~
```
Right. Because we have a reference, we need to give it a lifetime. But
our `factory()` function takes no arguments, so
[elision](lifetimes.html#lifetime-elision) doesnt kick in here. Then what
choices do we have? Try `'static`:
```rust,ignore
fn factory() -> &'static (Fn(i32) -> i32) {
let num = 5;
|x| x + num
}
let f = factory();
let answer = f(1);
assert_eq!(6, answer);
```
But we get another error:
```text
error: mismatched types:
expected `&'static core::ops::Fn(i32) -> i32`,
found `[closure@<anon>:7:9: 7:20]`
(expected &-ptr,
found closure) [E0308]
|x| x + num
^~~~~~~~~~~
```
This error is letting us know that we dont have a `&'static Fn(i32) -> i32`,
we have a `[closure@<anon>:7:9: 7:20]`. Wait, what?
Because each closure generates its own environment `struct` and implementation
of `Fn` and friends, these types are anonymous. They exist solely for
this closure. So Rust shows them as `closure@<anon>`, rather than some
autogenerated name.
The error also points out that the return type is expected to be a reference,
but what we are trying to return is not. Further, we cannot directly assign a
`'static` lifetime to an object. So we'll take a different approach and return
a trait object by `Box`ing up the `Fn`. This _almost_ works:
```rust,ignore
fn factory() -> Box<Fn(i32) -> i32> {
let num = 5;
Box::new(|x| x + num)
}
let f = factory();
let answer = f(1);
assert_eq!(6, answer);
```
Theres just one last problem:
```text
error: closure may outlive the current function, but it borrows `num`,
which is owned by the current function [E0373]
Box::new(|x| x + num)
^~~~~~~~~~~
```
Well, as we discussed before, closures borrow their environment. And in this
case, our environment is based on a stack-allocated `5`, the `num` variable
binding. So the borrow has a lifetime of the stack frame. So if we returned
this closure, the function call would be over, the stack frame would go away,
and our closure is capturing an environment of garbage memory! With one last
fix, we can make this work:
```rust
fn factory() -> Box<Fn(i32) -> i32> {
let num = 5;
Box::new(move |x| x + num)
}
let f = factory();
let answer = f(1);
assert_eq!(6, answer);
```
By making the inner closure a `move Fn`, we create a new stack frame for our
closure. By `Box`ing it up, weve given it a known size, allowing it to
escape our stack frame.
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/closures.html).

View File

@ -1,59 +1,10 @@
# Comments
Now that we have some functions, its a good idea to learn about comments.
Comments are notes that you leave to other programmers to help explain things
about your code. The compiler mostly ignores them.
The first edition of the book is no longer distributed with Rust's documentation.
Rust has two kinds of comments that you should care about: *line comments*
and *doc comments*.
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
```rust
// Line comments are anything after // and extend to the end of the line.
let x = 5; // This is also a line comment.
// If you have a long explanation for something, you can put line comments next
// to each other. Put a space between the // and your comment so that its
// more readable.
```
The other kind of comment is a doc comment. Doc comments use `///` instead of
`//`, and support Markdown notation inside:
```rust
/// Adds one to the number given.
///
/// # Examples
///
/// ```
/// let five = 5;
///
/// assert_eq!(6, add_one(5));
/// # fn add_one(x: i32) -> i32 {
/// # x + 1
/// # }
/// ```
fn add_one(x: i32) -> i32 {
x + 1
}
```
There is another style of doc comment, `//!`, to comment containing items (e.g.
crates, modules or functions), instead of the items following it. Commonly used
inside crates root (lib.rs) or modules root (mod.rs):
```
//! # The Rust Standard Library
//!
//! The Rust Standard Library provides the essential runtime
//! functionality for building portable Rust software.
```
When writing doc comments, providing some examples of usage is very, very
helpful. Youll notice weve used a new macro here: `assert_eq!`. This compares
two values, and `panic!`s if theyre not equal to each other. Its very helpful
in documentation. Theres another macro, `assert!`, which `panic!`s if the
value passed to it is `false`.
You can use the [`rustdoc`](documentation.html) tool to generate HTML documentation
from these doc comments, and also to run the code examples as tests!
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/comments.html).

View File

@ -1,465 +1,10 @@
# Concurrency
Concurrency and parallelism are incredibly important topics in computer
science, and are also a hot topic in industry today. Computers are gaining more
and more cores, yet many programmers aren't prepared to fully utilize them.
The first edition of the book is no longer distributed with Rust's documentation.
Rust's memory safety features also apply to its concurrency story. Even
concurrent Rust programs must be memory safe, having no data races. Rust's type
system is up to the task, and gives you powerful ways to reason about
concurrent code at compile time.
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
Before we talk about the concurrency features that come with Rust, it's important
to understand something: Rust is low-level enough that the vast majority of
this is provided by the standard library, not by the language. This means that
if you don't like some aspect of the way Rust handles concurrency, you can
implement an alternative way of doing things.
[mio](https://github.com/carllerche/mio) is a real-world example of this
principle in action.
## Background: `Send` and `Sync`
Concurrency is difficult to reason about. In Rust, we have a strong, static
type system to help us reason about our code. As such, Rust gives us two traits
to help us make sense of code that can possibly be concurrent.
### `Send`
The first trait we're going to talk about is
[`Send`](../../std/marker/trait.Send.html). When a type `T` implements `Send`, it
indicates that something of this type is able to have ownership transferred
safely between threads.
This is important to enforce certain restrictions. For example, if we have a
channel connecting two threads, we would want to be able to send some data
down the channel and to the other thread. Therefore, we'd ensure that `Send` was
implemented for that type.
In the opposite way, if we were wrapping a library with [FFI][ffi] that isn't
thread-safe, we wouldn't want to implement `Send`, and so the compiler will help
us enforce that it can't leave the current thread.
[ffi]: ffi.html
### `Sync`
The second of these traits is called [`Sync`](../../std/marker/trait.Sync.html).
When a type `T` implements `Sync`, it indicates that something
of this type has no possibility of introducing memory unsafety when used from
multiple threads concurrently through shared references. This implies that
types which don't have [interior mutability](mutability.html) are inherently
`Sync`, which includes simple primitive types (like `u8`) and aggregate types
containing them.
For sharing references across threads, Rust provides a wrapper type called
`Arc<T>`. `Arc<T>` implements `Send` and `Sync` if and only if `T` implements
both `Send` and `Sync`. For example, an object of type `Arc<RefCell<U>>` cannot
be transferred across threads because
[`RefCell`](choosing-your-guarantees.html#refcellt) does not implement
`Sync`, consequently `Arc<RefCell<U>>` would not implement `Send`.
These two traits allow you to use the type system to make strong guarantees
about the properties of your code under concurrency. Before we demonstrate
why, we need to learn how to create a concurrent Rust program in the first
place!
## Threads
Rust's standard library provides a library for threads, which allow you to
run Rust code in parallel. Here's a basic example of using `std::thread`:
```rust
use std::thread;
fn main() {
thread::spawn(|| {
println!("Hello from a thread!");
});
}
```
The `thread::spawn()` method accepts a [closure](closures.html), which is executed in a
new thread. It returns a handle to the thread, that can be used to
wait for the child thread to finish and extract its result:
```rust
use std::thread;
fn main() {
let handle = thread::spawn(|| {
"Hello from a thread!"
});
println!("{}", handle.join().unwrap());
}
```
As closures can capture variables from their environment, we can also try to
bring some data into the other thread:
```rust,ignore
use std::thread;
fn main() {
let x = 1;
thread::spawn(|| {
println!("x is {}", x);
});
}
```
However, this gives us an error:
```text
5:19: 7:6 error: closure may outlive the current function, but it
borrows `x`, which is owned by the current function
...
5:19: 7:6 help: to force the closure to take ownership of `x` (and any other referenced variables),
use the `move` keyword, as shown:
thread::spawn(move || {
println!("x is {}", x);
});
```
This is because by default closures capture variables by reference, and thus the
closure only captures a _reference to `x`_. This is a problem, because the
thread may outlive the scope of `x`, leading to a dangling pointer.
To fix this, we use a `move` closure as mentioned in the error message. `move`
closures are explained in depth [here](closures.html#move-closures); basically
they move variables from their environment into themselves.
```rust
use std::thread;
fn main() {
let x = 1;
thread::spawn(move || {
println!("x is {}", x);
});
}
```
Many languages have the ability to execute threads, but it's wildly unsafe.
There are entire books about how to prevent errors that occur from shared
mutable state. Rust helps out with its type system here as well, by preventing
data races at compile time. Let's talk about how you actually share things
between threads.
## Safe Shared Mutable State
Due to Rust's type system, we have a concept that sounds like a lie: "safe
shared mutable state." Many programmers agree that shared mutable state is
very, very bad.
Someone once said this:
> Shared mutable state is the root of all evil. Most languages attempt to deal
> with this problem through the 'mutable' part, but Rust deals with it by
> solving the 'shared' part.
The same [ownership system](ownership.html) that helps prevent using pointers
incorrectly also helps rule out data races, one of the worst kinds of
concurrency bugs.
As an example, here is a Rust program that would have a data race in many
languages. It will not compile:
```rust,ignore
use std::thread;
use std::time::Duration;
fn main() {
let mut data = vec![1, 2, 3];
for i in 0..3 {
thread::spawn(move || {
data[0] += i;
});
}
thread::sleep(Duration::from_millis(50));
}
```
This gives us an error:
```text
8:17 error: capture of moved value: `data`
data[0] += i;
^~~~
```
Rust knows this wouldn't be safe! If we had a reference to `data` in each
thread, and the thread takes ownership of the reference, we'd have three owners!
`data` gets moved out of `main` in the first call to `spawn()`, so subsequent
calls in the loop cannot use this variable.
So, we need some type that lets us have more than one owning reference to a
value. Usually, we'd use `Rc<T>` for this, which is a reference counted type
that provides shared ownership. It has some runtime bookkeeping that keeps track
of the number of references to it, hence the "reference count" part of its name.
Calling `clone()` on an `Rc<T>` will return a new owned reference and bump the
internal reference count. We create one of these for each thread:
```rust,ignore
use std::thread;
use std::time::Duration;
use std::rc::Rc;
fn main() {
let mut data = Rc::new(vec![1, 2, 3]);
for i in 0..3 {
// Create a new owned reference:
let data_ref = data.clone();
// Use it in a thread:
thread::spawn(move || {
data_ref[0] += i;
});
}
thread::sleep(Duration::from_millis(50));
}
```
This won't work, however, and will give us the error:
```text
13:9: 13:22 error: the trait bound `alloc::rc::Rc<collections::vec::Vec<i32>> : core::marker::Send`
is not satisfied
...
13:9: 13:22 note: `alloc::rc::Rc<collections::vec::Vec<i32>>`
cannot be sent between threads safely
```
As the error message mentions, `Rc` cannot be sent between threads safely. This
is because the internal reference count is not maintained in a thread-safe
manner and can have a data race.
To solve this, we'll use `Arc<T>`, Rust's standard atomic reference count type.
The Atomic part means `Arc<T>` can safely be accessed from multiple threads.
To do this the compiler guarantees that mutations of the internal count use
indivisible operations which can't have data races.
In essence, `Arc<T>` is a type that lets us share ownership of data _across
threads_.
```rust,ignore
use std::thread;
use std::sync::Arc;
use std::time::Duration;
fn main() {
let mut data = Arc::new(vec![1, 2, 3]);
for i in 0..3 {
let data = data.clone();
thread::spawn(move || {
data[0] += i;
});
}
thread::sleep(Duration::from_millis(50));
}
```
Similarly to last time, we use `clone()` to create a new owned handle.
This handle is then moved into the new thread.
And... still gives us an error.
```text
<anon>:11:24 error: cannot borrow immutable borrowed content as mutable
<anon>:11 data[0] += i;
^~~~
```
`Arc<T>` by default has immutable contents. It allows the _sharing_ of data
between threads, but shared mutable data is unsafe—and when threads are
involved—can cause data races!
Usually when we wish to make something in an immutable position mutable, we use
`Cell<T>` or `RefCell<T>` which allow safe mutation via runtime checks or
otherwise (see also: [Choosing Your Guarantees](choosing-your-guarantees.html)).
However, similar to `Rc`, these are not thread-safe. If we try using these, we
will get an error about these types not being `Sync`, and the code will fail to
compile.
It looks like we need some type that allows us to safely mutate a shared value
across threads, for example a type that can ensure only one thread at a time is
able to mutate the value inside it at any one time.
For that, we can use the `Mutex<T>` type!
Here's the working version:
```rust
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
fn main() {
let data = Arc::new(Mutex::new(vec![1, 2, 3]));
for i in 0..3 {
let data = data.clone();
thread::spawn(move || {
let mut data = data.lock().unwrap();
data[0] += i;
});
}
thread::sleep(Duration::from_millis(50));
}
```
Note that the value of `i` is bound (copied) to the closure and not shared
among the threads.
We're "locking" the mutex here. A mutex (short for "mutual exclusion"), as
mentioned, only allows one thread at a time to access a value. When we wish to
access the value, we use `lock()` on it. This will "lock" the mutex, and no
other thread will be able to lock it (and hence, do anything with the value)
until we're done with it. If a thread attempts to lock a mutex which is already
locked, it will wait until the other thread releases the lock.
The lock "release" here is implicit; when the result of the lock (in this case,
`data`) goes out of scope, the lock is automatically released.
Note that [`lock`](../../std/sync/struct.Mutex.html#method.lock) method of
[`Mutex`](../../std/sync/struct.Mutex.html) has this signature:
```rust,ignore
fn lock(&self) -> LockResult<MutexGuard<T>>
```
and because `Send` is not implemented for `MutexGuard<T>`, the guard cannot
cross thread boundaries, ensuring thread-locality of lock acquire and release.
Let's examine the body of the thread more closely:
```rust
# use std::sync::{Arc, Mutex};
# use std::thread;
# use std::time::Duration;
# fn main() {
# let data = Arc::new(Mutex::new(vec![1, 2, 3]));
# for i in 0..3 {
# let data = data.clone();
thread::spawn(move || {
let mut data = data.lock().unwrap();
data[0] += i;
});
# }
# thread::sleep(Duration::from_millis(50));
# }
```
First, we call `lock()`, which acquires the mutex's lock. Because this may fail,
it returns a `Result<T, E>`, and because this is just an example, we `unwrap()`
it to get a reference to the data. Real code would have more robust error handling
here. We're then free to mutate it, since we have the lock.
Lastly, while the threads are running, we wait on a short timer. But
this is not ideal: we may have picked a reasonable amount of time to
wait but it's more likely we'll either be waiting longer than
necessary or not long enough, depending on just how much time the
threads actually take to finish computing when the program runs.
A more precise alternative to the timer would be to use one of the
mechanisms provided by the Rust standard library for synchronizing
threads with each other. Let's talk about one of them: channels.
## Channels
Here's a version of our code that uses channels for synchronization, rather
than waiting for a specific time:
```rust
use std::sync::{Arc, Mutex};
use std::thread;
use std::sync::mpsc;
fn main() {
let data = Arc::new(Mutex::new(0));
// `tx` is the "transmitter" or "sender".
// `rx` is the "receiver".
let (tx, rx) = mpsc::channel();
for _ in 0..10 {
let (data, tx) = (data.clone(), tx.clone());
thread::spawn(move || {
let mut data = data.lock().unwrap();
*data += 1;
tx.send(()).unwrap();
});
}
for _ in 0..10 {
rx.recv().unwrap();
}
}
```
We use the `mpsc::channel()` method to construct a new channel. We `send`
a simple `()` down the channel, and then wait for ten of them to come back.
While this channel is sending a generic signal, we can send any data that
is `Send` over the channel!
```rust
use std::thread;
use std::sync::mpsc;
fn main() {
let (tx, rx) = mpsc::channel();
for i in 0..10 {
let tx = tx.clone();
thread::spawn(move || {
let answer = i * i;
tx.send(answer).unwrap();
});
}
for _ in 0..10 {
println!("{}", rx.recv().unwrap());
}
}
```
Here we create 10 threads, asking each to calculate the square of a number (`i`
at the time of `spawn()`), and then `send()` back the answer over the channel.
## Panics
A `panic!` will crash the currently executing thread. You can use Rust's
threads as a simple isolation mechanism:
```rust
use std::thread;
let handle = thread::spawn(move || {
panic!("oops!");
});
let result = handle.join();
assert!(result.is_err());
```
`Thread.join()` gives us a `Result` back, which allows us to check if the thread
has panicked or not.
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/concurrency.html).

View File

@ -1,91 +1,10 @@
# Conditional Compilation
Rust has a special attribute, `#[cfg]`, which allows you to compile code
based on a flag passed to the compiler. It has two forms:
The first edition of the book is no longer distributed with Rust's documentation.
```rust
#[cfg(foo)]
# fn foo() {}
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
#[cfg(bar = "baz")]
# fn bar() {}
```
They also have some helpers:
```rust
#[cfg(any(unix, windows))]
# fn foo() {}
#[cfg(all(unix, target_pointer_width = "32"))]
# fn bar() {}
#[cfg(not(foo))]
# fn not_foo() {}
```
These can nest arbitrarily:
```rust
#[cfg(any(not(unix), all(target_os="macos", target_arch = "powerpc")))]
# fn foo() {}
```
As for how to enable or disable these switches, if youre using Cargo,
they get set in the [`[features]` section][features] of your `Cargo.toml`:
[features]: http://doc.crates.io/manifest.html#the-features-section
```toml
[features]
# no features by default
default = []
# Add feature "foo" here, then you can use it.
# Our "foo" feature depends on nothing else.
foo = []
```
When you do this, Cargo passes along a flag to `rustc`:
```text
--cfg feature="${feature_name}"
```
The sum of these `cfg` flags will determine which ones get activated, and
therefore, which code gets compiled. Lets take this code:
```rust
#[cfg(feature = "foo")]
mod foo {
}
```
If we compile it with `cargo build --features "foo"`, it will send the `--cfg
feature="foo"` flag to `rustc`, and the output will have the `mod foo` in it.
If we compile it with a regular `cargo build`, no extra flags get passed on,
and so, no `foo` module will exist.
# cfg_attr
You can also set another attribute based on a `cfg` variable with `cfg_attr`:
```rust
#[cfg_attr(a, b)]
# fn foo() {}
```
Will be the same as `#[b]` if `a` is set by `cfg` attribute, and nothing otherwise.
# cfg!
The `cfg!` macro lets you use these kinds of flags elsewhere in your code, too:
```rust
if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
println!("Think Different!");
}
```
These will be replaced by a `true` or `false` at compile-time, depending on the
configuration settings.
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/conditional-compilation.html).

View File

@ -1,89 +1,10 @@
# const and static
Rust has a way of defining constants with the `const` keyword:
The first edition of the book is no longer distributed with Rust's documentation.
```rust
const N: i32 = 5;
```
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
Unlike [`let`][let] bindings, you must annotate the type of a `const`.
[let]: variable-bindings.html
Constants live for the entire lifetime of a program. More specifically,
constants in Rust have no fixed address in memory. This is because theyre
effectively inlined to each place that theyre used. References to the same
constant are not necessarily guaranteed to refer to the same memory address for
this reason.
# `static`
Rust provides a global variable sort of facility in static items. Theyre
similar to constants, but static items arent inlined upon use. This means that
there is only one instance for each value, and its at a fixed location in
memory.
Heres an example:
```rust
static N: i32 = 5;
```
Unlike [`let`][let] bindings, you must annotate the type of a `static`.
Statics live for the entire lifetime of a program, and therefore any
reference stored in a static has a [`'static` lifetime][lifetimes]:
```rust
static NAME: &'static str = "Steve";
```
The type of a `static` value must be `Sync` unless the `static` value is
mutable.
[lifetimes]: lifetimes.html
## Mutability
You can introduce mutability with the `mut` keyword:
```rust
static mut N: i32 = 5;
```
Because this is mutable, one thread could be updating `N` while another is
reading it, causing memory unsafety. As such both accessing and mutating a
`static mut` is [`unsafe`][unsafe], and so must be done in an `unsafe` block:
```rust
# static mut N: i32 = 5;
unsafe {
N += 1;
println!("N: {}", N);
}
```
[unsafe]: unsafe.html
# Initializing
Both `const` and `static` have requirements for giving them a value. They must
be given a value thats a constant expression. In other words, you cannot use
the result of a function call or anything similarly complex or at runtime.
# Dropping
Types implementing [`Drop`][drop] are allowed in `const` and `static`
definitions. Constants are inlined where they are used and are dropped
accordingly. `static` values are not dropped.
[drop]: drop.html
# Which construct should I use?
Almost always, if you can choose between the two, choose `const`. Its pretty
rare that you actually want a memory location associated with your constant,
and using a `const` allows for optimizations like constant propagation not only
in your crate but downstream crates.
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/const-and-static.html).

View File

@ -1,598 +1,10 @@
# Crates and Modules
When a project starts getting large, its considered good software
engineering practice to split it up into a bunch of smaller pieces, and then
fit them together. It is also important to have a well-defined interface, so
that some of your functionality is private, and some is public. To facilitate
these kinds of things, Rust has a module system.
The first edition of the book is no longer distributed with Rust's documentation.
# Basic terminology: Crates and Modules
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
Rust has two distinct terms that relate to the module system: crate and
module. A crate is synonymous with a library or package in other
languages. Hence “Cargo” as the name of Rusts package management tool: you
ship your crates to others with Cargo. Crates can produce an executable or a
library, depending on the project.
Each crate has an implicit *root module* that contains the code for that crate.
You can then define a tree of sub-modules under that root module. Modules allow
you to partition your code within the crate itself.
As an example, lets make a *phrases* crate, which will give us various phrases
in different languages. To keep things simple, well stick to greetings and
farewells as two kinds of phrases, and use English and Japanese (日本語) as
two languages for those phrases to be in. Well use this module layout:
```text
+-----------+
+---| greetings |
+---------+ | +-----------+
+---| english |---+
| +---------+ | +-----------+
| +---| farewells |
+---------+ | +-----------+
| phrases |---+
+---------+ | +-----------+
| +---| greetings |
| +----------+ | +-----------+
+---| japanese |--+
+----------+ | +-----------+
+---| farewells |
+-----------+
```
In this example, `phrases` is the name of our crate. All of the rest are
modules. You can see that they form a tree, branching out from the crate
*root*, which is the root of the tree: `phrases` itself.
Now that we have a plan, lets define these modules in code. To start,
generate a new crate with Cargo:
```bash
$ cargo new phrases
$ cd phrases
```
If you remember, this generates a simple project for us:
```bash
$ tree .
.
├── Cargo.toml
└── src
└── lib.rs
1 directory, 2 files
```
`src/lib.rs` is our crate root, corresponding to the `phrases` in our diagram
above.
# Defining Modules
To define each of our modules, we use the `mod` keyword. Lets make our
`src/lib.rs` look like this:
```rust
mod english {
mod greetings {
}
mod farewells {
}
}
mod japanese {
mod greetings {
}
mod farewells {
}
}
```
After the `mod` keyword, you give the name of the module. Module names follow
the conventions for other Rust identifiers: `lower_snake_case`. The contents of
each module are within curly braces (`{}`).
Within a given `mod`, you can declare sub-`mod`s. We can refer to sub-modules
with double-colon (`::`) notation: our four nested modules are
`english::greetings`, `english::farewells`, `japanese::greetings`, and
`japanese::farewells`. Because these sub-modules are namespaced under their
parent module, the names dont conflict: `english::greetings` and
`japanese::greetings` are distinct, even though their names are both
`greetings`.
Because this crate does not have a `main()` function, and is called `lib.rs`,
Cargo will build this crate as a library:
```bash
$ cargo build
Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
$ ls target/debug
build deps examples libphrases-a7448e02a0468eaa.rlib native
```
`libphrases-<hash>.rlib` is the compiled crate. Before we see how to use this
crate from another crate, lets break it up into multiple files.
# Multiple File Crates
If each crate were just one file, these files would get very large. Its often
easier to split up crates into multiple files, and Rust supports this in two
ways.
Instead of declaring a module like this:
```rust,ignore
mod english {
// Contents of our module go here.
}
```
We can instead declare our module like this:
```rust,ignore
mod english;
```
If we do that, Rust will expect to find either a `english.rs` file, or a
`english/mod.rs` file with the contents of our module.
Note that in these files, you dont need to re-declare the module: thats
already been done with the initial `mod` declaration.
Using these two techniques, we can break up our crate into two directories and
seven files:
```bash
$ tree .
.
├── Cargo.lock
├── Cargo.toml
├── src
│   ├── english
│   │   ├── farewells.rs
│   │   ├── greetings.rs
│   │   └── mod.rs
│   ├── japanese
│   │   ├── farewells.rs
│   │   ├── greetings.rs
│   │   └── mod.rs
│   └── lib.rs
└── target
└── debug
├── build
├── deps
├── examples
├── libphrases-a7448e02a0468eaa.rlib
└── native
```
`src/lib.rs` is our crate root, and looks like this:
```rust,ignore
mod english;
mod japanese;
```
These two declarations tell Rust to look for
- either `src/english.rs` or `src/english/mod.rs`, and
- either `src/japanese.rs` or `src/japanese/mod.rs`,
depending on our preference. In this case, because our modules have sub-modules,
weve chosen the `mod.rs` approach. Both `src/english/mod.rs` and
`src/japanese/mod.rs` look like this:
```rust,ignore
mod greetings;
mod farewells;
```
Again, these declarations tell Rust to look for
- `src/english/greetings.rs` or `src/english/greetings/mod.rs`,
- `src/english/farewells.rs` or `src/english/farewells/mod.rs`,
- `src/japanese/greetings.rs` or `src/japanese/greetings/mod.rs`,
- and `src/japanese/farewells.rs` or `src/japanese/farewells/mod.rs`.
Because these sub-modules dont have
their own sub-modules, weve chosen to make them
`src/english/greetings.rs`, `src/english/farewells.rs`,
`src/japanese/greetings.rs` and `src/japanese/farewells.rs`. Whew!
The contents of `src/english/greetings.rs`,
`src/english/farewells.rs`, `src/japanese/greetings.rs` and
`src/japanese/farewells.rs` are all empty at the moment. Lets add
some functions.
Put this in `src/english/greetings.rs`:
```rust
fn hello() -> String {
"Hello!".to_string()
}
```
Put this in `src/english/farewells.rs`:
```rust
fn goodbye() -> String {
"Goodbye.".to_string()
}
```
Put this in `src/japanese/greetings.rs`:
```rust
fn hello() -> String {
"こんにちは".to_string()
}
```
Of course, you can copy and paste this from this web page, or type
something else. Its not important that you actually put konnichiwa to learn
about the module system.
Put this in `src/japanese/farewells.rs`:
```rust
fn goodbye() -> String {
"さようなら".to_string()
}
```
(This is Sayōnara, if youre curious.)
Now that we have some functionality in our crate, lets try to use it from
another crate.
# Importing External Crates
We have a library crate. Lets make an executable crate that imports and uses
our library.
Make a `src/main.rs` and put this in it (it wont quite compile yet):
```rust,ignore
extern crate phrases;
fn main() {
println!("Hello in English: {}", phrases::english::greetings::hello());
println!("Goodbye in English: {}", phrases::english::farewells::goodbye());
println!("Hello in Japanese: {}", phrases::japanese::greetings::hello());
println!("Goodbye in Japanese: {}", phrases::japanese::farewells::goodbye());
}
```
The `extern crate` declaration tells Rust that we need to compile and link to
the `phrases` crate. We can then use `phrases` modules in this one. As we
mentioned earlier, you can use double colons to refer to sub-modules and the
functions inside of them.
(Note: when importing a crate that has dashes in its name "like-this", which is
not a valid Rust identifier, it will be converted by changing the dashes to
underscores, so you would write `extern crate like_this;`.)
Also, Cargo assumes that `src/main.rs` is the crate root of a binary crate,
rather than a library crate. Our package now has two crates: `src/lib.rs` and
`src/main.rs`. This pattern is quite common for executable crates: most
functionality is in a library crate, and the executable crate uses that
library. This way, other programs can also use the library crate, and its also
a nice separation of concerns.
This doesnt quite work yet, though. We get four errors that look similar to
this:
```bash
$ cargo build
Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
src/main.rs:4:38: 4:72 error: function `hello` is private
src/main.rs:4 println!("Hello in English: {}", phrases::english::greetings::hello());
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: in expansion of format_args!
<std macros>:2:25: 2:58 note: expansion site
<std macros>:1:1: 2:62 note: in expansion of print!
<std macros>:3:1: 3:54 note: expansion site
<std macros>:1:1: 3:58 note: in expansion of println!
phrases/src/main.rs:4:5: 4:76 note: expansion site
```
By default, everything is private in Rust. Lets talk about this in some more
depth.
# Exporting a Public Interface
Rust allows you to precisely control which aspects of your interface are
public, and so private is the default. To make things public, you use the `pub`
keyword. Lets focus on the `english` module first, so lets reduce our `src/main.rs`
to only this:
```rust,ignore
extern crate phrases;
fn main() {
println!("Hello in English: {}", phrases::english::greetings::hello());
println!("Goodbye in English: {}", phrases::english::farewells::goodbye());
}
```
In our `src/lib.rs`, lets add `pub` to the `english` module declaration:
```rust,ignore
pub mod english;
mod japanese;
```
And in our `src/english/mod.rs`, lets make both `pub`:
```rust,ignore
pub mod greetings;
pub mod farewells;
```
In our `src/english/greetings.rs`, lets add `pub` to our `fn` declaration:
```rust,ignore
pub fn hello() -> String {
"Hello!".to_string()
}
```
And also in `src/english/farewells.rs`:
```rust,ignore
pub fn goodbye() -> String {
"Goodbye.".to_string()
}
```
Now, our crate compiles, albeit with warnings about not using the `japanese`
functions:
```bash
$ cargo run
Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
src/japanese/greetings.rs:1:1: 3:2 warning: function is never used: `hello`, #[warn(dead_code)] on by default
src/japanese/greetings.rs:1 fn hello() -> String {
src/japanese/greetings.rs:2 "こんにちは".to_string()
src/japanese/greetings.rs:3 }
src/japanese/farewells.rs:1:1: 3:2 warning: function is never used: `goodbye`, #[warn(dead_code)] on by default
src/japanese/farewells.rs:1 fn goodbye() -> String {
src/japanese/farewells.rs:2 "さようなら".to_string()
src/japanese/farewells.rs:3 }
Running `target/debug/phrases`
Hello in English: Hello!
Goodbye in English: Goodbye.
```
`pub` also applies to `struct`s and their member fields. In keeping with Rusts
tendency toward safety, simply making a `struct` public won't automatically
make its members public: you must mark the fields individually with `pub`.
Now that our functions are public, we can use them. Great! However, typing out
`phrases::english::greetings::hello()` is very long and repetitive. Rust has
another keyword for importing names into the current scope, so that you can
refer to them with shorter names. Lets talk about `use`.
# Importing Modules with `use`
Rust has a `use` keyword, which allows us to import names into our local scope.
Lets change our `src/main.rs` to look like this:
```rust,ignore
extern crate phrases;
use phrases::english::greetings;
use phrases::english::farewells;
fn main() {
println!("Hello in English: {}", greetings::hello());
println!("Goodbye in English: {}", farewells::goodbye());
}
```
The two `use` lines import each module into the local scope, so we can refer to
the functions by a much shorter name. By convention, when importing functions, its
considered best practice to import the module, rather than the function directly. In
other words, you _can_ do this:
```rust,ignore
extern crate phrases;
use phrases::english::greetings::hello;
use phrases::english::farewells::goodbye;
fn main() {
println!("Hello in English: {}", hello());
println!("Goodbye in English: {}", goodbye());
}
```
But it is not idiomatic. This is significantly more likely to introduce a
naming conflict. In our short program, its not a big deal, but as it grows, it
becomes a problem. If we have conflicting names, Rust will give a compilation
error. For example, if we made the `japanese` functions public, and tried to do
this:
```rust,ignore
extern crate phrases;
use phrases::english::greetings::hello;
use phrases::japanese::greetings::hello;
fn main() {
println!("Hello in English: {}", hello());
println!("Hello in Japanese: {}", hello());
}
```
Rust will give us a compile-time error:
```text
Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
src/main.rs:4:5: 4:40 error: a value named `hello` has already been imported in this module [E0252]
src/main.rs:4 use phrases::japanese::greetings::hello;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
Could not compile `phrases`.
```
If were importing multiple names from the same module, we dont have to type it out
twice. Instead of this:
```rust,ignore
use phrases::english::greetings;
use phrases::english::farewells;
```
We can use this shortcut:
```rust,ignore
use phrases::english::{greetings, farewells};
```
## Re-exporting with `pub use`
You dont only use `use` to shorten identifiers. You can also use it inside of your crate
to re-export a function inside another module. This allows you to present an external
interface that may not directly map to your internal code organization.
Lets look at an example. Modify your `src/main.rs` to read like this:
```rust,ignore
extern crate phrases;
use phrases::english::{greetings,farewells};
use phrases::japanese;
fn main() {
println!("Hello in English: {}", greetings::hello());
println!("Goodbye in English: {}", farewells::goodbye());
println!("Hello in Japanese: {}", japanese::hello());
println!("Goodbye in Japanese: {}", japanese::goodbye());
}
```
Then, modify your `src/lib.rs` to make the `japanese` mod public:
```rust,ignore
pub mod english;
pub mod japanese;
```
Next, make the two functions public, first in `src/japanese/greetings.rs`:
```rust,ignore
pub fn hello() -> String {
"こんにちは".to_string()
}
```
And then in `src/japanese/farewells.rs`:
```rust,ignore
pub fn goodbye() -> String {
"さようなら".to_string()
}
```
Finally, modify your `src/japanese/mod.rs` to read like this:
```rust,ignore
pub use self::greetings::hello;
pub use self::farewells::goodbye;
mod greetings;
mod farewells;
```
The `pub use` declaration brings the function into scope at this part of our
module hierarchy. Because weve `pub use`d this inside of our `japanese`
module, we now have a `phrases::japanese::hello()` function and a
`phrases::japanese::goodbye()` function, even though the code for them lives in
`phrases::japanese::greetings::hello()` and
`phrases::japanese::farewells::goodbye()`. Our internal organization doesnt
define our external interface.
Here we have a `pub use` for each function we want to bring into the
`japanese` scope. We could alternatively use the wildcard syntax to include
everything from `greetings` into the current scope: `pub use self::greetings::*`.
What about the `self`? Well, by default, `use` declarations are absolute paths,
starting from your crate root. `self` makes that path relative to your current
place in the hierarchy instead. Theres one more special form of `use`: you can
`use super::` to reach one level up the tree from your current location. Some
people like to think of `self` as `.` and `super` as `..`, from many shells
display for the current directory and the parent directory.
Outside of `use`, paths are relative: `foo::bar()` refers to a function inside
of `foo` relative to where we are. If thats prefixed with `::`, as in
`::foo::bar()`, it refers to a different `foo`, an absolute path from your
crate root.
This will build and run:
```bash
$ cargo run
Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
Running `target/debug/phrases`
Hello in English: Hello!
Goodbye in English: Goodbye.
Hello in Japanese: こんにちは
Goodbye in Japanese: さようなら
```
## Complex imports
Rust offers several advanced options that can add compactness and
convenience to your `extern crate` and `use` statements. Here is an example:
```rust,ignore
extern crate phrases as sayings;
use sayings::japanese::greetings as ja_greetings;
use sayings::japanese::farewells::*;
use sayings::english::{self, greetings as en_greetings, farewells as en_farewells};
fn main() {
println!("Hello in English; {}", en_greetings::hello());
println!("And in Japanese: {}", ja_greetings::hello());
println!("Goodbye in English: {}", english::farewells::goodbye());
println!("Again: {}", en_farewells::goodbye());
println!("And in Japanese: {}", goodbye());
}
```
What's going on here?
First, both `extern crate` and `use` allow renaming the thing that is being
imported. So the crate is still called "phrases", but here we will refer
to it as "sayings". Similarly, the first `use` statement pulls in the
`japanese::greetings` module from the crate, but makes it available as
`ja_greetings` as opposed to simply `greetings`. This can help to avoid
ambiguity when importing similarly-named items from different places.
The second `use` statement uses a star glob to bring in all public symbols from
the `sayings::japanese::farewells` module. As you can see we can later refer to
the Japanese `goodbye` function with no module qualifiers. This kind of glob
should be used sparingly. Its worth noting that it only imports the public
symbols, even if the code doing the globbing is in the same module.
The third `use` statement bears more explanation. It's using "brace expansion"
globbing to compress three `use` statements into one (this sort of syntax
may be familiar if you've written Linux shell scripts before). The
uncompressed form of this statement would be:
```rust,ignore
use sayings::english;
use sayings::english::greetings as en_greetings;
use sayings::english::farewells as en_farewells;
```
As you can see, the curly brackets compress `use` statements for several items
under the same path, and in this context `self` refers back to that path.
Note: The curly brackets cannot be nested or mixed with star globbing.
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/crates-and-modules.html).

View File

@ -1,119 +1,10 @@
# `Deref` coercions
The standard library provides a special trait, [`Deref`][deref]. Its normally
used to overload `*`, the dereference operator:
The first edition of the book is no longer distributed with Rust's documentation.
```rust
use std::ops::Deref;
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
struct DerefExample<T> {
value: T,
}
impl<T> Deref for DerefExample<T> {
type Target = T;
fn deref(&self) -> &T {
&self.value
}
}
fn main() {
let x = DerefExample { value: 'a' };
assert_eq!('a', *x);
}
```
[deref]: ../../std/ops/trait.Deref.html
This is useful for writing custom pointer types. However, theres a language
feature related to `Deref`: deref coercions. Heres the rule: If you have a
type `U`, and it implements `Deref<Target=T>`, values of `&U` will
automatically coerce to a `&T`. Heres an example:
```rust
fn foo(s: &str) {
// Borrow a string for a second.
}
// String implements Deref<Target=str>.
let owned = "Hello".to_string();
// Therefore, this works:
foo(&owned);
```
Using an ampersand in front of a value takes a reference to it. So `owned` is a
`String`, `&owned` is an `&String`, and since `impl Deref<Target=str> for
String`, `&String` will deref to `&str`, which `foo()` takes.
Thats it. This rule is one of the only places in which Rust does an automatic
conversion for you, but it adds a lot of flexibility. For example, the `Rc<T>`
type implements `Deref<Target=T>`, so this works:
```rust
use std::rc::Rc;
fn foo(s: &str) {
// Borrow a string for a second.
}
// String implements Deref<Target=str>.
let owned = "Hello".to_string();
let counted = Rc::new(owned);
// Therefore, this works:
foo(&counted);
```
All weve done is wrap our `String` in an `Rc<T>`. But we can now pass the
`Rc<String>` around anywhere wed have a `String`. The signature of `foo`
didnt change, but works just as well with either type. This example has two
conversions: `&Rc<String>` to `&String` and then `&String` to `&str`. Rust will do
this as many times as possible until the types match.
Another very common implementation provided by the standard library is:
```rust
fn foo(s: &[i32]) {
// Borrow a slice for a second.
}
// Vec<T> implements Deref<Target=[T]>.
let owned = vec![1, 2, 3];
foo(&owned);
```
Vectors can `Deref` to a slice.
## Deref and method calls
`Deref` will also kick in when calling a method. Consider the following
example.
```rust
struct Foo;
impl Foo {
fn foo(&self) { println!("Foo"); }
}
let f = &&Foo;
f.foo();
```
Even though `f` is a `&&Foo` and `foo` takes `&self`, this works. Thats
because these things are the same:
```rust,ignore
f.foo();
(&f).foo();
(&&f).foo();
(&&&&&&&&f).foo();
```
A value of type `&&&&&&&&&&&&&&&&Foo` can still have methods defined on `Foo`
called, because the compiler will insert as many * operations as necessary to
get it right. And since its inserting `*`s, that uses `Deref`.
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/deref-coercions.html).

View File

@ -1,655 +1,10 @@
# Documentation
Documentation is an important part of any software project, and it's
first-class in Rust. Let's talk about the tooling Rust gives you to
document your project.
The first edition of the book is no longer distributed with Rust's documentation.
## About `rustdoc`
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
The Rust distribution includes a tool, `rustdoc`, that generates documentation.
`rustdoc` is also used by Cargo through `cargo doc`.
Documentation can be generated in two ways: from source code, and from
standalone Markdown files.
## Documenting source code
The primary way of documenting a Rust project is through annotating the source
code. You can use documentation comments for this purpose:
```rust,ignore
/// Constructs a new `Rc<T>`.
///
/// # Examples
///
/// ```
/// use std::rc::Rc;
///
/// let five = Rc::new(5);
/// ```
pub fn new(value: T) -> Rc<T> {
// Implementation goes here.
}
```
This code generates documentation that looks [like this][rc-new]. I've left the
implementation out, with a regular comment in its place.
The first thing to notice about this annotation is that it uses
`///` instead of `//`. The triple slash
indicates a documentation comment.
Documentation comments are written in Markdown.
Rust keeps track of these comments, and uses them when generating
documentation. This is important when documenting things like enums:
```rust
/// The `Option` type. See [the module level documentation](index.html) for more.
enum Option<T> {
/// No value
None,
/// Some value `T`
Some(T),
}
```
The above works, but this does not:
```rust,ignore
/// The `Option` type. See [the module level documentation](index.html) for more.
enum Option<T> {
None, /// No value
Some(T), /// Some value `T`
}
```
You'll get an error:
```text
hello.rs:4:1: 4:2 error: expected ident, found `}`
hello.rs:4 }
^
```
This [unfortunate error](https://github.com/rust-lang/rust/issues/22547) is
correct; documentation comments apply to the thing after them, and there's
nothing after that last comment.
[rc-new]: ../../std/rc/struct.Rc.html#method.new
### Writing documentation comments
Anyway, let's cover each part of this comment in detail:
```rust
/// Constructs a new `Rc<T>`.
# fn foo() {}
```
The first line of a documentation comment should be a short summary of its
functionality. One sentence. Just the basics. High level.
```rust
///
/// Other details about constructing `Rc<T>`s, maybe describing complicated
/// semantics, maybe additional options, all kinds of stuff.
///
# fn foo() {}
```
Our original example had just a summary line, but if we had more things to say,
we could have added more explanation in a new paragraph.
#### Special sections
Next, are special sections. These are indicated with a header, `#`. There
are four kinds of headers that are commonly used. They aren't special syntax,
just convention, for now.
```rust
/// # Panics
# fn foo() {}
```
Unrecoverable misuses of a function (i.e. programming errors) in Rust are
usually indicated by panics, which kill the whole current thread at the very
least. If your function has a non-trivial contract like this, that is
detected/enforced by panics, documenting it is very important.
```rust
/// # Errors
# fn foo() {}
```
If your function or method returns a `Result<T, E>`, then describing the
conditions under which it returns `Err(E)` is a nice thing to do. This is
slightly less important than `Panics`, because failure is encoded into the type
system, but it's still a good thing to do.
```rust
/// # Safety
# fn foo() {}
```
If your function is `unsafe`, you should explain which invariants the caller is
responsible for upholding.
```rust
/// # Examples
///
/// ```
/// use std::rc::Rc;
///
/// let five = Rc::new(5);
/// ```
# fn foo() {}
```
Fourth, `Examples`. Include one or more examples of using your function or
method, and your users will love you for it. These examples go inside of
code block annotations, which we'll talk about in a moment, and can have
more than one section:
```rust
/// # Examples
///
/// Simple `&str` patterns:
///
/// ```
/// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect();
/// assert_eq!(v, vec!["Mary", "had", "a", "little", "lamb"]);
/// ```
///
/// More complex patterns with a lambda:
///
/// ```
/// let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_numeric()).collect();
/// assert_eq!(v, vec!["abc", "def", "ghi"]);
/// ```
# fn foo() {}
```
#### Code block annotations
To write some Rust code in a comment, use the triple graves:
```rust
/// ```
/// println!("Hello, world");
/// ```
# fn foo() {}
```
This will add code highlighting. If you are only showing plain text, put `text`
instead of `rust` after the triple graves (see below).
## Documentation as tests
Let's discuss our sample example documentation:
```rust
/// ```
/// println!("Hello, world");
/// ```
# fn foo() {}
```
You'll notice that you don't need a `fn main()` or anything here. `rustdoc` will
automatically add a `main()` wrapper around your code, using heuristics to attempt
to put it in the right place. For example:
```rust
/// ```
/// use std::rc::Rc;
///
/// let five = Rc::new(5);
/// ```
# fn foo() {}
```
This will end up testing:
```rust
fn main() {
use std::rc::Rc;
let five = Rc::new(5);
}
```
Here's the full algorithm rustdoc uses to preprocess examples:
1. Any leading `#![foo]` attributes are left intact as crate attributes.
2. Some common `allow` attributes are inserted, including
`unused_variables`, `unused_assignments`, `unused_mut`,
`unused_attributes`, and `dead_code`. Small examples often trigger
these lints.
3. If the example does not contain `extern crate`, then `extern crate
<mycrate>;` is inserted (note the lack of `#[macro_use]`).
4. Finally, if the example does not contain `fn main`, the remainder of the
text is wrapped in `fn main() { your_code }`.
This generated `fn main` can be a problem! If you have `extern crate` or a `mod`
statements in the example code that are referred to by `use` statements, they will
fail to resolve unless you include at least `fn main() {}` to inhibit step 4.
`#[macro_use] extern crate` also does not work except at the crate root, so when
testing macros an explicit `main` is always required. It doesn't have to clutter
up your docs, though -- keep reading!
Sometimes this algorithm isn't enough, though. For example, all of these code samples
with `///` we've been talking about? The raw text:
```text
/// Some documentation.
# fn foo() {}
```
looks different than the output:
```rust
/// Some documentation.
# fn foo() {}
```
Yes, that's right: you can add lines that start with `# `, and they will
be hidden from the output, but will be used when compiling your code. You
can use this to your advantage. In this case, documentation comments need
to apply to some kind of function, so if I want to show you just a
documentation comment, I need to add a little function definition below
it. At the same time, it's only there to satisfy the compiler, so hiding
it makes the example more clear. You can use this technique to explain
longer examples in detail, while still preserving the testability of your
documentation.
For example, imagine that we wanted to document this code:
```rust
let x = 5;
let y = 6;
println!("{}", x + y);
```
We might want the documentation to end up looking like this:
> First, we set `x` to five:
>
> ```rust
> let x = 5;
> # let y = 6;
> # println!("{}", x + y);
> ```
>
> Next, we set `y` to six:
>
> ```rust
> # let x = 5;
> let y = 6;
> # println!("{}", x + y);
> ```
>
> Finally, we print the sum of `x` and `y`:
>
> ```rust
> # let x = 5;
> # let y = 6;
> println!("{}", x + y);
> ```
To keep each code block testable, we want the whole program in each block, but
we don't want the reader to see every line every time. Here's what we put in
our source code:
```text
First, we set `x` to five:
```rust
let x = 5;
# let y = 6;
# println!("{}", x + y);
```
Next, we set `y` to six:
```rust
# let x = 5;
let y = 6;
# println!("{}", x + y);
```
Finally, we print the sum of `x` and `y`:
```rust
# let x = 5;
# let y = 6;
println!("{}", x + y);
```
```
By repeating all parts of the example, you can ensure that your example still
compiles, while only showing the parts that are relevant to that part of your
explanation.
### Documenting macros
Heres an example of documenting a macro:
```rust
/// Panic with a given message unless an expression evaluates to true.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate foo;
/// # fn main() {
/// panic_unless!(1 + 1 == 2, “Math is broken.”);
/// # }
/// ```
///
/// ```rust,should_panic
/// # #[macro_use] extern crate foo;
/// # fn main() {
/// panic_unless!(true == false, “Im broken.”);
/// # }
/// ```
#[macro_export]
macro_rules! panic_unless {
($condition:expr, $($rest:expr),+) => ({ if ! $condition { panic!($($rest),+); } });
}
# fn main() {}
```
Youll note three things: we need to add our own `extern crate` line, so that
we can add the `#[macro_use]` attribute. Second, well need to add our own
`main()` as well (for reasons discussed above). Finally, a judicious use of
`#` to comment out those two things, so they dont show up in the output.
Another case where the use of `#` is handy is when you want to ignore
error handling. Lets say you want the following,
```rust,ignore
/// use std::io;
/// let mut input = String::new();
/// try!(io::stdin().read_line(&mut input));
```
The problem is that `try!` returns a `Result<T, E>` and test functions
don't return anything so this will give a mismatched types error.
```rust,ignore
/// A doc test using try!
///
/// ```
/// use std::io;
/// # fn foo() -> io::Result<()> {
/// let mut input = String::new();
/// try!(io::stdin().read_line(&mut input));
/// # Ok(())
/// # }
/// ```
# fn foo() {}
```
You can get around this by wrapping the code in a function. This catches
and swallows the `Result<T, E>` when running tests on the docs. This
pattern appears regularly in the standard library.
### Running documentation tests
To run the tests, either:
```bash
$ rustdoc --test path/to/my/crate/root.rs
# or
$ cargo test
```
That's right, `cargo test` tests embedded documentation too. **However,
`cargo test` will not test binary crates, only library ones.** This is
due to the way `rustdoc` works: it links against the library to be tested,
but with a binary, theres nothing to link to.
There are a few more annotations that are useful to help `rustdoc` do the right
thing when testing your code:
```rust
/// ```rust,ignore
/// fn foo() {
/// ```
# fn foo() {}
```
The `ignore` directive tells Rust to ignore your code. This is almost never
what you want, as it's the most generic. Instead, consider annotating it
with `text` if it's not code, or using `#`s to get a working example that
only shows the part you care about.
```rust
/// ```rust,should_panic
/// assert!(false);
/// ```
# fn foo() {}
```
`should_panic` tells `rustdoc` that the code should compile correctly, but
not actually pass as a test.
```rust
/// ```rust,no_run
/// loop {
/// println!("Hello, world");
/// }
/// ```
# fn foo() {}
```
The `no_run` attribute will compile your code, but not run it. This is
important for examples such as "Here's how to retrieve a web page,"
which you would want to ensure compiles, but might be run in a test
environment that has no network access.
### Documenting modules
Rust has another kind of doc comment, `//!`. This comment doesn't document the next item, but the enclosing item. In other words:
```rust
mod foo {
//! This is documentation for the `foo` module.
//!
//! # Examples
// ...
}
```
This is where you'll see `//!` used most often: for module documentation. If
you have a module in `foo.rs`, you'll often open its code and see this:
```rust
//! A module for using `foo`s.
//!
//! The `foo` module contains a lot of useful functionality blah blah blah...
```
### Crate documentation
Crates can be documented by placing an inner doc comment (`//!`) at the
beginning of the crate root, aka `lib.rs`:
```rust
//! This is documentation for the `foo` crate.
//!
//! The foo crate is meant to be used for bar.
```
### Documentation comment style
Check out [RFC 505][rfc505] for full conventions around the style and format of
documentation.
[rfc505]: https://github.com/rust-lang/rfcs/blob/master/text/0505-api-comment-conventions.md
## Other documentation
All of this behavior works in non-Rust source files too. Because comments
are written in Markdown, they're often `.md` files.
When you write documentation in Markdown files, you don't need to prefix
the documentation with comments. For example:
```rust
/// # Examples
///
/// ```
/// use std::rc::Rc;
///
/// let five = Rc::new(5);
/// ```
# fn foo() {}
```
is:
~~~markdown
# Examples
```
use std::rc::Rc;
let five = Rc::new(5);
```
~~~
when it's in a Markdown file. There is one wrinkle though: Markdown files need
to have a title like this:
```markdown
% The title
This is the example documentation.
```
This `%` line needs to be the very first line of the file.
## `doc` attributes
At a deeper level, documentation comments are syntactic sugar for documentation
attributes:
```rust
/// this
# fn foo() {}
#[doc="this"]
# fn bar() {}
```
are the same, as are these:
```rust
//! this
#![doc="this"]
```
You won't often see this attribute used for writing documentation, but it
can be useful when changing some options, or when writing a macro.
### Re-exports
`rustdoc` will show the documentation for a public re-export in both places:
```rust,ignore
extern crate foo;
pub use foo::bar;
```
This will create documentation for `bar` both inside the documentation for the
crate `foo`, as well as the documentation for your crate. It will use the same
documentation in both places.
This behavior can be suppressed with `no_inline`:
```rust,ignore
extern crate foo;
#[doc(no_inline)]
pub use foo::bar;
```
## Missing documentation
Sometimes you want to make sure that every single public thing in your project
is documented, especially when you are working on a library. Rust allows you to
to generate warnings or errors, when an item is missing documentation.
To generate warnings you use `warn`:
```rust,ignore
#![warn(missing_docs)]
```
And to generate errors you use `deny`:
```rust,ignore
#![deny(missing_docs)]
```
There are cases where you want to disable these warnings/errors to explicitly
leave something undocumented. This is done by using `allow`:
```rust
#[allow(missing_docs)]
struct Undocumented;
```
You might even want to hide items from the documentation completely:
```rust
#[doc(hidden)]
struct Hidden;
```
### Controlling HTML
You can control a few aspects of the HTML that `rustdoc` generates through the
`#![doc]` version of the attribute:
```rust,ignore
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://www.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/")]
```
This sets a few different options, with a logo, favicon, and a root URL.
### Configuring documentation tests
You can also configure the way that `rustdoc` tests your documentation examples
through the `#![doc(test(..))]` attribute.
```rust
#![doc(test(attr(allow(unused_variables), deny(warnings))))]
```
This allows unused variables within the examples, but will fail the test for any
other lint warning thrown.
## Generation options
`rustdoc` also contains a few other options on the command line, for further customization:
- `--html-in-header FILE`: includes the contents of FILE at the end of the
`<head>...</head>` section.
- `--html-before-content FILE`: includes the contents of FILE directly after
`<body>`, before the rendered content (including the search bar).
- `--html-after-content FILE`: includes the contents of FILE after all the rendered content.
## Security note
The Markdown in documentation comments is placed without processing into
the final webpage. Be careful with literal HTML:
```rust
/// <script>alert(document.cookie)</script>
# fn foo() {}
```
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/documentation.html).

View File

@ -1,67 +1,10 @@
# Drop
Now that weve discussed traits, lets talk about a particular trait provided
by the Rust standard library, [`Drop`][drop]. The `Drop` trait provides a way
to run some code when a value goes out of scope. For example:
The first edition of the book is no longer distributed with Rust's documentation.
[drop]: ../../std/ops/trait.Drop.html
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
```rust
struct HasDrop;
impl Drop for HasDrop {
fn drop(&mut self) {
println!("Dropping!");
}
}
fn main() {
let x = HasDrop;
// Do stuff.
} // `x` goes out of scope here.
```
When `x` goes out of scope at the end of `main()`, the code for `Drop` will
run. `Drop` has one method, which is also called `drop()`. It takes a mutable
reference to `self`.
Thats it! The mechanics of `Drop` are very simple, but there are some
subtleties. For example, values are dropped in the opposite order they are
declared. Heres another example:
```rust
struct Firework {
strength: i32,
}
impl Drop for Firework {
fn drop(&mut self) {
println!("BOOM times {}!!!", self.strength);
}
}
fn main() {
let firecracker = Firework { strength: 1 };
let tnt = Firework { strength: 100 };
}
```
This will output:
```text
BOOM times 100!!!
BOOM times 1!!!
```
The `tnt` goes off before the `firecracker` does, because it was declared
afterwards. Last in, first out.
So what is `Drop` good for? Generally, `Drop` is used to clean up any resources
associated with a `struct`. For example, the [`Arc<T>` type][arc] is a
reference-counted type. When `Drop` is called, it will decrement the reference
count, and if the total number of references is zero, will clean up the
underlying value.
[arc]: ../../std/sync/struct.Arc.html
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/drop.html).

View File

@ -1,8 +1,10 @@
# Effective Rust
So youve learned how to write some Rust code. But theres a difference between
writing *any* Rust code and writing *good* Rust code.
The first edition of the book is no longer distributed with Rust's documentation.
This chapter consists of relatively independent tutorials which show you how to
take your Rust to the next level. Common patterns and standard library features
will be introduced. Read these sections in any order of your choosing.
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/effective-rust.html).

View File

@ -1,107 +1,10 @@
# Enums
An `enum` in Rust is a type that represents data that is one of
several possible variants. Each variant in the `enum` can optionally
have data associated with it:
The first edition of the book is no longer distributed with Rust's documentation.
```rust
enum Message {
Quit,
ChangeColor(i32, i32, i32),
Move { x: i32, y: i32 },
Write(String),
}
```
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
The syntax for defining variants resembles the syntaxes used to define structs:
you can have variants with no data (like unit-like structs), variants with named
data, and variants with unnamed data (like tuple structs). Unlike
separate struct definitions, however, an `enum` is a single type. A
value of the enum can match any of the variants. For this reason, an
enum is sometimes called a sum type: the set of possible values of the
enum is the sum of the sets of possible values for each variant.
We use the `::` syntax to use the name of each variant: theyre scoped by the name
of the `enum` itself. This allows both of these to work:
```rust
# enum Message {
# Move { x: i32, y: i32 },
# }
let x: Message = Message::Move { x: 3, y: 4 };
enum BoardGameTurn {
Move { squares: i32 },
Pass,
}
let y: BoardGameTurn = BoardGameTurn::Move { squares: 1 };
```
Both variants are named `Move`, but since theyre scoped to the name of
the enum, they can both be used without conflict.
A value of an `enum` type contains information about which variant it is,
in addition to any data associated with that variant. This is sometimes
referred to as a tagged union, since the data includes a tag
indicating what type it is. The compiler uses this information to
enforce that youre accessing the data in the enum safely. For instance,
you cant simply try to destructure a value as if it were one of the
possible variants:
```rust,ignore
fn process_color_change(msg: Message) {
let Message::ChangeColor(r, g, b) = msg; // This causes a compile-time error.
}
```
Not supporting these operations may seem rather limiting, but its a limitation
which we can overcome. There are two ways: by implementing equality ourselves,
or by pattern matching variants with [`match`][match] expressions, which youll
learn in the next section. We dont know enough about Rust to implement
equality yet, but well find out in the [`traits`][traits] section.
[match]: match.html
[traits]: traits.html
# Constructors as functions
An `enum` constructor can also be used like a function. For example:
```rust
# enum Message {
# Write(String),
# }
let m = Message::Write("Hello, world".to_string());
```
is the same as
```rust
# enum Message {
# Write(String),
# }
fn foo(x: String) -> Message {
Message::Write(x)
}
let x = foo("Hello, world".to_string());
```
This is not immediately useful to us, but when we get to
[`closures`][closures], well talk about passing functions as arguments to
other functions. For example, with [`iterators`][iterators], we can do this
to convert a vector of `String`s into a vector of `Message::Write`s:
```rust
# enum Message {
# Write(String),
# }
let v = vec!["Hello".to_string(), "World".to_string()];
let v1: Vec<Message> = v.into_iter().map(Message::Write).collect();
```
[closures]: closures.html
[iterators]: iterators.html
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/enums.html).

File diff suppressed because it is too large Load Diff

View File

@ -1,758 +1,10 @@
# Foreign Function Interface
# Introduction
The first edition of the book is no longer distributed with Rust's documentation.
This guide will use the [snappy](https://github.com/google/snappy)
compression/decompression library as an introduction to writing bindings for
foreign code. Rust is currently unable to call directly into a C++ library, but
snappy includes a C interface (documented in
[`snappy-c.h`](https://github.com/google/snappy/blob/master/snappy-c.h)).
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
## A note about libc
Many of these examples use [the `libc` crate][libc], which provides various
type definitions for C types, among other things. If youre trying these
examples yourself, youll need to add `libc` to your `Cargo.toml`:
```toml
[dependencies]
libc = "0.2.0"
```
[libc]: https://crates.io/crates/libc
and add `extern crate libc;` to your crate root.
## Calling foreign functions
The following is a minimal example of calling a foreign function which will
compile if snappy is installed:
```rust,ignore
extern crate libc;
use libc::size_t;
#[link(name = "snappy")]
extern {
fn snappy_max_compressed_length(source_length: size_t) -> size_t;
}
fn main() {
let x = unsafe { snappy_max_compressed_length(100) };
println!("max compressed length of a 100 byte buffer: {}", x);
}
```
The `extern` block is a list of function signatures in a foreign library, in
this case with the platform's C ABI. The `#[link(...)]` attribute is used to
instruct the linker to link against the snappy library so the symbols are
resolved.
Foreign functions are assumed to be unsafe so calls to them need to be wrapped
with `unsafe {}` as a promise to the compiler that everything contained within
truly is safe. C libraries often expose interfaces that aren't thread-safe, and
almost any function that takes a pointer argument isn't valid for all possible
inputs since the pointer could be dangling, and raw pointers fall outside of
Rust's safe memory model.
When declaring the argument types to a foreign function, the Rust compiler
cannot check if the declaration is correct, so specifying it correctly is part
of keeping the binding correct at runtime.
The `extern` block can be extended to cover the entire snappy API:
```rust,ignore
extern crate libc;
use libc::{c_int, size_t};
#[link(name = "snappy")]
extern {
fn snappy_compress(input: *const u8,
input_length: size_t,
compressed: *mut u8,
compressed_length: *mut size_t) -> c_int;
fn snappy_uncompress(compressed: *const u8,
compressed_length: size_t,
uncompressed: *mut u8,
uncompressed_length: *mut size_t) -> c_int;
fn snappy_max_compressed_length(source_length: size_t) -> size_t;
fn snappy_uncompressed_length(compressed: *const u8,
compressed_length: size_t,
result: *mut size_t) -> c_int;
fn snappy_validate_compressed_buffer(compressed: *const u8,
compressed_length: size_t) -> c_int;
}
# fn main() {}
```
# Creating a safe interface
The raw C API needs to be wrapped to provide memory safety and make use of higher-level concepts
like vectors. A library can choose to expose only the safe, high-level interface and hide the unsafe
internal details.
Wrapping the functions which expect buffers involves using the `slice::raw` module to manipulate Rust
vectors as pointers to memory. Rust's vectors are guaranteed to be a contiguous block of memory. The
length is the number of elements currently contained, and the capacity is the total size in elements of
the allocated memory. The length is less than or equal to the capacity.
```rust,ignore
# extern crate libc;
# use libc::{c_int, size_t};
# unsafe fn snappy_validate_compressed_buffer(_: *const u8, _: size_t) -> c_int { 0 }
# fn main() {}
pub fn validate_compressed_buffer(src: &[u8]) -> bool {
unsafe {
snappy_validate_compressed_buffer(src.as_ptr(), src.len() as size_t) == 0
}
}
```
The `validate_compressed_buffer` wrapper above makes use of an `unsafe` block, but it makes the
guarantee that calling it is safe for all inputs by leaving off `unsafe` from the function
signature.
The `snappy_compress` and `snappy_uncompress` functions are more complex, since a buffer has to be
allocated to hold the output too.
The `snappy_max_compressed_length` function can be used to allocate a vector with the maximum
required capacity to hold the compressed output. The vector can then be passed to the
`snappy_compress` function as an output parameter. An output parameter is also passed to retrieve
the true length after compression for setting the length.
```rust,ignore
# extern crate libc;
# use libc::{size_t, c_int};
# unsafe fn snappy_compress(a: *const u8, b: size_t, c: *mut u8,
# d: *mut size_t) -> c_int { 0 }
# unsafe fn snappy_max_compressed_length(a: size_t) -> size_t { a }
# fn main() {}
pub fn compress(src: &[u8]) -> Vec<u8> {
unsafe {
let srclen = src.len() as size_t;
let psrc = src.as_ptr();
let mut dstlen = snappy_max_compressed_length(srclen);
let mut dst = Vec::with_capacity(dstlen as usize);
let pdst = dst.as_mut_ptr();
snappy_compress(psrc, srclen, pdst, &mut dstlen);
dst.set_len(dstlen as usize);
dst
}
}
```
Decompression is similar, because snappy stores the uncompressed size as part of the compression
format and `snappy_uncompressed_length` will retrieve the exact buffer size required.
```rust,ignore
# extern crate libc;
# use libc::{size_t, c_int};
# unsafe fn snappy_uncompress(compressed: *const u8,
# compressed_length: size_t,
# uncompressed: *mut u8,
# uncompressed_length: *mut size_t) -> c_int { 0 }
# unsafe fn snappy_uncompressed_length(compressed: *const u8,
# compressed_length: size_t,
# result: *mut size_t) -> c_int { 0 }
# fn main() {}
pub fn uncompress(src: &[u8]) -> Option<Vec<u8>> {
unsafe {
let srclen = src.len() as size_t;
let psrc = src.as_ptr();
let mut dstlen: size_t = 0;
snappy_uncompressed_length(psrc, srclen, &mut dstlen);
let mut dst = Vec::with_capacity(dstlen as usize);
let pdst = dst.as_mut_ptr();
if snappy_uncompress(psrc, srclen, pdst, &mut dstlen) == 0 {
dst.set_len(dstlen as usize);
Some(dst)
} else {
None // SNAPPY_INVALID_INPUT
}
}
}
```
Then, we can add some tests to show how to use them.
```rust,ignore
# extern crate libc;
# use libc::{c_int, size_t};
# unsafe fn snappy_compress(input: *const u8,
# input_length: size_t,
# compressed: *mut u8,
# compressed_length: *mut size_t)
# -> c_int { 0 }
# unsafe fn snappy_uncompress(compressed: *const u8,
# compressed_length: size_t,
# uncompressed: *mut u8,
# uncompressed_length: *mut size_t)
# -> c_int { 0 }
# unsafe fn snappy_max_compressed_length(source_length: size_t) -> size_t { 0 }
# unsafe fn snappy_uncompressed_length(compressed: *const u8,
# compressed_length: size_t,
# result: *mut size_t)
# -> c_int { 0 }
# unsafe fn snappy_validate_compressed_buffer(compressed: *const u8,
# compressed_length: size_t)
# -> c_int { 0 }
# fn main() { }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn valid() {
let d = vec![0xde, 0xad, 0xd0, 0x0d];
let c: &[u8] = &compress(&d);
assert!(validate_compressed_buffer(c));
assert!(uncompress(c) == Some(d));
}
#[test]
fn invalid() {
let d = vec![0, 0, 0, 0];
assert!(!validate_compressed_buffer(&d));
assert!(uncompress(&d).is_none());
}
#[test]
fn empty() {
let d = vec![];
assert!(!validate_compressed_buffer(&d));
assert!(uncompress(&d).is_none());
let c = compress(&d);
assert!(validate_compressed_buffer(&c));
assert!(uncompress(&c) == Some(d));
}
}
```
# Destructors
Foreign libraries often hand off ownership of resources to the calling code.
When this occurs, we must use Rust's destructors to provide safety and guarantee
the release of these resources (especially in the case of panic).
For more about destructors, see the [Drop trait](../../std/ops/trait.Drop.html).
# Callbacks from C code to Rust functions
Some external libraries require the usage of callbacks to report back their
current state or intermediate data to the caller.
It is possible to pass functions defined in Rust to an external library.
The requirement for this is that the callback function is marked as `extern`
with the correct calling convention to make it callable from C code.
The callback function can then be sent through a registration call
to the C library and afterwards be invoked from there.
A basic example is:
Rust code:
```rust,no_run
extern fn callback(a: i32) {
println!("I'm called from C with value {0}", a);
}
#[link(name = "extlib")]
extern {
fn register_callback(cb: extern fn(i32)) -> i32;
fn trigger_callback();
}
fn main() {
unsafe {
register_callback(callback);
trigger_callback(); // Triggers the callback.
}
}
```
C code:
```c
typedef void (*rust_callback)(int32_t);
rust_callback cb;
int32_t register_callback(rust_callback callback) {
cb = callback;
return 1;
}
void trigger_callback() {
cb(7); // Will call callback(7) in Rust.
}
```
In this example Rust's `main()` will call `trigger_callback()` in C,
which would, in turn, call back to `callback()` in Rust.
## Targeting callbacks to Rust objects
The former example showed how a global function can be called from C code.
However it is often desired that the callback is targeted to a special
Rust object. This could be the object that represents the wrapper for the
respective C object.
This can be achieved by passing a raw pointer to the object down to the
C library. The C library can then include the pointer to the Rust object in
the notification. This will allow the callback to unsafely access the
referenced Rust object.
Rust code:
```rust,no_run
#[repr(C)]
struct RustObject {
a: i32,
// Other members...
}
extern "C" fn callback(target: *mut RustObject, a: i32) {
println!("I'm called from C with value {0}", a);
unsafe {
// Update the value in RustObject with the value received from the callback:
(*target).a = a;
}
}
#[link(name = "extlib")]
extern {
fn register_callback(target: *mut RustObject,
cb: extern fn(*mut RustObject, i32)) -> i32;
fn trigger_callback();
}
fn main() {
// Create the object that will be referenced in the callback:
let mut rust_object = Box::new(RustObject { a: 5 });
unsafe {
register_callback(&mut *rust_object, callback);
trigger_callback();
}
}
```
C code:
```c
typedef void (*rust_callback)(void*, int32_t);
void* cb_target;
rust_callback cb;
int32_t register_callback(void* callback_target, rust_callback callback) {
cb_target = callback_target;
cb = callback;
return 1;
}
void trigger_callback() {
cb(cb_target, 7); // Will call callback(&rustObject, 7) in Rust.
}
```
## Asynchronous callbacks
In the previously given examples the callbacks are invoked as a direct reaction
to a function call to the external C library.
The control over the current thread is switched from Rust to C to Rust for the
execution of the callback, but in the end the callback is executed on the
same thread that called the function which triggered the callback.
Things get more complicated when the external library spawns its own threads
and invokes callbacks from there.
In these cases access to Rust data structures inside the callbacks is
especially unsafe and proper synchronization mechanisms must be used.
Besides classical synchronization mechanisms like mutexes, one possibility in
Rust is to use channels (in `std::sync::mpsc`) to forward data from the C
thread that invoked the callback into a Rust thread.
If an asynchronous callback targets a special object in the Rust address space
it is also absolutely necessary that no more callbacks are performed by the
C library after the respective Rust object gets destroyed.
This can be achieved by unregistering the callback in the object's
destructor and designing the library in a way that guarantees that no
callback will be performed after deregistration.
# Linking
The `link` attribute on `extern` blocks provides the basic building block for
instructing rustc how it will link to native libraries. There are two accepted
forms of the link attribute today:
* `#[link(name = "foo")]`
* `#[link(name = "foo", kind = "bar")]`
In both of these cases, `foo` is the name of the native library that we're
linking to, and in the second case `bar` is the type of native library that the
compiler is linking to. There are currently three known types of native
libraries:
* Dynamic - `#[link(name = "readline")]`
* Static - `#[link(name = "my_build_dependency", kind = "static")]`
* Frameworks - `#[link(name = "CoreFoundation", kind = "framework")]`
Note that frameworks are only available on macOS targets.
The different `kind` values are meant to differentiate how the native library
participates in linkage. From a linkage perspective, the Rust compiler creates
two flavors of artifacts: partial (rlib/staticlib) and final (dylib/binary).
Native dynamic library and framework dependencies are propagated to the final
artifact boundary, while static library dependencies are not propagated at
all, because the static libraries are integrated directly into the subsequent
artifact.
A few examples of how this model can be used are:
* A native build dependency. Sometimes some C/C++ glue is needed when writing
some Rust code, but distribution of the C/C++ code in a library format is
a burden. In this case, the code will be archived into `libfoo.a` and then the
Rust crate would declare a dependency via `#[link(name = "foo", kind =
"static")]`.
Regardless of the flavor of output for the crate, the native static library
will be included in the output, meaning that distribution of the native static
library is not necessary.
* A normal dynamic dependency. Common system libraries (like `readline`) are
available on a large number of systems, and often a static copy of these
libraries cannot be found. When this dependency is included in a Rust crate,
partial targets (like rlibs) will not link to the library, but when the rlib
is included in a final target (like a binary), the native library will be
linked in.
On macOS, frameworks behave with the same semantics as a dynamic library.
# Unsafe blocks
Some operations, like dereferencing raw pointers or calling functions that have been marked
unsafe are only allowed inside unsafe blocks. Unsafe blocks isolate unsafety and are a promise to
the compiler that the unsafety does not leak out of the block.
Unsafe functions, on the other hand, advertise it to the world. An unsafe function is written like
this:
```rust
unsafe fn kaboom(ptr: *const i32) -> i32 { *ptr }
```
This function can only be called from an `unsafe` block or another `unsafe` function.
# Accessing foreign globals
Foreign APIs often export a global variable which could do something like track
global state. In order to access these variables, you declare them in `extern`
blocks with the `static` keyword:
```rust,ignore
extern crate libc;
#[link(name = "readline")]
extern {
static rl_readline_version: libc::c_int;
}
fn main() {
println!("You have readline version {} installed.",
unsafe { rl_readline_version as i32 });
}
```
Alternatively, you may need to alter global state provided by a foreign
interface. To do this, statics can be declared with `mut` so we can mutate
them.
```rust,ignore
extern crate libc;
use std::ffi::CString;
use std::ptr;
#[link(name = "readline")]
extern {
static mut rl_prompt: *const libc::c_char;
}
fn main() {
let prompt = CString::new("[my-awesome-shell] $").unwrap();
unsafe {
rl_prompt = prompt.as_ptr();
println!("{:?}", rl_prompt);
rl_prompt = ptr::null();
}
}
```
Note that all interaction with a `static mut` is unsafe, both reading and
writing. Dealing with global mutable state requires a great deal of care.
# Foreign calling conventions
Most foreign code exposes a C ABI, and Rust uses the platform's C calling convention by default when
calling foreign functions. Some foreign functions, most notably the Windows API, use other calling
conventions. Rust provides a way to tell the compiler which convention to use:
```rust,ignore
extern crate libc;
#[cfg(all(target_os = "win32", target_arch = "x86"))]
#[link(name = "kernel32")]
#[allow(non_snake_case)]
extern "stdcall" {
fn SetEnvironmentVariableA(n: *const u8, v: *const u8) -> libc::c_int;
}
# fn main() { }
```
This applies to the entire `extern` block. The list of supported ABI constraints
are:
* `stdcall`
* `aapcs`
* `cdecl`
* `fastcall`
* `vectorcall`
This is currently hidden behind the `abi_vectorcall` gate and is subject to change.
* `Rust`
* `rust-intrinsic`
* `system`
* `C`
* `win64`
* `sysv64`
Most of the ABIs in this list are self-explanatory, but the `system` ABI may
seem a little odd. This constraint selects whatever the appropriate ABI is for
interoperating with the target's libraries. For example, on win32 with a x86
architecture, this means that the ABI used would be `stdcall`. On x86_64,
however, windows uses the `C` calling convention, so `C` would be used. This
means that in our previous example, we could have used `extern "system" { ... }`
to define a block for all windows systems, not only x86 ones.
# Interoperability with foreign code
Rust guarantees that the layout of a `struct` is compatible with the platform's
representation in C only if the `#[repr(C)]` attribute is applied to it.
`#[repr(C, packed)]` can be used to lay out struct members without padding.
`#[repr(C)]` can also be applied to an enum.
Rust's owned boxes (`Box<T>`) use non-nullable pointers as handles which point
to the contained object. However, they should not be manually created because
they are managed by internal allocators. References can safely be assumed to be
non-nullable pointers directly to the type. However, breaking the borrow
checking or mutability rules is not guaranteed to be safe, so prefer using raw
pointers (`*`) if that's needed because the compiler can't make as many
assumptions about them.
Vectors and strings share the same basic memory layout, and utilities are
available in the `vec` and `str` modules for working with C APIs. However,
strings are not terminated with `\0`. If you need a NUL-terminated string for
interoperability with C, you should use the `CString` type in the `std::ffi`
module.
The [`libc` crate on crates.io][libc] includes type aliases and function
definitions for the C standard library in the `libc` module, and Rust links
against `libc` and `libm` by default.
# Variadic functions
In C, functions can be 'variadic', meaning they accept a variable number of arguments. This can
be achieved in Rust by specifying `...` within the argument list of a foreign function declaration:
```rust,no_run
extern {
fn foo(x: i32, ...);
}
fn main() {
unsafe {
foo(10, 20, 30, 40, 50);
}
}
```
Normal Rust functions can *not* be variadic:
```rust,ignore
// This will not compile
fn foo(x: i32, ...) { }
```
# The "nullable pointer optimization"
Certain Rust types are defined to never be `null`. This includes references (`&T`,
`&mut T`), boxes (`Box<T>`), and function pointers (`extern "abi" fn()`). When
interfacing with C, pointers that might be `null` are often used, which would seem to
require some messy `transmute`s and/or unsafe code to handle conversions to/from Rust types.
However, the language provides a workaround.
As a special case, an `enum` is eligible for the "nullable pointer optimization" if it contains
exactly two variants, one of which contains no data and the other contains a field of one of the
non-nullable types listed above. This means no extra space is required for a discriminant; rather,
the empty variant is represented by putting a `null` value into the non-nullable field. This is
called an "optimization", but unlike other optimizations it is guaranteed to apply to eligible
types.
The most common type that takes advantage of the nullable pointer optimization is `Option<T>`,
where `None` corresponds to `null`. So `Option<extern "C" fn(c_int) -> c_int>` is a correct way
to represent a nullable function pointer using the C ABI (corresponding to the C type
`int (*)(int)`).
Here is a contrived example. Let's say some C library has a facility for registering a
callback, which gets called in certain situations. The callback is passed a function pointer
and an integer and it is supposed to run the function with the integer as a parameter. So
we have function pointers flying across the FFI boundary in both directions.
```rust,ignore
extern crate libc;
use libc::c_int;
# #[cfg(hidden)]
extern "C" {
/// Registers the callback.
fn register(cb: Option<extern "C" fn(Option<extern "C" fn(c_int) -> c_int>, c_int) -> c_int>);
}
# unsafe fn register(_: Option<extern "C" fn(Option<extern "C" fn(c_int) -> c_int>,
# c_int) -> c_int>)
# {}
/// This fairly useless function receives a function pointer and an integer
/// from C, and returns the result of calling the function with the integer.
/// In case no function is provided, it squares the integer by default.
extern "C" fn apply(process: Option<extern "C" fn(c_int) -> c_int>, int: c_int) -> c_int {
match process {
Some(f) => f(int),
None => int * int
}
}
fn main() {
unsafe {
register(Some(apply));
}
}
```
And the code on the C side looks like this:
```c
void register(void (*f)(void (*)(int), int)) {
...
}
```
No `transmute` required!
# Calling Rust code from C
You may wish to compile Rust code in a way so that it can be called from C. This is
fairly easy, but requires a few things:
```rust
#[no_mangle]
pub extern fn hello_rust() -> *const u8 {
"Hello, world!\0".as_ptr()
}
# fn main() {}
```
The `extern` makes this function adhere to the C calling convention, as
discussed above in "[Foreign Calling
Conventions](ffi.html#foreign-calling-conventions)". The `no_mangle`
attribute turns off Rust's name mangling, so that it is easier to link to.
# FFI and panics
Its important to be mindful of `panic!`s when working with FFI. A `panic!`
across an FFI boundary is undefined behavior. If youre writing code that may
panic, you should run it in a closure with [`catch_unwind`]:
```rust
use std::panic::catch_unwind;
#[no_mangle]
pub extern fn oh_no() -> i32 {
let result = catch_unwind(|| {
panic!("Oops!");
});
match result {
Ok(_) => 0,
Err(_) => 1,
}
}
fn main() {}
```
Please note that [`catch_unwind`] will only catch unwinding panics, not
those who abort the process. See the documentation of [`catch_unwind`]
for more information.
[`catch_unwind`]: ../../std/panic/fn.catch_unwind.html
# Representing opaque structs
Sometimes, a C library wants to provide a pointer to something, but not let you
know the internal details of the thing it wants. The simplest way is to use a
`void *` argument:
```c
void foo(void *arg);
void bar(void *arg);
```
We can represent this in Rust with the `c_void` type:
```rust,ignore
extern crate libc;
extern "C" {
pub fn foo(arg: *mut libc::c_void);
pub fn bar(arg: *mut libc::c_void);
}
# fn main() {}
```
This is a perfectly valid way of handling the situation. However, we can do a bit
better. To solve this, some C libraries will instead create a `struct`, where
the details and memory layout of the struct are private. This gives some amount
of type safety. These structures are called opaque. Heres an example, in C:
```c
struct Foo; /* Foo is a structure, but its contents are not part of the public interface */
struct Bar;
void foo(struct Foo *arg);
void bar(struct Bar *arg);
```
To do this in Rust, lets create our own opaque types:
```rust
#[repr(C)] pub struct Foo { private: [u8; 0] }
#[repr(C)] pub struct Bar { private: [u8; 0] }
extern "C" {
pub fn foo(arg: *mut Foo);
pub fn bar(arg: *mut Bar);
}
# fn main() {}
```
By including a private field and no constructor,
we create an opaque type that we cant instantiate outside of this module.
An empty array is both zero-size and compatible with `#[repr(C)]`.
But because our `Foo` and `Bar` types are
different, well get type safety between the two of them, so we cannot
accidentally pass a pointer to `Foo` to `bar()`.
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/ffi.html).

View File

@ -1,336 +1,10 @@
# Functions
Every Rust program has at least one function, the `main` function:
The first edition of the book is no longer distributed with Rust's documentation.
```rust
fn main() {
}
```
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
This is the simplest possible function declaration. As we mentioned before,
`fn` says this is a function, followed by the name, some parentheses because
this function takes no arguments, and then some curly braces to indicate the
body. Heres a function named `foo`:
```rust
fn foo() {
}
```
So, what about taking arguments? Heres a function that prints a number:
```rust
fn print_number(x: i32) {
println!("x is: {}", x);
}
```
Heres a complete program that uses `print_number`:
```rust
fn main() {
print_number(5);
}
fn print_number(x: i32) {
println!("x is: {}", x);
}
```
As you can see, function arguments work very similar to `let` declarations:
you add a type to the argument name, after a colon.
Heres a complete program that adds two numbers together and prints them:
```rust
fn main() {
print_sum(5, 6);
}
fn print_sum(x: i32, y: i32) {
println!("sum is: {}", x + y);
}
```
You separate arguments with a comma, both when you call the function, as well
as when you declare it.
Unlike `let`, you _must_ declare the types of function arguments. This does
not work:
```rust,ignore
fn print_sum(x, y) {
println!("sum is: {}", x + y);
}
```
You get this error:
```text
expected one of `!`, `:`, or `@`, found `)`
fn print_sum(x, y) {
```
This is a deliberate design decision. While full-program inference is possible,
languages which have it, like Haskell, often suggest that documenting your
types explicitly is a best-practice. We agree that forcing functions to declare
types while allowing for inference inside of function bodies is a wonderful
sweet spot between full inference and no inference.
What about returning a value? Heres a function that adds one to an integer:
```rust
fn add_one(x: i32) -> i32 {
x + 1
}
```
Rust functions return exactly one value, and you declare the type after an
arrow, which is a dash (`-`) followed by a greater-than sign (`>`). The last
line of a function determines what it returns. Youll note the lack of a
semicolon here. If we added it in:
```rust,ignore
fn add_one(x: i32) -> i32 {
x + 1;
}
```
We would get an error:
```text
error: not all control paths return a value
fn add_one(x: i32) -> i32 {
x + 1;
}
help: consider removing this semicolon:
x + 1;
^
```
This reveals two interesting things about Rust: it is an expression-based
language, and semicolons are different from semicolons in other curly brace
and semicolon-based languages. These two things are related.
## Expressions vs. Statements
Rust is primarily an expression-based language. There are only two kinds of
statements, and everything else is an expression.
So what's the difference? Expressions return a value, and statements do not.
Thats why we end up with not all control paths return a value here: the
statement `x + 1;` doesnt return a value. There are two kinds of statements in
Rust: declaration statements and expression statements. Everything else is
an expression. Lets talk about declaration statements first.
In some languages, variable bindings can be written as expressions, not
statements. Like Ruby:
```ruby
x = y = 5
```
In Rust, however, using `let` to introduce a binding is _not_ an expression. The
following will produce a compile-time error:
```rust,ignore
let x = (let y = 5); // Expected identifier, found keyword `let`.
```
The compiler is telling us here that it was expecting to see the beginning of
an expression, and a `let` can only begin a statement, not an expression.
Note that assigning to an already-bound variable (e.g. `y = 5`) is still an
expression, although its value is not particularly useful. Unlike other
languages where an assignment evaluates to the assigned value (e.g. `5` in the
previous example), in Rust the value of an assignment is an empty tuple `()`
because the assigned value can have [only one owner](ownership.html), and any
other returned value would be too surprising:
```rust
let mut y = 5;
let x = (y = 6); // `x` has the value `()`, not `6`.
```
The second kind of statement in Rust is the *expression statement*. Its
purpose is to turn any expression into a statement. In practical terms, Rust's
grammar expects statements to follow other statements. This means that you use
semicolons to separate expressions from each other. This means that Rust
looks a lot like most other languages that require you to use semicolons
at the end of every line, and you will see semicolons at the end of almost
every line of Rust code you see.
What is this exception that makes us say "almost"? You saw it already, in this
code:
```rust
fn add_one(x: i32) -> i32 {
x + 1
}
```
Our function claims to return an `i32`, but with a semicolon, it would return
`()` instead. Rust realizes this probably isnt what we want, and suggests
removing the semicolon in the error we saw before.
## Early returns
But what about early returns? Rust does have a keyword for that, `return`:
```rust
fn foo(x: i32) -> i32 {
return x;
// We never run this code!
x + 1
}
```
Using a `return` as the last line of a function works, but is considered poor
style:
```rust
fn foo(x: i32) -> i32 {
return x + 1;
}
```
The previous definition without `return` may look a bit strange if you havent
worked in an expression-based language before, but it becomes intuitive over
time.
## Diverging functions
Rust has some special syntax for diverging functions, which are functions that
do not return:
```rust
fn diverges() -> ! {
panic!("This function never returns!");
}
```
`panic!` is a macro, similar to `println!()` that weve already seen. Unlike
`println!()`, `panic!()` causes the current thread of execution to crash with
the given message. Because this function will cause a crash, it will never
return, and so it has the type `!`, which is read diverges.
If you add a main function that calls `diverges()` and run it, youll get
some output that looks like this:
```text
thread main panicked at This function never returns!, hello.rs:2
```
If you want more information, you can get a backtrace by setting the
`RUST_BACKTRACE` environment variable:
```text
$ RUST_BACKTRACE=1 ./diverges
thread 'main' panicked at 'This function never returns!', hello.rs:2
Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
stack backtrace:
hello::diverges
at ./hello.rs:2
hello::main
at ./hello.rs:6
```
If you want the complete backtrace and filenames:
```text
$ RUST_BACKTRACE=full ./diverges
thread 'main' panicked at 'This function never returns!', hello.rs:2
stack backtrace:
1: 0x7f402773a829 - sys::backtrace::write::h0942de78b6c02817K8r
2: 0x7f402773d7fc - panicking::on_panic::h3f23f9d0b5f4c91bu9w
3: 0x7f402773960e - rt::unwind::begin_unwind_inner::h2844b8c5e81e79558Bw
4: 0x7f4027738893 - rt::unwind::begin_unwind::h4375279447423903650
5: 0x7f4027738809 - diverges::h2266b4c4b850236beaa
6: 0x7f40277389e5 - main::h19bb1149c2f00ecfBaa
7: 0x7f402773f514 - rt::unwind::try::try_fn::h13186883479104382231
8: 0x7f402773d1d8 - __rust_try
9: 0x7f402773f201 - rt::lang_start::ha172a3ce74bb453aK5w
10: 0x7f4027738a19 - main
11: 0x7f402694ab44 - __libc_start_main
12: 0x7f40277386c8 - <unknown>
13: 0x0 - <unknown>
```
If you need to override an already set `RUST_BACKTRACE`,
in cases when you cannot just unset the variable,
then set it to `0` to avoid getting a backtrace.
Any other value (even no value at all) turns on backtrace.
```text
$ export RUST_BACKTRACE=1
...
$ RUST_BACKTRACE=0 ./diverges
thread 'main' panicked at 'This function never returns!', hello.rs:2
note: Run with `RUST_BACKTRACE=1` for a backtrace.
```
`RUST_BACKTRACE` also works with Cargos `run` command:
```text
$ RUST_BACKTRACE=full cargo run
Running `target/debug/diverges`
thread 'main' panicked at 'This function never returns!', hello.rs:2
stack backtrace:
1: 0x7f402773a829 - sys::backtrace::write::h0942de78b6c02817K8r
2: 0x7f402773d7fc - panicking::on_panic::h3f23f9d0b5f4c91bu9w
3: 0x7f402773960e - rt::unwind::begin_unwind_inner::h2844b8c5e81e79558Bw
4: 0x7f4027738893 - rt::unwind::begin_unwind::h4375279447423903650
5: 0x7f4027738809 - diverges::h2266b4c4b850236beaa
6: 0x7f40277389e5 - main::h19bb1149c2f00ecfBaa
7: 0x7f402773f514 - rt::unwind::try::try_fn::h13186883479104382231
8: 0x7f402773d1d8 - __rust_try
9: 0x7f402773f201 - rt::lang_start::ha172a3ce74bb453aK5w
10: 0x7f4027738a19 - main
11: 0x7f402694ab44 - __libc_start_main
12: 0x7f40277386c8 - <unknown>
13: 0x0 - <unknown>
```
A diverging function can be used as any type:
```rust,should_panic
# fn diverges() -> ! {
# panic!("This function never returns!");
# }
let x: i32 = diverges();
let x: String = diverges();
```
## Function pointers
We can also create variable bindings which point to functions:
```rust
let f: fn(i32) -> i32;
```
`f` is a variable binding which points to a function that takes an `i32` as
an argument and returns an `i32`. For example:
```rust
fn plus_one(i: i32) -> i32 {
i + 1
}
// Without type inference:
let f: fn(i32) -> i32 = plus_one;
// With type inference:
let f = plus_one;
```
We can then use `f` to call the function:
```rust
# fn plus_one(i: i32) -> i32 { i + 1 }
# let f = plus_one;
let six = f(5);
```
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/functions.html).

View File

@ -1,190 +1,10 @@
# Generics
Sometimes, when writing a function or data type, we may want it to work for
multiple types of arguments. In Rust, we can do this with generics.
Generics are called parametric polymorphism in type theory,
which means that they are types or functions that have multiple forms (poly
is multiple, morph is form) over a given parameter (parametric).
The first edition of the book is no longer distributed with Rust's documentation.
Anyway, enough type theory, lets check out some generic code. Rusts
standard library provides a type, `Option<T>`, thats generic:
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
```rust
enum Option<T> {
Some(T),
None,
}
```
The `<T>` part, which youve seen a few times before, indicates that this is
a generic data type. Inside the declaration of our `enum`, wherever we see a `T`,
we substitute that type for the same type used in the generic. Heres an
example of using `Option<T>`, with some extra type annotations:
```rust
let x: Option<i32> = Some(5);
```
In the type declaration, we say `Option<i32>`. Note how similar this looks to
`Option<T>`. So, in this particular `Option`, `T` has the value of `i32`. On
the right-hand side of the binding, we make a `Some(T)`, where `T` is `5`.
Since thats an `i32`, the two sides match, and Rust is happy. If they didnt
match, wed get an error:
```rust,ignore
let x: Option<f64> = Some(5);
// error: mismatched types: expected `core::option::Option<f64>`,
// found `core::option::Option<_>` (expected f64 but found integral variable)
```
That doesnt mean we cant make `Option<T>`s that hold an `f64`! They have
to match up:
```rust
let x: Option<i32> = Some(5);
let y: Option<f64> = Some(5.0f64);
```
This is just fine. One definition, multiple uses.
Generics dont have to only be generic over one type. Consider another type from Rusts standard library thats similar, `Result<T, E>`:
```rust
enum Result<T, E> {
Ok(T),
Err(E),
}
```
This type is generic over _two_ types: `T` and `E`. By the way, the capital letters
can be any letter youd like. We could define `Result<T, E>` as:
```rust
enum Result<A, Z> {
Ok(A),
Err(Z),
}
```
if we wanted to. Convention says that the first generic parameter should be
`T`, for type, and that we use `E` for error. Rust doesnt care, however.
The `Result<T, E>` type is intended to be used to return the result of a
computation, and to have the ability to return an error if it didnt work out.
## Generic functions
We can write functions that take generic types with a similar syntax:
```rust
fn takes_anything<T>(x: T) {
// Do something with `x`.
}
```
The syntax has two parts: the `<T>` says “this function is generic over one
type, `T`”, and the `x: T` says “x has the type `T`.”
Multiple arguments can have the same generic type:
```rust
fn takes_two_of_the_same_things<T>(x: T, y: T) {
// ...
}
```
We could write a version that takes multiple types:
```rust
fn takes_two_things<T, U>(x: T, y: U) {
// ...
}
```
## Generic structs
You can store a generic type in a `struct` as well:
```rust
struct Point<T> {
x: T,
y: T,
}
let int_origin = Point { x: 0, y: 0 };
let float_origin = Point { x: 0.0, y: 0.0 };
```
Similar to functions, the `<T>` is where we declare the generic parameters,
and we then use `x: T` in the type declaration, too.
When you want to add an implementation for the generic `struct`, you
declare the type parameter after the `impl`:
```rust
# struct Point<T> {
# x: T,
# y: T,
# }
#
impl<T> Point<T> {
fn swap(&mut self) {
std::mem::swap(&mut self.x, &mut self.y);
}
}
```
So far youve seen generics that take absolutely any type. These are useful in
many cases: youve already seen `Option<T>`, and later youll meet universal
container types like [`Vec<T>`][Vec]. On the other hand, often you want to
trade that flexibility for increased expressive power. Read about [trait
bounds][traits] to see why and how.
## Resolving ambiguities
Most of the time when generics are involved, the compiler can infer the
generic parameters automatically:
```rust
// v must be a Vec<T> but we don't know what T is yet
let mut v = Vec::new();
// v just got a bool value, so T must be bool!
v.push(true);
// Debug-print v
println!("{:?}", v);
```
Sometimes though, the compiler needs a little help. For example, had we
omitted the last line, we would get a compile error:
```rust,ignore
let v = Vec::new();
// ^^^^^^^^ cannot infer type for `T`
//
// note: type annotations or generic parameter binding required
println!("{:?}", v);
```
We can solve this using either a type annotation:
```rust
let v: Vec<bool> = Vec::new();
println!("{:?}", v);
```
or by binding the generic parameter `T` via the so-called
[turbofish][turbofish] `::<>` syntax:
```rust
let v = Vec::<bool>::new();
println!("{:?}", v);
```
The second approach is useful in situations where we dont want to bind the
result to a variable. It can also be used to bind generic parameters in
functions or methods. See [Iterators § Consumers](iterators.html#consumers)
for an example.
[traits]: traits.html
[Vec]: ../../std/vec/struct.Vec.html
[turbofish]: ../../std/iter/trait.Iterator.html#method.collect
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/generics.html).

View File

@ -1,550 +1,10 @@
# Getting Started
This first chapter of the book will get us going with Rust and its tooling.
First, well install Rust. Then, the classic Hello World program. Finally,
well talk about Cargo, Rusts build system and package manager.
The first edition of the book is no longer distributed with Rust's documentation.
Well be showing off a number of commands using a terminal, and those lines all
start with `$`. You don't need to type in the `$`s, they are there to indicate
the start of each command. Well see many tutorials and examples around the web
that follow this convention: `$` for commands run as our regular user, and `#`
for commands we should be running as an administrator.
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
# Installing Rust
The first step to using Rust is to install it. Generally speaking, youll need
an Internet connection to run the commands in this section, as well be
downloading Rust from the Internet.
The Rust compiler runs on, and compiles to, a great number of platforms, but is
best supported on Linux, Mac, and Windows, on the x86 and x86-64 CPU
architecture. There are official builds of the Rust compiler and standard
library for these platforms and more. [For full details on Rust platform support
see the website][platform-support].
[platform-support]: https://forge.rust-lang.org/platform-support.html
## Installing Rust
All you need to do on Unix systems like Linux and macOS is open a
terminal and type this:
```bash
$ curl https://sh.rustup.rs -sSf | sh
```
It will download a script, and start the installation. If everything
goes well, youll see this appear:
```text
Rust is installed now. Great!
```
Installing on Windows is nearly as easy: download and run
[rustup-init.exe]. It will start the installation in a console and
present the above message on success.
For other installation options and information, visit the [install]
page of the Rust website.
[rustup-init.exe]: https://win.rustup.rs
[install]: https://www.rust-lang.org/install.html
## Uninstalling
Uninstalling Rust is as easy as installing it:
```bash
$ rustup self uninstall
```
## Troubleshooting
If we've got Rust installed, we can open up a shell, and type this:
```bash
$ rustc --version
```
You should see the version number, commit hash, and commit date.
If you do, Rust has been installed successfully! Congrats!
If you don't, that probably means that the `PATH` environment variable
doesn't include Cargo's binary directory, `~/.cargo/bin` on Unix, or
`%USERPROFILE%\.cargo\bin` on Windows. This is the directory where
Rust development tools live, and most Rust developers keep it in their
`PATH` environment variable, which makes it possible to run `rustc` on
the command line. Due to differences in operating systems, command
shells, and bugs in installation, you may need to restart your shell,
log out of the system, or configure `PATH` manually as appropriate for
your operating environment.
Rust does not do its own linking, and so youll need to have a linker
installed. Doing so will depend on your specific system. For
Linux-based systems, Rust will attempt to call `cc` for linking. On
`windows-msvc` (Rust built on Windows with Microsoft Visual Studio),
this depends on having [Microsoft Visual C++ Build Tools][msvbt]
installed. These do not need to be in `%PATH%` as `rustc` will find
them automatically. In general, if you have your linker in a
non-traditional location you can call `rustc
linker=/path/to/cc`, where `/path/to/cc` should point to your linker path.
[msvbt]: http://landinghub.visualstudio.com/visual-cpp-build-tools
If you are still stuck, there are a number of places where we can get
help. The easiest is
[the #rust-beginners IRC channel on irc.mozilla.org][irc-beginners]
and for general discussion
[the #rust IRC channel on irc.mozilla.org][irc], which we
can access through [Mibbit][mibbit]. Then we'll be chatting with other
Rustaceans (a silly nickname we call ourselves) who can help us out. Other great
resources include [the users forum][users] and [Stack Overflow][stackoverflow].
[irc-beginners]: irc://irc.mozilla.org/#rust-beginners
[irc]: irc://irc.mozilla.org/#rust
[mibbit]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust-beginners,%23rust
[users]: https://users.rust-lang.org/
[stackoverflow]: http://stackoverflow.com/questions/tagged/rust
This installer also installs a copy of the documentation locally, so we can
read it offline. It's only a `rustup doc` away!
# Hello, world!
Now that you have Rust installed, we'll help you write your first Rust program.
It's traditional when learning a new language to write a little program to
print the text “Hello, world!” to the screen, and in this section, we'll follow
that tradition.
The nice thing about starting with such a simple program is that you can
quickly verify that your compiler is installed, and that it's working properly.
Printing information to the screen is also a pretty common thing to do, so
practicing it early on is good.
> Note: This book assumes basic familiarity with the command line. Rust itself
> makes no specific demands about your editing, tooling, or where your code
> lives, so if you prefer an IDE to the command line, that's an option. You may
> want to check out [SolidOak], which was built specifically with Rust in mind.
> There are a number of extensions in development by the community, and the
> Rust team ships plugins for [various editors]. Configuring your editor or
> IDE is out of the scope of this tutorial, so check the documentation for your
> specific setup.
[SolidOak]: https://github.com/oakes/SolidOak
[various editors]: https://github.com/rust-lang/rust/blob/master/src/etc/CONFIGS.md
## Creating a Project File
First, make a file to put your Rust code in. Rust doesn't care where your code
lives, but for this book, I suggest making a *projects* directory in your home
directory, and keeping all your projects there. Open a terminal and enter the
following commands to make a directory for this particular project:
```bash
$ mkdir ~/projects
$ cd ~/projects
$ mkdir hello_world
$ cd hello_world
```
> Note: If youre on Windows and not using PowerShell, the `~` may not work.
> Consult the documentation for your shell for more details.
## Writing and Running a Rust Program
We need to create a source file for our Rust program. Rust files always end
in a *.rs* extension. If you are using more than one word in your filename,
use an underscore to separate them; for example, you would use
*my_program.rs* rather than *myprogram.rs*.
Now, make a new file and call it *main.rs*. Open the file and type
the following code:
```rust
fn main() {
println!("Hello, world!");
}
```
Save the file, and go back to your terminal window. On Linux or macOS, enter the
following commands:
```bash
$ rustc main.rs
$ ./main
Hello, world!
```
In Windows, replace `main` with `main.exe`. Regardless of your operating
system, you should see the string `Hello, world!` print to the terminal. If you
did, then congratulations! You've officially written a Rust program. That makes
you a Rust programmer! Welcome.
## Anatomy of a Rust Program
Now, lets go over what just happened in your "Hello, world!" program in
detail. Here's the first piece of the puzzle:
```rust
fn main() {
}
```
These lines define a *function* in Rust. The `main` function is special: it's
the beginning of every Rust program. The first line says, “Im declaring a
function named `main` that takes no arguments and returns nothing.” If there
were arguments, they would go inside the parentheses (`(` and `)`), and because
we arent returning anything from this function, we can omit the return type
entirely.
Also note that the function body is wrapped in curly braces (`{` and `}`). Rust
requires these around all function bodies. It's considered good style to put
the opening curly brace on the same line as the function declaration, with one
space in between.
Inside the `main()` function:
```rust
println!("Hello, world!");
```
This line does all of the work in this little program: it prints text to the
screen. There are a number of details that are important here. The first is
that its indented with four spaces, not tabs.
The second important part is the `println!()` line. This is calling a Rust
*[macro]*, which is how metaprogramming is done in Rust. If it were calling a
function instead, it would look like this: `println()` (without the !). We'll
discuss Rust macros in more detail later, but for now you only need to
know that when you see a `!` that means that youre calling a macro instead of
a normal function.
[macro]: macros.html
Next is `"Hello, world!"` which is a *string*. Strings are a surprisingly
complicated topic in a systems programming language, and this is a *[statically
allocated]* string. We pass this string as an argument to `println!`, which
prints the string to the screen. Easy enough!
[statically allocated]: the-stack-and-the-heap.html
The line ends with a semicolon (`;`). Rust is an *[expression-oriented
language]*, which means that most things are expressions, rather than
statements. The `;` indicates that this expression is over, and the next one is
ready to begin. Most lines of Rust code end with a `;`.
[expression-oriented language]: glossary.html#expression-oriented-language
## Compiling and Running Are Separate Steps
In "Writing and Running a Rust Program", we showed you how to run a newly
created program. We'll break that process down and examine each step now.
Before running a Rust program, you have to compile it. You can use the Rust
compiler by entering the `rustc` command and passing it the name of your source
file, like this:
```bash
$ rustc main.rs
```
If you come from a C or C++ background, you'll notice that this is similar to
`gcc` or `clang`. After compiling successfully, Rust should output a binary
executable, which you can see on Linux or macOS by entering the `ls` command in
your shell as follows:
```bash
$ ls
main main.rs
```
On Windows, you'd enter:
```bash
$ dir
main.exe
main.rs
```
This shows we have two files: the source code, with an `.rs` extension, and the
executable (`main.exe` on Windows, `main` everywhere else). All that's left to
do from here is run the `main` or `main.exe` file, like this:
```bash
$ ./main # or .\main.exe on Windows
```
If *main.rs* were your "Hello, world!" program, this would print `Hello,
world!` to your terminal.
If you come from a dynamic language like Ruby, Python, or JavaScript, you may
not be used to compiling and running a program being separate steps. Rust is an
*ahead-of-time compiled* language, which means that you can compile a program,
give it to someone else, and they can run it even without Rust installed. If
you give someone a `.rb` or `.py` or `.js` file, on the other hand, they need
to have a Ruby, Python, or JavaScript implementation installed (respectively),
but you only need one command to both compile and run your program. Everything
is a tradeoff in language design.
Just compiling with `rustc` is fine for simple programs, but as your project
grows, you'll want to be able to manage all of the options your project has,
and make it easy to share your code with other people and projects. Next, I'll
introduce you to a tool called Cargo, which will help you write real-world Rust
programs.
# Hello, Cargo!
Cargo is Rusts build system and package manager, and Rustaceans use Cargo to
manage their Rust projects. Cargo manages three things: building your code,
downloading the libraries your code depends on, and building those libraries.
We call libraries your code needs dependencies since your code depends on
them.
The simplest Rust programs dont have any dependencies, so right now, you'd
only use the first part of its functionality. As you write more complex Rust
programs, youll want to add dependencies, and if you start off using Cargo,
that will be a lot easier to do.
As the vast, vast majority of Rust projects use Cargo, we will assume that
youre using it for the rest of the book. Cargo comes installed with Rust
itself, if you used the official installers. If you installed Rust through some
other means, you can check if you have Cargo installed by typing:
```bash
$ cargo --version
```
Into a terminal. If you see a version number, great! If you see an error like
`command not found`, then you should look at the documentation for the system
in which you installed Rust, to determine if Cargo is separate.
## Converting to Cargo
Lets convert the Hello World program to Cargo. To Cargo-fy a project, you need
to do three things:
1. Put your source file in the right directory.
2. Get rid of the old executable (`main.exe` on Windows, `main` everywhere
else).
3. Make a Cargo configuration file.
Let's get started!
### Creating a Source Directory and Removing the Old Executable
First, go back to your terminal, move to your *hello_world* directory, and
enter the following commands:
```bash
$ mkdir src
$ mv main.rs src/main.rs # or 'move main.rs src/main.rs' on Windows
$ rm main # or 'del main.exe' on Windows
```
Cargo expects your source files to live inside a *src* directory, so do that
first. This leaves the top-level project directory (in this case,
*hello_world*) for READMEs, license information, and anything else not related
to your code. In this way, using Cargo helps you keep your projects nice and
tidy. There's a place for everything, and everything is in its place.
Now, move *main.rs* into the *src* directory, and delete the compiled file you
created with `rustc`. As usual, replace `main` with `main.exe` if you're on
Windows.
This example retains `main.rs` as the source filename because it's creating an
executable. If you wanted to make a library instead, you'd name the file
`lib.rs`. This convention is used by Cargo to successfully compile your
projects, but it can be overridden if you wish.
### Creating a Configuration File
Next, create a new file inside your *hello_world* directory, and call it
`Cargo.toml`.
Make sure to capitalize the `C` in `Cargo.toml`, or Cargo won't know what to do
with the configuration file.
This file is in the *[TOML]* (Tom's Obvious, Minimal Language) format. TOML is
similar to INI, but has some extra goodies, and is used as Cargos
configuration format.
[TOML]: https://github.com/toml-lang/toml
Inside this file, type the following information:
```toml
[package]
name = "hello_world"
version = "0.0.1"
authors = [ "Your name <you@example.com>" ]
```
The first line, `[package]`, indicates that the following statements are
configuring a package. As we add more information to this file, well add other
sections, but for now, we only have the package configuration.
The other three lines set the three bits of configuration that Cargo needs to
know to compile your program: its name, what version it is, and who wrote it.
Once you've added this information to the *Cargo.toml* file, save it to finish
creating the configuration file.
## Building and Running a Cargo Project
With your *Cargo.toml* file in place in your project's root directory, you
should be ready to build and run your Hello World program! To do so, enter the
following commands:
```bash
$ cargo build
Compiling hello_world v0.0.1 (file:///home/yourname/projects/hello_world)
$ ./target/debug/hello_world
Hello, world!
```
Bam! If all goes well, `Hello, world!` should print to the terminal once more.
You just built a project with `cargo build` and ran it with
`./target/debug/hello_world`, but you can actually do both in one step with
`cargo run` as follows:
```bash
$ cargo run
Running `target/debug/hello_world`
Hello, world!
```
The `run` command comes in handy when you need to rapidly iterate on a
project.
Notice that this example didnt re-build the project. Cargo figured out that
the file hasnt changed, and so it just ran the binary. If you'd modified your
source code, Cargo would have rebuilt the project before running it, and you
would have seen something like this:
```bash
$ cargo run
Compiling hello_world v0.0.1 (file:///home/yourname/projects/hello_world)
Running `target/debug/hello_world`
Hello, world!
```
Cargo checks to see if any of your projects files have been modified, and only
rebuilds your project if theyve changed since the last time you built it.
With simple projects, Cargo doesn't bring a whole lot over just using `rustc`,
but it will become useful in the future. This is especially true when you start
using crates; these are synonymous with a library or package in other
programming languages. For complex projects composed of multiple crates, its
much easier to let Cargo coordinate the build. Using Cargo, you can run `cargo
build`, and it should work the right way.
### Building for Release
When your project is ready for release, you can use `cargo build
--release` to compile your project with optimizations. These optimizations make
your Rust code run faster, but turning them on makes your program take longer
to compile. This is why there are two different profiles, one for development,
and one for building the final program youll give to a user.
### What Is That `Cargo.lock`?
Running `cargo build` also causes Cargo to create a new file called
*Cargo.lock*, which looks like this:
```toml
[root]
name = "hello_world"
version = "0.0.1"
```
Cargo uses the *Cargo.lock* file to keep track of dependencies in your
application. This is the Hello World project's *Cargo.lock* file. This project
doesn't have dependencies, so the file is a bit sparse. Realistically, you
won't ever need to touch this file yourself; just let Cargo handle it.
Thats it! If you've been following along, you should have successfully built
`hello_world` with Cargo.
Even though the project is simple, it now uses much of the real tooling youll
use for the rest of your Rust career. In fact, you can expect to start
virtually all Rust projects with some variation on the following commands:
```bash
$ git clone someurl.com/foo
$ cd foo
$ cargo build
```
## Making A New Cargo Project the Easy Way
You dont have to go through that previous process every time you want to start
a new project! Cargo can quickly make a bare-bones project directory that you
can start developing in right away.
To start a new project with Cargo, enter `cargo new` at the command line:
```bash
$ cargo new hello_world --bin
```
This command passes `--bin` because the goal is to get straight to making an
executable application, as opposed to a library. Executables are often called
*binaries* (as in `/usr/bin`, if youre on a Unix system).
Cargo has generated two files and one directory for us: a `Cargo.toml` and a
*src* directory with a *main.rs* file inside. These should look familiar,
theyre exactly what we created by hand, above.
This output is all you need to get started. First, open `Cargo.toml`. It should
look something like this:
```toml
[package]
name = "hello_world"
version = "0.1.0"
authors = ["Your Name <you@example.com>"]
[dependencies]
```
Do not worry about the `[dependencies]` line, we will come back to it later.
Cargo has populated *Cargo.toml* with reasonable defaults based on the arguments
you gave it and your `git` global configuration. You may notice that Cargo has
also initialized the `hello_world` directory as a `git` repository.
Heres what should be in `src/main.rs`:
```rust
fn main() {
println!("Hello, world!");
}
```
Cargo has generated a "Hello World!" for you, and youre ready to start coding!
> Note: If you want to look at Cargo in more detail, check out the official [Cargo
guide], which covers all of its features.
[Cargo guide]: http://doc.crates.io/guide.html
# Closing Thoughts
This chapter covered the basics that will serve you well through the rest of
this book, and the rest of your time with Rust. Now that youve got the tools
down, we'll cover more about the Rust language itself.
You have two options: Dive into a project with [Tutorial: Guessing Game][guessinggame], or
start from the bottom and work your way up with [Syntax and
Semantics][syntax]. More experienced systems programmers will probably prefer
Tutorial: Guessing Game, while those from dynamic backgrounds may enjoy either. Different
people learn differently! Choose whatevers right for you.
[guessinggame]: guessing-game.html
[syntax]: syntax-and-semantics.html
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/getting-started.html).

View File

@ -1,85 +1,10 @@
# Glossary
Not every Rustacean has a background in systems programming, nor in computer
science, so we've added explanations of terms that might be unfamiliar.
The first edition of the book is no longer distributed with Rust's documentation.
### Abstract Syntax Tree
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
When a compiler is compiling your program, it does a number of different things.
One of the things that it does is turn the text of your program into an
abstract syntax tree, or AST. This tree is a representation of the structure
of your program. For example, `2 + 3` can be turned into a tree:
```text
+
/ \
2 3
```
And `2 + (3 * 4)` would look like this:
```text
+
/ \
2 *
/ \
3 4
```
### Arity
Arity refers to the number of arguments a function or operation takes.
```rust
let x = (2, 3);
let y = (4, 6);
let z = (8, 2, 6);
```
In the example above `x` and `y` have arity 2. `z` has arity 3.
### Bounds
Bounds are constraints on a type or [trait][traits]. For example, if a bound
is placed on the argument a function takes, types passed to that function
must abide by that constraint.
[traits]: traits.html
### Combinators
Combinators are higher-order functions that apply only functions and
earlier defined combinators to provide a result from its arguments.
They can be used to manage control flow in a modular fashion.
### DST (Dynamically Sized Type)
A type without a statically known size or alignment. ([more info][link])
[link]: ../../nomicon/exotic-sizes.html#dynamically-sized-types-dsts
### Expression
In computer programming, an expression is a combination of values, constants,
variables, operators and functions that evaluate to a single value. For example,
`2 + (3 * 4)` is an expression that returns the value 14. It is worth noting
that expressions can have side-effects. For example, a function included in an
expression might perform actions other than simply returning a value.
### Expression-Oriented Language
In early programming languages, [expressions][expression] and
[statements][statement] were two separate syntactic categories: expressions had
a value and statements did things. However, later languages blurred this
distinction, allowing expressions to do things and statements to have a value.
In an expression-oriented language, (nearly) every statement is an expression
and therefore returns a value. Consequently, these expression statements can
themselves form part of larger expressions.
[expression]: glossary.html#expression
[statement]: glossary.html#statement
### Statement
In computer programming, a statement is the smallest standalone element of a
programming language that commands a computer to perform an action.
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/glossary.html).

File diff suppressed because it is too large Load Diff

View File

@ -1,84 +1,10 @@
# if let
`if let` permits [patterns][patterns] matching within the condition of an [if][if] statement.
This allows us to reduce the overhead of certain kinds of [pattern][patterns] matches
and express them in a more convenient way.
The first edition of the book is no longer distributed with Rust's documentation.
For example, lets say we have some sort of `Option<T>`. We want to call a function
on it if its `Some<T>`, but do nothing if its `None`. That looks like this:
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
```rust
# let option = Some(5);
# fn foo(x: i32) { }
match option {
Some(x) => { foo(x) },
None => {},
}
```
We dont have to use `match` here, for example, we could use `if`:
```rust
# let option = Some(5);
# fn foo(x: i32) { }
if option.is_some() {
let x = option.unwrap();
foo(x);
}
```
Neither of these options is particularly appealing. We can use `if let` to
do the same thing in a nicer way:
```rust
# let option = Some(5);
# fn foo(x: i32) { }
if let Some(x) = option {
foo(x);
}
```
If a [pattern][patterns] matches successfully, it binds any appropriate parts of
the value to the identifiers in the pattern, then evaluates the expression. If
the pattern doesnt match, nothing happens.
If you want to do something else when the pattern does not match, you can
use `else`:
```rust
# let option = Some(5);
# fn foo(x: i32) { }
# fn bar() { }
if let Some(x) = option {
foo(x);
} else {
bar();
}
```
## `while let`
In a similar fashion, `while let` can be used when you want to conditionally
loop as long as a value matches a certain pattern. It turns code like this:
```rust
let mut v = vec![1, 3, 5, 7, 11];
loop {
match v.pop() {
Some(x) => println!("{}", x),
None => break,
}
}
```
Into code like this:
```rust
let mut v = vec![1, 3, 5, 7, 11];
while let Some(x) = v.pop() {
println!("{}", x);
}
```
[patterns]: patterns.html
[if]: if.html
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/if-let.html).

View File

@ -1,73 +1,10 @@
# if
Rusts take on `if` is not particularly complex, but its much more like the
`if` youll find in a dynamically typed language than in a more traditional
systems language. So lets talk about it, to make sure you grasp the nuances.
The first edition of the book is no longer distributed with Rust's documentation.
`if` is a specific form of a more general concept, the branch, whose name comes
from a branch in a tree: a decision point, where depending on a choice,
multiple paths can be taken.
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
In the case of `if`, there is one choice that leads down two paths:
```rust
let x = 5;
if x == 5 {
println!("x is five!");
}
```
If we changed the value of `x` to something else, this line would not print.
More specifically, if the expression after the `if` evaluates to `true`, then
the block is executed. If its `false`, then it is not.
If you want something to happen in the `false` case, use an `else`:
```rust
let x = 5;
if x == 5 {
println!("x is five!");
} else {
println!("x is not five :(");
}
```
If there is more than one case, use an `else if`:
```rust
let x = 5;
if x == 5 {
println!("x is five!");
} else if x == 6 {
println!("x is six!");
} else {
println!("x is not five or six :(");
}
```
This is all pretty standard. However, you can also do this:
```rust
let x = 5;
let y = if x == 5 {
10
} else {
15
}; // y: i32
```
Which we can (and probably should) write like this:
```rust
let x = 5;
let y = if x == 5 { 10 } else { 15 }; // y: i32
```
This works because `if` is an expression. The value of the expression is the
value of the last expression in whichever branch was chosen. An `if` without an
`else` always results in `()` as the value.
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/if.html).

View File

@ -1,343 +1,10 @@
# Iterators
Let's talk about loops.
The first edition of the book is no longer distributed with Rust's documentation.
Remember Rust's `for` loop? Here's an example:
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
```rust
for x in 0..10 {
println!("{}", x);
}
```
Now that you know more Rust, we can talk in detail about how this works.
Ranges (the `0..10`) are 'iterators'. An iterator is something that we can
call the `.next()` method on repeatedly, and it gives us a sequence of things.
A range with two dots like `0..10` is inclusive on the left (so it
starts at 0) and exclusive on the right (so it ends at 9). A mathematician
would write "[0, 10)".
Like this:
```rust
let mut range = 0..10;
loop {
match range.next() {
Some(x) => {
println!("{}", x);
},
None => { break }
}
}
```
We make a mutable binding to the range, which is our iterator. We then `loop`,
with an inner `match`. This `match` is used on the result of `range.next()`,
which gives us a reference to the next value of the iterator. `next` returns an
`Option<i32>`, in this case, which will be `Some(i32)` when we have a value and
`None` once we run out. If we get `Some(i32)`, we print it out, and if we get
`None`, we `break` out of the loop.
This code sample is basically the same as our `for` loop version. The `for`
loop is a handy way to write this `loop`/`match`/`break` construct.
`for` loops aren't the only thing that uses iterators, however. Writing your
own iterator involves implementing the `Iterator` trait. While doing that is
outside of the scope of this guide, Rust provides a number of useful iterators
to accomplish various tasks. But first, a few notes about limitations of ranges.
Ranges are very primitive, and we often can use better alternatives. Consider the
following Rust anti-pattern: using ranges to emulate a C-style `for` loop. Lets
suppose you needed to iterate over the contents of a vector. You may be tempted
to write this:
```rust
let nums = vec![1, 2, 3];
for i in 0..nums.len() {
println!("{}", nums[i]);
}
```
This is strictly worse than using an actual iterator. You can iterate over vectors
directly, so write this:
```rust
let nums = vec![1, 2, 3];
for num in &nums {
println!("{}", num);
}
```
There are two reasons for this. First, this more directly expresses what we
mean. We iterate through the entire vector, rather than iterating through
indexes, and then indexing the vector. Second, this version is more efficient:
the first version will have extra bounds checking because it used indexing,
`nums[i]`. But since we yield a reference to each element of the vector in turn
with the iterator, there's no bounds checking in the second example. This is
very common with iterators: we can ignore unnecessary bounds checks, but still
know that we're safe.
There's another detail here that's not 100% clear because of how `println!`
works. `num` is actually of type `&i32`. That is, it's a reference to an `i32`,
not an `i32` itself. `println!` handles the dereferencing for us, so we don't
see it. This code works fine too:
```rust
let nums = vec![1, 2, 3];
for num in &nums {
println!("{}", *num);
}
```
Now we're explicitly dereferencing `num`. Why does `&nums` give us
references? Firstly, because we explicitly asked it to with
`&`. Secondly, if it gave us the data itself, we would have to be its
owner, which would involve making a copy of the data and giving us the
copy. With references, we're only borrowing a reference to the data,
and so it's only passing a reference, without needing to do the move.
So, now that we've established that ranges are often not what you want, let's
talk about what you do want instead.
There are three broad classes of things that are relevant here: iterators,
*iterator adaptors*, and *consumers*. Here's some definitions:
* *iterators* give you a sequence of values.
* *iterator adaptors* operate on an iterator, producing a new iterator with a
different output sequence.
* *consumers* operate on an iterator, producing some final set of values.
Let's talk about consumers first, since you've already seen an iterator, ranges.
## Consumers
A *consumer* operates on an iterator, returning some kind of value or values.
The most common consumer is `collect()`. This code doesn't quite compile,
but it shows the intention:
```rust,ignore
let one_to_one_hundred = (1..101).collect();
```
As you can see, we call `collect()` on our iterator. `collect()` takes
as many values as the iterator will give it, and returns a collection
of the results. So why won't this compile? Rust can't determine what
type of things you want to collect, and so you need to let it know.
Here's the version that does compile:
```rust
let one_to_one_hundred = (1..101).collect::<Vec<i32>>();
```
If you remember, the [`::<>` syntax](generics.html#resolving-ambiguities)
allows us to give a type hint that tells the compiler we want a vector of
integers. You don't always need to use the whole type, though. Using a `_`
will let you provide a partial hint:
```rust
let one_to_one_hundred = (1..101).collect::<Vec<_>>();
```
This says "Collect into a `Vec<T>`, please, but infer what the `T` is for me."
`_` is sometimes called a "type placeholder" for this reason.
`collect()` is the most common consumer, but there are others too. `find()`
is one:
```rust
let greater_than_forty_two = (0..100)
.find(|x| *x > 42);
match greater_than_forty_two {
Some(_) => println!("Found a match!"),
None => println!("No match found :("),
}
```
`find` takes a closure, and works on a reference to each element of an
iterator. This closure returns `true` if the element is the element we're
looking for, and `false` otherwise. `find` returns the first element satisfying
the specified predicate. Because we might not find a matching element, `find`
returns an `Option` rather than the element itself.
Another important consumer is `fold`. Here's what it looks like:
```rust
let sum = (1..4).fold(0, |sum, x| sum + x);
```
`fold()` is a consumer that looks like this:
`fold(base, |accumulator, element| ...)`. It takes two arguments: the first
is an element called the *base*. The second is a closure that itself takes two
arguments: the first is called the *accumulator*, and the second is an
*element*. Upon each iteration, the closure is called, and the result is the
value of the accumulator on the next iteration. On the first iteration, the
base is assigned the value of the accumulator.
Okay, that's a bit confusing. Let's examine the values of all of these things
in this iterator:
| base | accumulator | element | closure result |
|------|-------------|---------|----------------|
| 0 | 0 | 1 | 1 |
| 0 | 1 | 2 | 3 |
| 0 | 3 | 3 | 6 |
We called `fold()` with these arguments:
```rust
# (1..4)
.fold(0, |sum, x| sum + x);
```
So, `0` is our base, `sum` is our accumulator, and `x` is our element. On the
first iteration, we set `sum` to `0`, and `x` is the first element of `nums`,
`1`. We then add `sum` and `x`, which gives us `0 + 1 = 1`. On the second
iteration, that value becomes our accumulator, `sum`, and the element is
the second element of the array, `2`. `1 + 2 = 3`, and so that becomes
the value of the accumulator for the last iteration. On that iteration,
`x` is the last element, `3`, and `3 + 3 = 6`, which is our final
result for our sum. `1 + 2 + 3 = 6`, and that's the result we got.
Whew. `fold` can be a bit strange the first few times you see it, but once it
clicks, you can use it all over the place. Any time you have a list of things,
and you want a single result, `fold` is appropriate.
Consumers are important due to one additional property of iterators we haven't
talked about yet: laziness. Let's talk some more about iterators, and you'll
see why consumers matter.
## Iterators
As we've said before, an iterator is something that we can call the
`.next()` method on repeatedly, and it gives us a sequence of things.
Because you need to call the method, this means that iterators
can be *lazy* and not generate all of the values upfront. This code,
for example, does not actually generate the numbers `1-99`, instead
creating a value that merely represents the sequence:
```rust
let nums = 1..100;
```
Since we didn't do anything with the range, it didn't generate the sequence.
Let's add the consumer:
```rust
let nums = (1..100).collect::<Vec<i32>>();
```
Now, `collect()` will require that the range gives it some numbers, and so
it will do the work of generating the sequence.
Ranges are one of two basic iterators that you'll see. The other is `iter()`.
`iter()` can turn a vector into a simple iterator that gives you each element
in turn:
```rust
let nums = vec![1, 2, 3];
for num in nums.iter() {
println!("{}", num);
}
```
These two basic iterators should serve you well. There are some more
advanced iterators, including ones that are infinite.
That's enough about iterators. Iterator adaptors are the last concept
we need to talk about with regards to iterators. Let's get to it!
## Iterator adaptors
*Iterator adaptors* take an iterator and modify it somehow, producing
a new iterator. The simplest one is called `map`:
```rust,ignore
(1..100).map(|x| x + 1);
```
`map` is called upon another iterator, and produces a new iterator where each
element reference has the closure it's been given as an argument called on it.
So this would give us the numbers from `2-100`. Well, almost! If you
compile the example, you'll get a warning:
```text
warning: unused result which must be used: iterator adaptors are lazy and
do nothing unless consumed, #[warn(unused_must_use)] on by default
(1..100).map(|x| x + 1);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
Laziness strikes again! That closure will never execute. This example
doesn't print any numbers:
```rust,ignore
(1..100).map(|x| println!("{}", x));
```
If you are trying to execute a closure on an iterator for its side effects,
use `for` instead.
There are tons of interesting iterator adaptors. `take(n)` will return an
iterator over the next `n` elements of the original iterator. Let's try it out
with an infinite iterator:
```rust
for i in (1..).take(5) {
println!("{}", i);
}
```
This will print
```text
1
2
3
4
5
```
`filter()` is an adapter that takes a closure as an argument. This closure
returns `true` or `false`. The new iterator `filter()` produces
only the elements that the closure returns `true` for:
```rust
for i in (1..100).filter(|&x| x % 2 == 0) {
println!("{}", i);
}
```
This will print all of the even numbers between one and a hundred.
(Note that, unlike `map`, the closure passed to `filter` is passed a reference
to the element instead of the element itself. The filter predicate here uses
the `&x` pattern to extract the integer. The filter closure is passed a
reference because it returns `true` or `false` instead of the element,
so the `filter` implementation must retain ownership to put the elements
into the newly constructed iterator.)
You can chain all three things together: start with an iterator, adapt it
a few times, and then consume the result. Check it out:
```rust
(1..)
.filter(|&x| x % 2 == 0)
.filter(|&x| x % 3 == 0)
.take(5)
.collect::<Vec<i32>>();
```
This will give you a vector containing `6`, `12`, `18`, `24`, and `30`.
This is just a small taste of what iterators, iterator adaptors, and consumers
can help you with. There are a number of really useful iterators, and you can
write your own as well. Iterators provide a safe, efficient way to manipulate
all kinds of lists. They're a little unusual at first, but if you play with
them, you'll get hooked. For a full list of the different iterators and
consumers, check out the [iterator module documentation](../../std/iter/index.html).
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/iterators.html).

View File

@ -1,428 +1,10 @@
# Lifetimes
This is the last of three sections presenting Rusts ownership system. This is one of
Rusts most distinct and compelling features, with which Rust developers should
become quite acquainted. Ownership is how Rust achieves its largest goal,
memory safety. There are a few distinct concepts, each with its own chapter:
The first edition of the book is no longer distributed with Rust's documentation.
* [ownership][ownership], the key concept
* [borrowing][borrowing], and their associated feature references
* lifetimes, which youre reading now
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
These three chapters are related, and in order. Youll need all three to fully
understand the ownership system.
[ownership]: ownership.html
[borrowing]: references-and-borrowing.html
# Meta
Before we get to the details, two important notes about the ownership system.
Rust has a focus on safety and speed. It accomplishes these goals through many
zero-cost abstractions, which means that in Rust, abstractions cost as little
as possible in order to make them work. The ownership system is a prime example
of a zero-cost abstraction. All of the analysis well talk about in this guide
is _done at compile time_. You do not pay any run-time cost for any of these
features.
However, this system does have a certain cost: learning curve. Many new users
to Rust experience something we like to call fighting with the borrow
checker, where the Rust compiler refuses to compile a program that the author
thinks is valid. This often happens because the programmers mental model of
how ownership should work doesnt match the actual rules that Rust implements.
You probably will experience similar things at first. There is good news,
however: more experienced Rust developers report that once they work with the
rules of the ownership system for a period of time, they fight the borrow
checker less and less.
With that in mind, lets learn about lifetimes.
# Lifetimes
Lending out a reference to a resource that someone else owns can be
complicated. For example, imagine this set of operations:
1. I acquire a handle to some kind of resource.
2. I lend you a reference to the resource.
3. I decide Im done with the resource, and deallocate it, while you still have
your reference.
4. You decide to use the resource.
Uh oh! Your reference is pointing to an invalid resource. This is called a
dangling pointer or use after free, when the resource is memory. A small
example of such a situation would be:
```rust,ignore
let r; // Introduce reference: `r`.
{
let i = 1; // Introduce scoped value: `i`.
r = &i; // Store reference of `i` in `r`.
} // `i` goes out of scope and is dropped.
println!("{}", r); // `r` still refers to `i`.
```
To fix this, we have to make sure that step four never happens after step
three. In the small example above the Rust compiler is able to report the issue
as it can see the lifetimes of the various values in the function.
When we have a function that takes arguments by reference the situation becomes
more complex. Consider the following example:
```rust,ignore
fn skip_prefix(line: &str, prefix: &str) -> &str {
// ...
# line
}
let line = "lang:en=Hello World!";
let lang = "en";
let v;
{
let p = format!("lang:{}=", lang); // -+ `p` comes into scope.
v = skip_prefix(line, p.as_str()); // |
} // -+ `p` goes out of scope.
println!("{}", v);
```
Here we have a function `skip_prefix` which takes two `&str` references
as parameters and returns a single `&str` reference. We call it
by passing in references to `line` and `p`: Two variables with different
lifetimes. Now the safety of the `println!`-line depends on whether the
reference returned by `skip_prefix` function references the still living
`line` or the already dropped `p` string.
Because of the above ambiguity, Rust will refuse to compile the example
code. To get it to compile we need to tell the compiler more about the
lifetimes of the references. This can be done by making the lifetimes
explicit in the function declaration:
```rust
fn skip_prefix<'a, 'b>(line: &'a str, prefix: &'b str) -> &'a str {
// ...
# line
}
```
Let's examine the changes without going too deep into the syntax for now -
we'll get to that later. The first change was adding the `<'a, 'b>` after the
method name. This introduces two lifetime parameters: `'a` and `'b`. Next, each
reference in the function signature was associated with one of the lifetime
parameters by adding the lifetime name after the `&`. This tells the compiler
how the lifetimes between different references are related.
As a result the compiler is now able to deduce that the return value of
`skip_prefix` has the same lifetime as the `line` parameter, which makes the `v`
reference safe to use even after the `p` goes out of scope in the original
example.
In addition to the compiler being able to validate the usage of `skip_prefix`
return value, it can also ensure that the implementation follows the contract
established by the function declaration. This is useful especially when you are
implementing traits that are introduced [later in the book][traits].
**Note** It's important to understand that lifetime annotations are
_descriptive_, not _prescriptive_. This means that how long a reference is valid
is determined by the code, not by the annotations. The annotations, however,
give information about lifetimes to the compiler that uses them to check the
validity of references. The compiler can do so without annotations in simple
cases, but needs the programmer's support in complex scenarios.
[traits]: traits.html
# Syntax
The `'a` reads the lifetime a. Technically, every reference has some lifetime
associated with it, but the compiler lets you elide (i.e. omit, see
["Lifetime Elision"][lifetime-elision] below) them in common cases. Before we
get to that, though, lets look at a short example with explicit lifetimes:
[lifetime-elision]: #lifetime-elision
```rust,ignore
fn bar<'a>(...)
```
We previously talked a little about [function syntax][functions], but we didnt
discuss the `<>`s after a functions name. A function can have generic
parameters between the `<>`s, of which lifetimes are one kind. Well discuss
other kinds of generics [later in the book][generics], but for now, lets
focus on the lifetimes aspect.
[functions]: functions.html
[generics]: generics.html
We use `<>` to declare our lifetimes. This says that `bar` has one lifetime,
`'a`. If we had two reference parameters with different lifetimes, it would
look like this:
```rust,ignore
fn bar<'a, 'b>(...)
```
Then in our parameter list, we use the lifetimes weve named:
```rust,ignore
...(x: &'a i32)
```
If we wanted a `&mut` reference, wed do this:
```rust,ignore
...(x: &'a mut i32)
```
If you compare `&mut i32` to `&'a mut i32`, theyre the same, its that
the lifetime `'a` has snuck in between the `&` and the `mut i32`. We read `&mut
i32` as a mutable reference to an `i32` and `&'a mut i32` as a mutable
reference to an `i32` with the lifetime `'a`.
# In `struct`s
Youll also need explicit lifetimes when working with [`struct`][structs]s that
contain references:
```rust
struct Foo<'a> {
x: &'a i32,
}
fn main() {
let y = &5; // This is the same as `let _y = 5; let y = &_y;`.
let f = Foo { x: y };
println!("{}", f.x);
}
```
[structs]: structs.html
As you can see, `struct`s can also have lifetimes. In a similar way to functions,
```rust
struct Foo<'a> {
# x: &'a i32,
# }
```
declares a lifetime, and
```rust
# struct Foo<'a> {
x: &'a i32,
# }
```
uses it. So why do we need a lifetime here? We need to ensure that any reference
to a `Foo` cannot outlive the reference to an `i32` it contains.
## `impl` blocks
Lets implement a method on `Foo`:
```rust
struct Foo<'a> {
x: &'a i32,
}
impl<'a> Foo<'a> {
fn x(&self) -> &'a i32 { self.x }
}
fn main() {
let y = &5; // This is the same as `let _y = 5; let y = &_y;`.
let f = Foo { x: y };
println!("x is: {}", f.x());
}
```
As you can see, we need to declare a lifetime for `Foo` in the `impl` line. We repeat
`'a` twice, like on functions: `impl<'a>` defines a lifetime `'a`, and `Foo<'a>`
uses it.
## Multiple lifetimes
If you have multiple references, you can use the same lifetime multiple times:
```rust
fn x_or_y<'a>(x: &'a str, y: &'a str) -> &'a str {
# x
# }
```
This says that `x` and `y` both are alive for the same scope, and that the
return value is also alive for that scope. If you wanted `x` and `y` to have
different lifetimes, you can use multiple lifetime parameters:
```rust
fn x_or_y<'a, 'b>(x: &'a str, y: &'b str) -> &'a str {
# x
# }
```
In this example, `x` and `y` have different valid scopes, but the return value
has the same lifetime as `x`.
## Thinking in scopes
A way to think about lifetimes is to visualize the scope that a reference is
valid for. For example:
```rust
fn main() {
let y = &5; // -+ `y` comes into scope.
// |
// Stuff... // |
// |
} // -+ `y` goes out of scope.
```
Adding in our `Foo`:
```rust
struct Foo<'a> {
x: &'a i32,
}
fn main() {
let y = &5; // -+ `y` comes into scope.
let f = Foo { x: y }; // -+ `f` comes into scope.
// |
// Stuff... // |
// |
} // -+ `f` and `y` go out of scope.
```
Our `f` lives within the scope of `y`, so everything works. What if it didnt?
This code wont work:
```rust,ignore
struct Foo<'a> {
x: &'a i32,
}
fn main() {
let x; // -+ `x` comes into scope.
// |
{ // |
let y = &5; // ---+ `y` comes into scope.
let f = Foo { x: y }; // ---+ `f` comes into scope.
x = &f.x; // | | This causes an error.
} // ---+ `f` and y go out of scope.
// |
println!("{}", x); // |
} // -+ `x` goes out of scope.
```
Whew! As you can see here, the scopes of `f` and `y` are smaller than the scope
of `x`. But when we do `x = &f.x`, we make `x` a reference to something thats
about to go out of scope.
Named lifetimes are a way of giving these scopes a name. Giving something a
name is the first step towards being able to talk about it.
## 'static
The lifetime named static is a special lifetime. It signals that something
has the lifetime of the entire program. Most Rust programmers first come across
`'static` when dealing with strings:
```rust
let x: &'static str = "Hello, world.";
```
String literals have the type `&'static str` because the reference is always
alive: they are baked into the data segment of the final binary. Another
example are globals:
```rust
static FOO: i32 = 5;
let x: &'static i32 = &FOO;
```
This adds an `i32` to the data segment of the binary, and `x` is a reference
to it.
## Lifetime Elision
Rust supports powerful local type inference in the bodies of functions, but it
deliberately does not perform any reasoning about types for item signatures.
However, for ergonomic reasons, a very restricted secondary inference algorithm called
“lifetime elision” does apply when judging lifetimes. Lifetime elision is concerned solely with inferring
lifetime parameters using three easily memorizable and unambiguous rules. This means lifetime elision
acts as a shorthand for writing an item signature, while not hiding
away the actual types involved as full local inference would if applied to it.
When talking about lifetime elision, we use the terms *input lifetime* and
*output lifetime*. An *input lifetime* is a lifetime associated with a parameter
of a function, and an *output lifetime* is a lifetime associated with the return
value of a function. For example, this function has an input lifetime:
```rust,ignore
fn foo<'a>(bar: &'a str)
```
This one has an output lifetime:
```rust,ignore
fn foo<'a>() -> &'a str
```
This one has a lifetime in both positions:
```rust,ignore
fn foo<'a>(bar: &'a str) -> &'a str
```
Here are the three rules:
* Each elided lifetime in a functions arguments becomes a distinct lifetime
parameter.
* If there is exactly one input lifetime, elided or not, that lifetime is
assigned to all elided lifetimes in the return values of that function.
* If there are multiple input lifetimes, but one of them is `&self` or `&mut
self`, the lifetime of `self` is assigned to all elided output lifetimes.
Otherwise, it is an error to elide an output lifetime.
### Examples
Here are some examples of functions with elided lifetimes. Weve paired each
example of an elided lifetime with its expanded form.
```rust,ignore
fn print(s: &str); // elided
fn print<'a>(s: &'a str); // expanded
fn debug(lvl: u32, s: &str); // elided
fn debug<'a>(lvl: u32, s: &'a str); // expanded
```
In the preceding example, `lvl` doesnt need a lifetime because its not a
reference (`&`). Only things relating to references (such as a `struct`
which contains a reference) need lifetimes.
```rust,ignore
fn substr(s: &str, until: u32) -> &str; // elided
fn substr<'a>(s: &'a str, until: u32) -> &'a str; // expanded
fn get_str() -> &str; // ILLEGAL, no inputs
fn frob(s: &str, t: &str) -> &str; // ILLEGAL, two inputs
fn frob<'a, 'b>(s: &'a str, t: &'b str) -> &str; // Expanded: Output lifetime is ambiguous
fn get_mut(&mut self) -> &mut T; // elided
fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded
fn args<T: ToCStr>(&mut self, args: &[T]) -> &mut Command; // elided
fn args<'a, 'b, T: ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command; // expanded
fn new(buf: &mut [u8]) -> BufWriter; // elided
fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a>; // expanded
```
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/lifetimes.html).

View File

@ -1,215 +1,10 @@
# Loops
Rust currently provides three approaches to performing some kind of iterative activity. They are: `loop`, `while` and `for`. Each approach has its own set of uses.
The first edition of the book is no longer distributed with Rust's documentation.
## loop
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
The infinite `loop` is the simplest form of loop available in Rust. Using the keyword `loop`, Rust provides a way to loop indefinitely until some terminating statement is reached. Rust's infinite `loop`s look like this:
```rust,ignore
loop {
println!("Loop forever!");
}
```
## while
Rust also has a `while` loop. It looks like this:
```rust
let mut x = 5; // mut x: i32
let mut done = false; // mut done: bool
while !done {
x += x - 3;
println!("{}", x);
if x % 5 == 0 {
done = true;
}
}
```
`while` loops are the correct choice when youre not sure how many times
you need to loop.
If you need an infinite loop, you may be tempted to write this:
```rust,ignore
while true {
```
However, `loop` is far better suited to handle this case:
```rust,ignore
loop {
```
Rusts control-flow analysis treats this construct differently than a `while
true`, since we know that it will always loop. In general, the more information
we can give to the compiler, the better it can do with safety and code
generation, so you should always prefer `loop` when you plan to loop
infinitely.
## for
The `for` loop is used to loop a particular number of times. Rusts `for` loops
work a bit differently than in other systems languages, however. Rusts `for`
loop doesnt 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,
```rust,ignore
for var in expression {
code
}
```
The expression is an item that can be converted into an [iterator] using
[`IntoIterator`]. The iterator gives back a series of elements, one element per
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.
[iterator]: iterators.html
[`IntoIterator`]: ../../std/iter/trait.IntoIterator.html
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.
### Enumerate
When you need to keep track of how many times you have already looped, you can
use the `.enumerate()` function.
#### On ranges:
```rust
for (index, value) in (5..10).enumerate() {
println!("index = {} and value = {}", index, value);
}
```
Outputs:
```text
index = 0 and value = 5
index = 1 and value = 6
index = 2 and value = 7
index = 3 and value = 8
index = 4 and value = 9
```
Don't forget to add the parentheses around the range.
#### On iterators:
```rust
let lines = "hello\nworld".lines();
for (linenumber, line) in lines.enumerate() {
println!("{}: {}", linenumber, line);
}
```
Outputs:
```text
0: hello
1: world
```
## Ending iteration early
Lets take a look at that `while` loop we had earlier:
```rust
let mut x = 5;
let mut done = false;
while !done {
x += x - 3;
println!("{}", x);
if x % 5 == 0 {
done = true;
}
}
```
We had to keep a dedicated `mut` boolean variable binding, `done`, to know
when we should exit out of the loop. Rust has two keywords to help us with
modifying iteration: `break` and `continue`.
In this case, we can write the loop in a better way with `break`:
```rust
let mut x = 5;
loop {
x += x - 3;
println!("{}", x);
if x % 5 == 0 { break; }
}
```
We now loop forever with `loop` and use `break` to break out early. Issuing an explicit `return` statement will also serve to terminate the loop early.
`continue` is similar, but instead of ending the loop, it goes to the next
iteration. This will only print the odd numbers:
```rust
for x in 0..10 {
if x % 2 == 0 { continue; }
println!("{}", x);
}
```
## Loop labels
You may also encounter situations where you have nested loops and need to
specify which one your `break` or `continue` statement is for. Like most
other languages, Rust's `break` or `continue` apply to the innermost loop.
In a situation where you would like to `break` or `continue` for one
of the outer loops, you can use labels to specify which loop the `break` or
`continue` statement applies to.
In the example below, we `continue` to the next iteration of `outer` loop
when `x` is even, while we `continue` to the next iteration of `inner`
loop when y is even. So it will execute the `println!` when both `x` and
`y` are odd.
```rust
'outer: for x in 0..10 {
'inner: for y in 0..10 {
if x % 2 == 0 { continue 'outer; } // Continues the loop over `x`.
if y % 2 == 0 { continue 'inner; } // Continues the loop over `y`.
println!("x: {}, y: {}", x, y);
}
}
```
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/loops.html).

View File

@ -1,786 +1,10 @@
# Macros
By now youve learned about many of the tools Rust provides for abstracting and
reusing code. These units of code reuse have a rich semantic structure. For
example, functions have a type signature, type parameters have trait bounds,
and overloaded functions must belong to a particular trait.
The first edition of the book is no longer distributed with Rust's documentation.
This structure means that Rusts core abstractions have powerful compile-time
correctness checking. But this comes at the price of reduced flexibility. If
you visually identify a pattern of repeated code, you may find its difficult
or cumbersome to express that pattern as a generic function, a trait, or
anything else within Rusts semantics.
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
Macros allow us to abstract at a syntactic level. A macro invocation is
shorthand for an "expanded" syntactic form. This expansion happens early in
compilation, before any static checking. As a result, macros can capture many
patterns of code reuse that Rusts core abstractions cannot.
The drawback is that macro-based code can be harder to understand, because
fewer of the built-in rules apply. Like an ordinary function, a well-behaved
macro can be used without understanding its implementation. However, it can be
difficult to design a well-behaved macro! Additionally, compiler errors in
macro code are harder to interpret, because they describe problems in the
expanded code, not the source-level form that developers use.
These drawbacks make macros something of a "feature of last resort". Thats not
to say that macros are bad; they are part of Rust because sometimes theyre
needed for truly concise, well-abstracted code. Just keep this tradeoff in
mind.
# Defining a macro
You may have seen the `vec!` macro, used to initialize a [vector][vector] with
any number of elements.
[vector]: vectors.html
```rust
let x: Vec<u32> = vec![1, 2, 3];
# assert_eq!(x, [1, 2, 3]);
```
This cant be an ordinary function, because it takes any number of arguments.
But we can imagine it as syntactic shorthand for
```rust
let x: Vec<u32> = {
let mut temp_vec = Vec::new();
temp_vec.push(1);
temp_vec.push(2);
temp_vec.push(3);
temp_vec
};
# assert_eq!(x, [1, 2, 3]);
```
We can implement this shorthand, using a macro: [^actual]
[^actual]: The actual definition of `vec!` in libcollections differs from the
one presented here, for reasons of efficiency and reusability.
```rust
macro_rules! vec {
( $( $x:expr ),* ) => {
{
let mut temp_vec = Vec::new();
$(
temp_vec.push($x);
)*
temp_vec
}
};
}
# fn main() {
# assert_eq!(vec![1,2,3], [1, 2, 3]);
# }
```
Whoa, thats a lot of new syntax! Lets break it down.
```rust,ignore
macro_rules! vec { ... }
```
This says were defining a macro named `vec`, much as `fn vec` would define a
function named `vec`. In prose, we informally write a macros name with an
exclamation point, e.g. `vec!`. The exclamation point is part of the invocation
syntax and serves to distinguish a macro from an ordinary function.
## Matching
The macro is defined through a series of rules, which are pattern-matching
cases. Above, we had
```rust,ignore
( $( $x:expr ),* ) => { ... };
```
This is like a `match` expression arm, but the matching happens on Rust syntax
trees, at compile time. The semicolon is optional on the last (here, only)
case. The "pattern" on the left-hand side of `=>` is known as a matcher.
These have [their own little grammar] within the language.
[their own little grammar]: ../../reference/macros.html
The matcher `$x:expr` will match any Rust expression, binding that syntax tree
to the metavariable `$x`. The identifier `expr` is a fragment specifier;
the full possibilities are enumerated later in this chapter.
Surrounding the matcher with `$(...),*` will match zero or more expressions,
separated by commas.
Aside from the special matcher syntax, any Rust tokens that appear in a matcher
must match exactly. For example,
```rust,ignore
macro_rules! foo {
(x => $e:expr) => (println!("mode X: {}", $e));
(y => $e:expr) => (println!("mode Y: {}", $e));
}
fn main() {
foo!(y => 3);
}
```
will print
```text
mode Y: 3
```
With
```rust,ignore
foo!(z => 3);
```
we get the compiler error
```text
error: no rules expected the token `z`
```
## Expansion
The right-hand side of a macro rule is ordinary Rust syntax, for the most part.
But we can splice in bits of syntax captured by the matcher. From the original
example:
```rust,ignore
$(
temp_vec.push($x);
)*
```
Each matched expression `$x` will produce a single `push` statement in the
macro expansion. The repetition in the expansion proceeds in "lockstep" with
repetition in the matcher (more on this in a moment).
Because `$x` was already declared as matching an expression, we dont repeat
`:expr` on the right-hand side. Also, we dont include a separating comma as
part of the repetition operator. Instead, we have a terminating semicolon
within the repeated block.
Another detail: the `vec!` macro has *two* pairs of braces on the right-hand
side. They are often combined like so:
```rust,ignore
macro_rules! foo {
() => {{
...
}}
}
```
The outer braces are part of the syntax of `macro_rules!`. In fact, you can use
`()` or `[]` instead. They simply delimit the right-hand side as a whole.
The inner braces are part of the expanded syntax. Remember, the `vec!` macro is
used in an expression context. To write an expression with multiple statements,
including `let`-bindings, we use a block. If your macro expands to a single
expression, you dont need this extra layer of braces.
Note that we never *declared* that the macro produces an expression. In fact,
this is not determined until we use the macro as an expression. With care, you
can write a macro whose expansion works in several contexts. For example,
shorthand for a data type could be valid as either an expression or a pattern.
## Repetition
The repetition operator follows two principal rules:
1. `$(...)*` walks through one "layer" of repetitions, for all of the `$name`s
it contains, in lockstep, and
2. each `$name` must be under at least as many `$(...)*`s as it was matched
against. If it is under more, itll be duplicated, as appropriate.
This baroque macro illustrates the duplication of variables from outer
repetition levels.
```rust
macro_rules! o_O {
(
$(
$x:expr; [ $( $y:expr ),* ]
);*
) => {
&[ $($( $x + $y ),*),* ]
}
}
fn main() {
let a: &[i32]
= o_O!(10; [1, 2, 3];
20; [4, 5, 6]);
assert_eq!(a, [11, 12, 13, 24, 25, 26]);
}
```
Thats most of the matcher syntax. These examples use `$(...)*`, which is a
"zero or more" match. Alternatively you can write `$(...)+` for a "one or
more" match. Both forms optionally include a separator, which can be any token
except `+` or `*`.
This system is based on
"[Macro-by-Example](https://www.cs.indiana.edu/ftp/techreports/TR206.pdf)"
(PDF link).
# Hygiene
Some languages implement macros using simple text substitution, which leads to
various problems. For example, this C program prints `13` instead of the
expected `25`.
```text
#define FIVE_TIMES(x) 5 * x
int main() {
printf("%d\n", FIVE_TIMES(2 + 3));
return 0;
}
```
After expansion we have `5 * 2 + 3`, and multiplication has greater precedence
than addition. If youve used C macros a lot, you probably know the standard
idioms for avoiding this problem, as well as five or six others. In Rust, we
dont have to worry about it.
```rust
macro_rules! five_times {
($x:expr) => (5 * $x);
}
fn main() {
assert_eq!(25, five_times!(2 + 3));
}
```
The metavariable `$x` is parsed as a single expression node, and keeps its
place in the syntax tree even after substitution.
Another common problem in macro systems is variable capture. Heres a C
macro using a block with multiple statements.
```text
#define LOG(msg) do { \
int state = get_log_state(); \
if (state > 0) { \
printf("log(%d): %s\n", state, msg); \
} \
} while (0)
```
Heres a simple use case that goes terribly wrong:
```text
const char *state = "reticulating splines";
LOG(state);
```
This expands to
```text
const char *state = "reticulating splines";
do {
int state = get_log_state();
if (state > 0) {
printf("log(%d): %s\n", state, state);
}
} while (0);
```
The second variable named `state` shadows the first one. This is a problem
because the print statement should refer to both of them.
The equivalent Rust macro has the desired behavior.
```rust
# fn get_log_state() -> i32 { 3 }
macro_rules! log {
($msg:expr) => {{
let state: i32 = get_log_state();
if state > 0 {
println!("log({}): {}", state, $msg);
}
}};
}
fn main() {
let state: &str = "reticulating splines";
log!(state);
}
```
This works because Rust has a [hygienic macro system]. Each macro expansion
happens in a distinct syntax context, and each variable is tagged with the
syntax context where it was introduced. Its as though the variable `state`
inside `main` is painted a different "color" from the variable `state` inside
the macro, and therefore they dont conflict.
[hygienic macro system]: https://en.wikipedia.org/wiki/Hygienic_macro
This also restricts the ability of macros to introduce new bindings at the
invocation site. Code such as the following will not work:
```rust,ignore
macro_rules! foo {
() => (let x = 3;);
}
fn main() {
foo!();
println!("{}", x);
}
```
Instead you need to pass the variable name into the invocation, so that its
tagged with the right syntax context.
```rust
macro_rules! foo {
($v:ident) => (let $v = 3;);
}
fn main() {
foo!(x);
println!("{}", x);
}
```
This holds for `let` bindings and loop labels, but not for [items][items].
So the following code does compile:
```rust
macro_rules! foo {
() => (fn x() { });
}
fn main() {
foo!();
x();
}
```
[items]: ../../reference/items.html
# Recursive macros
A macros expansion can include more macro invocations, including invocations
of the very same macro being expanded. These recursive macros are useful for
processing tree-structured input, as illustrated by this (simplistic) HTML
shorthand:
```rust
# #![allow(unused_must_use)]
macro_rules! write_html {
($w:expr, ) => (());
($w:expr, $e:tt) => (write!($w, "{}", $e));
($w:expr, $tag:ident [ $($inner:tt)* ] $($rest:tt)*) => {{
write!($w, "<{}>", stringify!($tag));
write_html!($w, $($inner)*);
write!($w, "</{}>", stringify!($tag));
write_html!($w, $($rest)*);
}};
}
fn main() {
# // FIXME(#21826)
use std::fmt::Write;
let mut out = String::new();
write_html!(&mut out,
html[
head[title["Macros guide"]]
body[h1["Macros are the best!"]]
]);
assert_eq!(out,
"<html><head><title>Macros guide</title></head>\
<body><h1>Macros are the best!</h1></body></html>");
}
```
# Debugging macro code
To see the results of expanding macros, run `rustc --pretty expanded`. The
output represents a whole crate, so you can also feed it back in to `rustc`,
which will sometimes produce better error messages than the original
compilation. Note that the `--pretty expanded` output may have a different
meaning if multiple variables of the same name (but different syntax contexts)
are in play in the same scope. In this case `--pretty expanded,hygiene` will
tell you about the syntax contexts.
`rustc` provides two syntax extensions that help with macro debugging. For now,
they are unstable and require feature gates.
* `log_syntax!(...)` will print its arguments to standard output, at compile
time, and "expand" to nothing.
* `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.
# 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
Rusts 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 { 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 and optionally an expression. Example:
`{ log(error, "hi"); return 12; }`.
* `item`: an [item][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` and `stmt` variables may only be followed by one of: `=> , ;`
* `ty` and `path` variables may only be followed by one of: `=> , = | ; : > [ { as where`
* `pat` variables may only be followed by one of: `=> , = | if in`
* Other variables may be followed by any token.
These rules provide some flexibility for Rusts syntax to evolve without
breaking existing macros.
The macro system does not deal with parse ambiguity at all. For example, the
grammar `$($i:ident)* $e:expr` will always fail to parse, because the parser would
be forced to choose between parsing `$i` and parsing `$e`. Changing the
invocation syntax to put a distinctive token in front can solve the problem. In
this case, you can write `$(I $i:ident)* E $e:expr`.
[item]: ../../reference/items.html
# 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 crates 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. If you want to use your macro, which is
defined in a different module, you need to use `macro_use` attribute *before*
using the macro. Let's say our macros are defined in module `macros` and we
would like to use them inside module `client`. This is the required module
definition order:
```rust
#[macro_use]
mod macros;
mod client;
```
The opposite order would result in a compilation failure:
```rust
mod client;
#[macro_use]
mod macros;
```
```bash
error: cannot find macro `my_macro!` in this scope
```
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 childs `mod` item. If the parent also has `macro_use`
then the macros will be visible in the grandparent after the parents `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 crates 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/attributes.html#macro-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`.
# 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 macros
arguments.
As an extreme example, it is possible, though hardly advisable, to implement
the [Bitwise Cyclic Tag](https://esolangs.org/wiki/Bitwise_Cyclic_Tag) automaton
within Rusts 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.
# Common macros
Here are some common macros youll see in Rust code.
## panic!
This macro causes the current thread to panic. You can give it a message
to panic with:
```rust,should_panic
panic!("oh no!");
```
## vec!
The `vec!` macro is used throughout the book, so youve probably seen it
already. It creates `Vec<T>`s with ease:
```rust
let v = vec![1, 2, 3, 4, 5];
```
It also lets you make vectors with repeating values. For example, a hundred
zeroes:
```rust
let v = vec![0; 100];
```
## assert! and assert_eq!
These two macros are used in tests. `assert!` takes a boolean. `assert_eq!`
takes two values and checks them for equality. `true` passes, `false` `panic!`s.
Like this:
```rust,should_panic
// A-ok!
assert!(true);
assert_eq!(5, 3 + 2);
// Nope :(
assert!(5 < 3);
assert_eq!(5, 3);
```
## try!
`try!` is used for error handling. It takes something that can return a
`Result<T, E>`, and gives `T` if its a `Ok<T>`, and `return`s with the
`Err(E)` if its that. Like this:
```rust,no_run
use std::fs::File;
fn foo() -> std::io::Result<()> {
let f = try!(File::create("foo.txt"));
Ok(())
}
```
This is cleaner than doing this:
```rust,no_run
use std::fs::File;
fn foo() -> std::io::Result<()> {
let f = File::create("foo.txt");
let f = match f {
Ok(t) => t,
Err(e) => return Err(e),
};
Ok(())
}
```
## unreachable!
This macro is used when you think some code should never execute:
```rust
if false {
unreachable!();
}
```
Sometimes, the compiler may make you have a different branch that you know
will never, ever run. In these cases, use this macro, so that if you end
up wrong, youll get a `panic!` about it.
```rust
let x: Option<i32> = None;
match x {
Some(_) => unreachable!(),
None => println!("I know x is None!"),
}
```
## unimplemented!
The `unimplemented!` macro can be used when youre trying to get your functions
to typecheck, and dont want to worry about writing out the body of the
function. One example of this situation is implementing a trait with multiple
required methods, where you want to tackle one at a time. Define the others
as `unimplemented!` until youre ready to write them.
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/macros.html).

View File

@ -1,100 +1,10 @@
# Match
Often, a simple [`if`][if]/`else` isnt enough, because you have more than two
possible options. Also, conditions can get quite complex. Rust
has a keyword, `match`, that allows you to replace complicated `if`/`else`
groupings with something more powerful. Check it out:
The first edition of the book is no longer distributed with Rust's documentation.
```rust
let x = 5;
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
match x {
1 => println!("one"),
2 => println!("two"),
3 => println!("three"),
4 => println!("four"),
5 => println!("five"),
_ => println!("something else"),
}
```
[if]: if.html
`match` takes an expression and then branches based on its value. Each arm of
the branch is of the form `val => expression`. When the value matches, that arms
expression will be evaluated. Its called `match` because of the term pattern
matching, which `match` is an implementation of. Theres a [separate section on
patterns][patterns] that covers all the patterns that are possible here.
[patterns]: patterns.html
One of the many advantages of `match` is it enforces exhaustiveness checking.
For example if we remove the last arm with the underscore `_`, the compiler will
give us an error:
```text
error: non-exhaustive patterns: `_` not covered
```
Rust is telling us that we forgot some value. The compiler infers from `x` that it
can have any 32bit integer value; for example -2,147,483,648 to 2,147,483,647. The `_` acts
as a 'catch-all', and will catch all possible values that *aren't* specified in
an arm of `match`. As you can see in the previous example, we provide `match`
arms for integers 1-5, if `x` is 6 or any other value, then it is caught by `_`.
`match` is also an expression, which means we can use it on the right-hand
side of a `let` binding or directly where an expression is used:
```rust
let x = 5;
let number = match x {
1 => "one",
2 => "two",
3 => "three",
4 => "four",
5 => "five",
_ => "something else",
};
```
Sometimes its a nice way of converting something from one type to another; in
this example the integers are converted to `String`.
# Matching on enums
Another important use of the `match` keyword is to process the possible
variants of an enum:
```rust
enum Message {
Quit,
ChangeColor(i32, i32, i32),
Move { x: i32, y: i32 },
Write(String),
}
fn quit() { /* ... */ }
fn change_color(r: i32, g: i32, b: i32) { /* ... */ }
fn move_cursor(x: i32, y: i32) { /* ... */ }
fn process_message(msg: Message) {
match msg {
Message::Quit => quit(),
Message::ChangeColor(r, g, b) => change_color(r, g, b),
Message::Move { x, y: new_name_for_y } => move_cursor(x, new_name_for_y),
Message::Write(s) => println!("{}", s),
};
}
```
Again, the Rust compiler checks exhaustiveness, so it demands that you
have a match arm for every variant of the enum. If you leave one off, it
will give you a compile-time error unless you use `_` or provide all possible
arms.
Unlike the previous uses of `match`, you cant use the normal `if`
statement to do this. You can use the [`if let`][if-let] statement,
which can be seen as an abbreviated form of `match`.
[if-let]: if-let.html
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/match.html).

View File

@ -1,259 +1,10 @@
# Method Syntax
Functions are great, but if you want to call a bunch of them on some data, it
can be awkward. Consider this code:
The first edition of the book is no longer distributed with Rust's documentation.
```rust,ignore
baz(bar(foo));
```
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
We would read this left-to-right, and so we see baz bar foo. But this isnt the
order that the functions would get called in, thats inside-out: foo bar baz.
Wouldnt it be nice if we could do this instead?
```rust,ignore
foo.bar().baz();
```
Luckily, as you may have guessed with the leading question, you can! Rust provides
the ability to use this method call syntax via the `impl` keyword.
# Method calls
Heres how it works:
```rust
struct Circle {
x: f64,
y: f64,
radius: f64,
}
impl Circle {
fn area(&self) -> f64 {
std::f64::consts::PI * (self.radius * self.radius)
}
}
fn main() {
let c = Circle { x: 0.0, y: 0.0, radius: 2.0 };
println!("{}", c.area());
}
```
This will print `12.566371`.
Weve made a `struct` that represents a circle. We then write an `impl` block,
and inside it, define a method, `area`.
Methods take a special first parameter, of which there are three variants:
`self`, `&self`, and `&mut self`. You can think of this first parameter as
being the `foo` in `foo.bar()`. The three variants correspond to the three
kinds of things `foo` could be: `self` if its a value on the stack,
`&self` if its a reference, and `&mut self` if its a mutable reference.
Because we took the `&self` parameter to `area`, we can use it like any
other parameter. Because we know its a `Circle`, we can access the `radius`
like we would with any other `struct`.
We should default to using `&self`, as you should prefer borrowing over taking
ownership, as well as taking immutable references over mutable ones. Heres an
example of all three variants:
```rust
struct Circle {
x: f64,
y: f64,
radius: f64,
}
impl Circle {
fn reference(&self) {
println!("taking self by reference!");
}
fn mutable_reference(&mut self) {
println!("taking self by mutable reference!");
}
fn takes_ownership(self) {
println!("taking ownership of self!");
}
}
```
You can use as many `impl` blocks as youd like. The previous example could
have also been written like this:
```rust
struct Circle {
x: f64,
y: f64,
radius: f64,
}
impl Circle {
fn reference(&self) {
println!("taking self by reference!");
}
}
impl Circle {
fn mutable_reference(&mut self) {
println!("taking self by mutable reference!");
}
}
impl Circle {
fn takes_ownership(self) {
println!("taking ownership of self!");
}
}
```
# Chaining method calls
So, now we know how to call a method, such as `foo.bar()`. But what about our
original example, `foo.bar().baz()`? This is called method chaining. Lets
look at an example:
```rust
struct Circle {
x: f64,
y: f64,
radius: f64,
}
impl Circle {
fn area(&self) -> f64 {
std::f64::consts::PI * (self.radius * self.radius)
}
fn grow(&self, increment: f64) -> Circle {
Circle { x: self.x, y: self.y, radius: self.radius + increment }
}
}
fn main() {
let c = Circle { x: 0.0, y: 0.0, radius: 2.0 };
println!("{}", c.area());
let d = c.grow(2.0).area();
println!("{}", d);
}
```
Check the return type:
```rust
# struct Circle;
# impl Circle {
fn grow(&self, increment: f64) -> Circle {
# Circle } }
```
We say were returning a `Circle`. With this method, we can grow a new
`Circle` to any arbitrary size.
# Associated functions
You can also define associated functions that do not take a `self` parameter.
Heres a pattern thats very common in Rust code:
```rust
struct Circle {
x: f64,
y: f64,
radius: f64,
}
impl Circle {
fn new(x: f64, y: f64, radius: f64) -> Circle {
Circle {
x: x,
y: y,
radius: radius,
}
}
}
fn main() {
let c = Circle::new(0.0, 0.0, 2.0);
}
```
This associated function builds a new `Circle` for us. Note that associated
functions are called with the `Struct::function()` syntax, rather than the
`ref.method()` syntax. Some other languages call associated functions static
methods.
# Builder Pattern
Lets say that we want our users to be able to create `Circle`s, but we will
allow them to only set the properties they care about. Otherwise, the `x`
and `y` attributes will be `0.0`, and the `radius` will be `1.0`. Rust doesnt
have method overloading, named arguments, or variable arguments. We employ
the builder pattern instead. It looks like this:
```rust
struct Circle {
x: f64,
y: f64,
radius: f64,
}
impl Circle {
fn area(&self) -> f64 {
std::f64::consts::PI * (self.radius * self.radius)
}
}
struct CircleBuilder {
x: f64,
y: f64,
radius: f64,
}
impl CircleBuilder {
fn new() -> CircleBuilder {
CircleBuilder { x: 0.0, y: 0.0, radius: 1.0, }
}
fn x(&mut self, coordinate: f64) -> &mut CircleBuilder {
self.x = coordinate;
self
}
fn y(&mut self, coordinate: f64) -> &mut CircleBuilder {
self.y = coordinate;
self
}
fn radius(&mut self, radius: f64) -> &mut CircleBuilder {
self.radius = radius;
self
}
fn finalize(&self) -> Circle {
Circle { x: self.x, y: self.y, radius: self.radius }
}
}
fn main() {
let c = CircleBuilder::new()
.x(1.0)
.y(2.0)
.radius(2.0)
.finalize();
println!("area: {}", c.area());
println!("x: {}", c.x);
println!("y: {}", c.y);
}
```
What weve done here is make another `struct`, `CircleBuilder`. Weve defined our
builder methods on it. Weve also defined our `area()` method on `Circle`. We
also made one more method on `CircleBuilder`: `finalize()`. This method creates
our final `Circle` from the builder. Now, weve used the type system to enforce
our concerns: we can use the methods on `CircleBuilder` to constrain making
`Circle`s in any way we choose.
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/method-syntax.html).

View File

@ -1,181 +1,10 @@
# Mutability
Mutability, the ability to change something, works a bit differently in Rust
than in other languages. The first aspect of mutability is its non-default
status:
The first edition of the book is no longer distributed with Rust's documentation.
```rust,ignore
let x = 5;
x = 6; // Error!
```
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
We can introduce mutability with the `mut` keyword:
```rust
let mut x = 5;
x = 6; // No problem!
```
This is a mutable [variable binding][vb]. When a binding is mutable, it means
youre allowed to change what the binding points to. So in the above example,
its not so much that the value at `x` is changing, but that the binding
changed from one `i32` to another.
[vb]: variable-bindings.html
You can also create a [reference][ref] to it, using `&x`, but if you want to use the reference to change it, you will need a mutable reference:
```rust
let mut x = 5;
let y = &mut x;
```
[ref]: references-and-borrowing.html
`y` is an immutable binding to a mutable reference, which means that you cant bind 'y' to something else (`y = &mut z`), but `y` can be used to bind `x` to something else (`*y = 5`). A subtle distinction.
Of course, if you need both:
```rust
let mut x = 5;
let mut y = &mut x;
```
Now `y` can be bound to another value, and the value its referencing can be
changed.
Its important to note that `mut` is part of a [pattern][pattern], so you
can do things like this:
```rust
let (mut x, y) = (5, 6);
fn foo(mut x: i32) {
# }
```
Note that here, the `x` is mutable, but not the `y`.
[pattern]: patterns.html
# Interior vs. Exterior Mutability
However, when we say something is immutable in Rust, that doesnt mean that
its not able to be changed: we are referring to its exterior mutability that
in this case is immutable. Consider, for example, [`Arc<T>`][arc]:
```rust
use std::sync::Arc;
let x = Arc::new(5);
let y = x.clone();
```
[arc]: ../../std/sync/struct.Arc.html
When we call `clone()`, the `Arc<T>` needs to update the reference count. Yet
weve not used any `mut`s here, `x` is an immutable binding, and we didnt take
`&mut 5` or anything. So what gives?
To understand this, we have to go back to the core of Rusts guiding
philosophy, memory safety, and the mechanism by which Rust guarantees it, the
[ownership][ownership] system, and more specifically, [borrowing][borrowing]:
> You may have one or the other of these two kinds of borrows, but not both at
> the same time:
>
> * one or more references (`&T`) to a resource,
> * exactly one mutable reference (`&mut T`).
[ownership]: ownership.html
[borrowing]: references-and-borrowing.html#borrowing
So, thats the real definition of immutability: is this safe to have two
pointers to? In `Arc<T>`s case, yes: the mutation is entirely contained inside
the structure itself. Its not user facing. For this reason, it hands out `&T`
with `clone()`. If it handed out `&mut T`s, though, that would be a problem.
Other types, like the ones in the [`std::cell`][stdcell] module, have the
opposite: interior mutability. For example:
```rust
use std::cell::RefCell;
let x = RefCell::new(42);
let y = x.borrow_mut();
```
[stdcell]: ../../std/cell/index.html
RefCell hands out `&mut` references to whats inside of it with the
`borrow_mut()` method. Isnt that dangerous? What if we do:
```rust,ignore
use std::cell::RefCell;
let x = RefCell::new(42);
let y = x.borrow_mut();
let z = x.borrow_mut();
# (y, z);
```
This will in fact panic, at runtime. This is what `RefCell` does: it enforces
Rusts borrowing rules at runtime, and `panic!`s if theyre violated. This
allows us to get around another aspect of Rusts mutability rules. Lets talk
about it first.
## Field-level mutability
Mutability is a property of either a borrow (`&mut`) or a binding (`let mut`).
This means that, for example, you cannot have a [`struct`][struct] with
some fields mutable and some immutable:
```rust,ignore
struct Point {
x: i32,
mut y: i32, // Nope.
}
```
The mutability of a struct is in its binding:
```rust,ignore
struct Point {
x: i32,
y: i32,
}
let mut a = Point { x: 5, y: 6 };
a.x = 10;
let b = Point { x: 5, y: 6 };
b.x = 10; // Error: cannot assign to immutable field `b.x`.
```
[struct]: structs.html
However, by using [`Cell<T>`][cell], you can emulate field-level mutability:
```rust
use std::cell::Cell;
struct Point {
x: i32,
y: Cell<i32>,
}
let point = Point { x: 5, y: Cell::new(6) };
point.y.set(7);
println!("y: {:?}", point.y);
```
[cell]: ../../std/cell/struct.Cell.html
This will print `y: Cell { value: 7 }`. Weve successfully updated `y`.
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/mutability.html).

View File

@ -1,135 +1,10 @@
# Operators and Overloading
Rust allows for a limited form of operator overloading. There are certain
operators that are able to be overloaded. To support a particular operator
between types, theres a specific trait that you can implement, which then
overloads the operator.
The first edition of the book is no longer distributed with Rust's documentation.
For example, the `+` operator can be overloaded with the `Add` trait:
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
```rust
use std::ops::Add;
#[derive(Debug)]
struct Point {
x: i32,
y: i32,
}
impl Add for Point {
type Output = Point;
fn add(self, other: Point) -> Point {
Point { x: self.x + other.x, y: self.y + other.y }
}
}
fn main() {
let p1 = Point { x: 1, y: 0 };
let p2 = Point { x: 2, y: 3 };
let p3 = p1 + p2;
println!("{:?}", p3);
}
```
In `main`, we can use `+` on our two `Point`s, since weve implemented
`Add<Output=Point>` for `Point`.
There are a number of operators that can be overloaded this way, and all of
their associated traits live in the [`std::ops`][stdops] module. Check out its
documentation for the full list.
[stdops]: ../../std/ops/index.html
Implementing these traits follows a pattern. Lets look at [`Add`][add] in more
detail:
```rust
# mod foo {
pub trait Add<RHS = Self> {
type Output;
fn add(self, rhs: RHS) -> Self::Output;
}
# }
```
[add]: ../../std/ops/trait.Add.html
Theres three types in total involved here: the type you `impl Add` for, `RHS`,
which defaults to `Self`, and `Output`. For an expression `let z = x + y`, `x`
is the `Self` type, `y` is the RHS, and `z` is the `Self::Output` type.
```rust
# struct Point;
# use std::ops::Add;
impl Add<i32> for Point {
type Output = f64;
fn add(self, rhs: i32) -> f64 {
// Add an i32 to a Point and get an f64.
# 1.0
}
}
```
will let you do this:
```rust,ignore
let p: Point = // ...
let x: f64 = p + 2i32;
```
# Using operator traits in generic structs
Now that we know how operator traits are defined, we can define our `HasArea`
trait and `Square` struct from the [traits chapter][traits] more generically:
[traits]: traits.html
```rust
use std::ops::Mul;
trait HasArea<T> {
fn area(&self) -> T;
}
struct Square<T> {
x: T,
y: T,
side: T,
}
impl<T> HasArea<T> for Square<T>
where T: Mul<Output=T> + Copy {
fn area(&self) -> T {
self.side * self.side
}
}
fn main() {
let s = Square {
x: 0.0f64,
y: 0.0f64,
side: 12.0f64,
};
println!("Area of s: {}", s.area());
}
```
For `HasArea` and `Square`, we declare a type parameter `T` and replace
`f64` with it. The `impl` needs more involved modifications:
```rust,ignore
impl<T> HasArea<T> for Square<T>
where T: Mul<Output=T> + Copy { ... }
```
The `area` method requires that we can multiply the sides, so we declare that
type `T` must implement `std::ops::Mul`. Like `Add`, mentioned above, `Mul`
itself takes an `Output` parameter: since we know that numbers don't change
type when multiplied, we also set it to `T`. `T` must also support copying, so
Rust doesn't try to move `self.side` into the return value.
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/operators-and-overloading.html).

View File

@ -1,295 +1,10 @@
# Ownership
This is the first of three sections presenting Rusts ownership system. This is one of
Rusts most distinct and compelling features, with which Rust developers should
become quite acquainted. Ownership is how Rust achieves its largest goal,
memory safety. There are a few distinct concepts, each with its own
chapter:
The first edition of the book is no longer distributed with Rust's documentation.
* ownership, which youre reading now
* [borrowing][borrowing], and their associated feature references
* [lifetimes][lifetimes], an advanced concept of borrowing
These three chapters are related, and in order. Youll need all three to fully
understand the ownership system.
[borrowing]: references-and-borrowing.html
[lifetimes]: lifetimes.html
# Meta
Before we get to the details, two important notes about the ownership system.
Rust has a focus on safety and speed. It accomplishes these goals through many
zero-cost abstractions, which means that in Rust, abstractions cost as little
as possible in order to make them work. The ownership system is a prime example
of a zero-cost abstraction. All of the analysis well talk about in this guide
is _done at compile time_. You do not pay any run-time cost for any of these
features.
However, this system does have a certain cost: learning curve. Many new users
to Rust experience something we like to call fighting with the borrow
checker, where the Rust compiler refuses to compile a program that the author
thinks is valid. This often happens because the programmers mental model of
how ownership should work doesnt match the actual rules that Rust implements.
You probably will experience similar things at first. There is good news,
however: more experienced Rust developers report that once they work with the
rules of the ownership system for a period of time, they fight the borrow
checker less and less.
With that in mind, lets learn about ownership.
# Ownership
[Variable bindings][bindings] have a property in Rust: they have ownership
of what theyre bound to. This means that when a binding goes out of scope,
Rust will free the bound resources. For example:
```rust
fn foo() {
let v = vec![1, 2, 3];
}
```
When `v` comes into scope, a new [vector][vectors] is created on [the stack][stack],
and it allocates space on [the heap][heap] for its elements. When `v` goes out
of scope at the end of `foo()`, Rust will clean up everything related to the
vector, even the heap-allocated memory. This happens deterministically, at the
end of the scope.
We covered [vectors] in the previous chapter; we use them
here as an example of a type that allocates space on the heap at runtime. They
behave like [arrays], except their size may change by `push()`ing more
elements onto them.
Vectors have a [generic type][generics] `Vec<T>`, so in this example `v` will have type
`Vec<i32>`. We'll cover [generics] in detail in a later chapter.
[arrays]: primitive-types.html#arrays
[vectors]: vectors.html
[heap]: the-stack-and-the-heap.html#the-heap
[stack]: the-stack-and-the-heap.html#the-stack
[bindings]: variable-bindings.html
[generics]: generics.html
# Move semantics
Theres some more subtlety here, though: Rust ensures that there is _exactly
one_ binding to any given resource. For example, if we have a vector, we can
assign it to another binding:
```rust
let v = vec![1, 2, 3];
let v2 = v;
```
But, if we try to use `v` afterwards, we get an error:
```rust,ignore
let v = vec![1, 2, 3];
let v2 = v;
println!("v[0] is: {}", v[0]);
```
It looks like this:
```text
error: use of moved value: `v`
println!("v[0] is: {}", v[0]);
^
```
A similar thing happens if we define a function which takes ownership, and
try to use something after weve passed it as an argument:
```rust,ignore
fn take(v: Vec<i32>) {
// What happens here isnt important.
}
let v = vec![1, 2, 3];
take(v);
println!("v[0] is: {}", v[0]);
```
Same error: use of moved value. When we transfer ownership to something else,
we say that weve moved the thing we refer to. You dont need some sort of
special annotation here, its the default thing that Rust does.
## The details
The reason that we cannot use a binding after weve moved it is subtle, but
important.
When we write code like this:
```rust
let x = 10;
```
Rust allocates memory for an integer [i32] on the [stack][sh], copies the bit
pattern representing the value of 10 to the allocated memory and binds the
variable name x to this memory region for future reference.
[i32]: primitive-types.html#numeric-types
Now consider the following code fragment:
```rust
let v = vec![1, 2, 3];
let mut v2 = v;
```
The first line allocates memory for the vector object `v` on the stack like
it does for `x` above. But in addition to that it also allocates some memory
on the [heap][sh] for the actual data (`[1, 2, 3]`). Rust copies the address
of this heap allocation to an internal pointer, which is part of the vector
object placed on the stack (let's call it the data pointer).
It is worth pointing out (even at the risk of stating the obvious) that the
vector object and its data live in separate memory regions instead of being a
single contiguous memory allocation (due to reasons we will not go into at
this point of time). These two parts of the vector (the one on the stack and
one on the heap) must agree with each other at all times with regards to
things like the length, capacity, etc.
When we move `v` to `v2`, Rust actually does a bitwise copy of the vector
object `v` into the stack allocation represented by `v2`. This shallow copy
does not create a copy of the heap allocation containing the actual data.
Which means that there would be two pointers to the contents of the vector
both pointing to the same memory allocation on the heap. It would violate
Rusts safety guarantees by introducing a data race if one could access both
`v` and `v2` at the same time.
For example if we truncated the vector to just two elements through `v2`:
```rust
# let v = vec![1, 2, 3];
# let mut v2 = v;
v2.truncate(2);
```
and `v` were still accessible we'd end up with an invalid vector since `v`
would not know that the heap data has been truncated. Now, the part of the
vector `v` on the stack does not agree with the corresponding part on the
heap. `v` still thinks there are three elements in the vector and will
happily let us access the non existent element `v[2]` but as you might
already know this is a recipe for disaster. Especially because it might lead
to a segmentation fault or worse allow an unauthorized user to read from
memory to which they don't have access.
This is why Rust forbids using `v` after weve done the move.
[sh]: the-stack-and-the-heap.html
Its also important to note that optimizations may remove the actual copy of
the bytes on the stack, depending on circumstances. So it may not be as
inefficient as it initially seems.
## `Copy` types
Weve established that when ownership is transferred to another binding, you
cannot use the original binding. However, theres a [trait][traits] that changes this
behavior, and its called `Copy`. We havent discussed traits yet, but for now,
you can think of them as an annotation to a particular type that adds extra
behavior. For example:
```rust
let v = 1;
let v2 = v;
println!("v is: {}", v);
```
In this case, `v` is an `i32`, which implements the `Copy` trait. This means
that, just like a move, when we assign `v` to `v2`, a copy of the data is made.
But, unlike a move, we can still use `v` afterward. This is because an `i32`
has no pointers to data somewhere else, copying it is a full copy.
All primitive types implement the `Copy` trait and their ownership is
therefore not moved like one would assume, following the ownership rules.
To give an example, the two following snippets of code only compile because the
`i32` and `bool` types implement the `Copy` trait.
```rust
fn main() {
let a = 5;
let _y = double(a);
println!("{}", a);
}
fn double(x: i32) -> i32 {
x * 2
}
```
```rust
fn main() {
let a = true;
let _y = change_truth(a);
println!("{}", a);
}
fn change_truth(x: bool) -> bool {
!x
}
```
If we had used types that do not implement the `Copy` trait,
we would have gotten a compile error because we tried to use a moved value.
```text
error: use of moved value: `a`
println!("{}", a);
^
```
We will discuss how to make your own types `Copy` in the [traits][traits]
section.
[traits]: traits.html
# More than ownership
Of course, if we had to hand ownership back with every function we wrote:
```rust
fn foo(v: Vec<i32>) -> Vec<i32> {
// Do stuff with `v`.
// Hand back ownership.
v
}
```
This would get very tedious. It gets worse the more things we want to take ownership of:
```rust
fn foo(v1: Vec<i32>, v2: Vec<i32>) -> (Vec<i32>, Vec<i32>, i32) {
// Do stuff with `v1` and `v2`.
// Hand back ownership, and the result of our function.
(v1, v2, 42)
}
let v1 = vec![1, 2, 3];
let v2 = vec![1, 2, 3];
let (v1, v2, answer) = foo(v1, v2);
```
Ugh! The return type, return line, and calling the function gets way more
complicated.
Luckily, Rust offers a feature which helps us solve this problem.
Its called borrowing and is the topic of the next section!
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/ownership.html).

View File

@ -1,411 +1,10 @@
# Patterns
Patterns are quite common in Rust. We use them in [variable
bindings][bindings], [match expressions][match], and other places, too. Lets go
on a whirlwind tour of all of the things patterns can do!
The first edition of the book is no longer distributed with Rust's documentation.
[bindings]: variable-bindings.html
[match]: match.html
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
A quick refresher: you can match against literals directly, and `_` acts as an
any case:
```rust
let x = 1;
match x {
1 => println!("one"),
2 => println!("two"),
3 => println!("three"),
_ => println!("anything"),
}
```
This prints `one`.
It's possible to create a binding for the value in the any case:
```rust
let x = 1;
match x {
y => println!("x: {} y: {}", x, y),
}
```
This prints:
```text
x: 1 y: 1
```
Note it is an error to have both a catch-all `_` and a catch-all binding in the same match block:
```rust
let x = 1;
match x {
y => println!("x: {} y: {}", x, y),
_ => println!("anything"), // this causes an error as it is unreachable
}
```
Theres one pitfall with patterns: like anything that introduces a new binding,
they introduce shadowing. For example:
```rust
let x = 1;
let c = 'c';
match c {
x => println!("x: {} c: {}", x, c),
}
println!("x: {}", x)
```
This prints:
```text
x: c c: c
x: 1
```
In other words, `x =>` matches the pattern and introduces a new binding named
`x`. This new binding is in scope for the match arm and takes on the value of
`c`. Notice that the value of `x` outside the scope of the match has no bearing
on the value of `x` within it. Because we already have a binding named `x`, this
new `x` shadows it.
# Multiple patterns
You can match multiple patterns with `|`:
```rust
let x = 1;
match x {
1 | 2 => println!("one or two"),
3 => println!("three"),
_ => println!("anything"),
}
```
This prints `one or two`.
# Destructuring
If you have a compound data type, like a [`struct`][struct], you can destructure it
inside of a pattern:
```rust
struct Point {
x: i32,
y: i32,
}
let origin = Point { x: 0, y: 0 };
match origin {
Point { x, y } => println!("({},{})", x, y),
}
```
[struct]: structs.html
We can use `:` to give a value a different name.
```rust
struct Point {
x: i32,
y: i32,
}
let origin = Point { x: 0, y: 0 };
match origin {
Point { x: x1, y: y1 } => println!("({},{})", x1, y1),
}
```
If we only care about some of the values, we dont have to give them all names:
```rust
struct Point {
x: i32,
y: i32,
}
let point = Point { x: 2, y: 3 };
match point {
Point { x, .. } => println!("x is {}", x),
}
```
This prints `x is 2`.
You can do this kind of match on any member, not only the first:
```rust
struct Point {
x: i32,
y: i32,
}
let point = Point { x: 2, y: 3 };
match point {
Point { y, .. } => println!("y is {}", y),
}
```
This prints `y is 3`.
This destructuring behavior works on any compound data type, like
[tuples][tuples] or [enums][enums].
[tuples]: primitive-types.html#tuples
[enums]: enums.html
# Ignoring bindings
You can use `_` in a pattern to disregard the type and value.
For example, heres a `match` against a `Result<T, E>`:
```rust
# let some_value: Result<i32, &'static str> = Err("There was an error");
match some_value {
Ok(value) => println!("got a value: {}", value),
Err(_) => println!("an error occurred"),
}
```
In the first arm, we bind the value inside the `Ok` variant to `value`. But
in the `Err` arm, we use `_` to disregard the specific error, and print
a general error message.
`_` is valid in any pattern that creates a binding. This can be useful to
ignore parts of a larger structure:
```rust
fn coordinate() -> (i32, i32, i32) {
// Generate and return some sort of triple tuple.
# (1, 2, 3)
}
let (x, _, z) = coordinate();
```
Here, we bind the first and last element of the tuple to `x` and `z`, but
ignore the middle element.
Its worth noting that using `_` never binds the value in the first place,
which means that the value does not move:
```rust
let tuple: (u32, String) = (5, String::from("five"));
// Here, tuple is moved, because the String moved:
let (x, _s) = tuple;
// The next line would give "error: use of partially moved value: `tuple`".
// println!("Tuple is: {:?}", tuple);
// However,
let tuple = (5, String::from("five"));
// Here, tuple is _not_ moved, as the String was never moved, and u32 is Copy:
let (x, _) = tuple;
// That means this works:
println!("Tuple is: {:?}", tuple);
```
This also means that any temporary variables will be dropped at the end of the
statement:
```rust
// Here, the String created will be dropped immediately, as its not bound:
let _ = String::from(" hello ").trim();
```
You can also use `..` in a pattern to disregard multiple values:
```rust
enum OptionalTuple {
Value(i32, i32, i32),
Missing,
}
let x = OptionalTuple::Value(5, -2, 3);
match x {
OptionalTuple::Value(..) => println!("Got a tuple!"),
OptionalTuple::Missing => println!("No such luck."),
}
```
This prints `Got a tuple!`.
# ref and ref mut
If you want to get a [reference][ref], use the `ref` keyword:
```rust
let x = 5;
match x {
ref r => println!("Got a reference to {}", r),
}
```
This prints `Got a reference to 5`.
[ref]: references-and-borrowing.html
Here, the `r` inside the `match` has the type `&i32`. In other words, the `ref`
keyword _creates_ a reference, for use in the pattern. If you need a mutable
reference, `ref mut` will work in the same way:
```rust
let mut x = 5;
match x {
ref mut mr => println!("Got a mutable reference to {}", mr),
}
```
# Ranges
You can match a range of values with `...`:
```rust
let x = 1;
match x {
1 ... 5 => println!("one through five"),
_ => println!("anything"),
}
```
This prints `one through five`.
Ranges are mostly used with integers and `char`s:
```rust
let x = '💅';
match x {
'a' ... 'j' => println!("early letter"),
'k' ... 'z' => println!("late letter"),
_ => println!("something else"),
}
```
This prints `something else`.
# Bindings
You can bind values to names with `@`:
```rust
let x = 1;
match x {
e @ 1 ... 5 => println!("got a range element {}", e),
_ => println!("anything"),
}
```
This prints `got a range element 1`. This is useful when you want to
do a complicated match of part of a data structure:
```rust
#[derive(Debug)]
struct Person {
name: Option<String>,
}
let name = "Steve".to_string();
let x: Option<Person> = Some(Person { name: Some(name) });
match x {
Some(Person { name: ref a @ Some(_), .. }) => println!("{:?}", a),
_ => {}
}
```
This prints `Some("Steve")`: weve bound the inner `name` to `a`.
If you use `@` with `|`, you need to make sure the name is bound in each part
of the pattern:
```rust
let x = 5;
match x {
e @ 1 ... 5 | e @ 8 ... 10 => println!("got a range element {}", e),
_ => println!("anything"),
}
```
# Guards
You can introduce match guards with `if`:
```rust
enum OptionalInt {
Value(i32),
Missing,
}
let x = OptionalInt::Value(5);
match x {
OptionalInt::Value(i) if i > 5 => println!("Got an int bigger than five!"),
OptionalInt::Value(..) => println!("Got an int!"),
OptionalInt::Missing => println!("No such luck."),
}
```
This prints `Got an int!`.
If youre using `if` with multiple patterns, the `if` applies to both sides:
```rust
let x = 4;
let y = false;
match x {
4 | 5 if y => println!("yes"),
_ => println!("no"),
}
```
This prints `no`, because the `if` applies to the whole of `4 | 5`, and not to
only the `5`. In other words, the precedence of `if` behaves like this:
```text
(4 | 5) if y => ...
```
not this:
```text
4 | (5 if y) => ...
```
# Mix and Match
Whew! Thats a lot of different ways to match things, and they can all be
mixed and matched, depending on what youre doing:
```rust,ignore
match x {
Foo { x: Some(ref name), y: None } => ...
}
```
Patterns are very powerful. Make good use of them.
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/patterns.html).

View File

@ -1,305 +1,10 @@
# Primitive Types
The Rust language has a number of types that are considered primitive. This
means that theyre built-in to the language. Rust is structured in such a way
that the standard library also provides a number of useful types built on top
of these ones, as well, but these are the most primitive.
The first edition of the book is no longer distributed with Rust's documentation.
# Booleans
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
Rust has a built-in boolean type, named `bool`. It has two values, `true` and `false`:
```rust
let x = true;
let y: bool = false;
```
A common use of booleans is in [`if` conditionals][if].
[if]: if.html
You can find more documentation for `bool`s [in the standard library
documentation][bool].
[bool]: ../../std/primitive.bool.html
# `char`
The `char` type represents a single Unicode scalar value. You can create `char`s
with a single tick: (`'`)
```rust
let x = 'x';
let two_hearts = '💕';
```
Unlike some other languages, this means that Rusts `char` is not a single byte,
but four.
You can find more documentation for `char`s [in the standard library
documentation][char].
[char]: ../../std/primitive.char.html
# Numeric types
Rust has a variety of numeric types in a few categories: signed and unsigned,
fixed and variable, floating-point and integer.
These types consist of two parts: the category, and the size. For example,
`u16` is an unsigned type with sixteen bits of size. More bits lets you have
bigger numbers.
If a number literal has nothing to cause its type to be inferred, it defaults:
```rust
let x = 42; // `x` has type `i32`.
let y = 1.0; // `y` has type `f64`.
```
Heres a list of the different numeric types, with links to their documentation
in the standard library:
* [i8](../../std/primitive.i8.html)
* [i16](../../std/primitive.i16.html)
* [i32](../../std/primitive.i32.html)
* [i64](../../std/primitive.i64.html)
* [u8](../../std/primitive.u8.html)
* [u16](../../std/primitive.u16.html)
* [u32](../../std/primitive.u32.html)
* [u64](../../std/primitive.u64.html)
* [isize](../../std/primitive.isize.html)
* [usize](../../std/primitive.usize.html)
* [f32](../../std/primitive.f32.html)
* [f64](../../std/primitive.f64.html)
Lets go over them by category:
## Signed and Unsigned
Integer types come in two varieties: signed and unsigned. To understand the
difference, lets consider a number with four bits of size. A signed, four-bit
number would let you store numbers from `-8` to `+7`. Signed numbers use
“twos complement representation”. An unsigned four bit number, since it does
not need to store negatives, can store values from `0` to `+15`.
Unsigned types use a `u` for their category, and signed types use `i`. The `i`
is for integer. So `u8` is an eight-bit unsigned number, and `i8` is an
eight-bit signed number.
## Fixed-size types
Fixed-size types have a specific number of bits in their representation. Valid
bit sizes are `8`, `16`, `32`, and `64`. So, `u32` is an unsigned, 32-bit integer,
and `i64` is a signed, 64-bit integer.
## Variable-size types
Rust also provides types whose particular size depends on the underlying machine
architecture. Their range is sufficient to express the size of any collection, so
these types have size as the category. They come in signed and unsigned varieties
which account for two types: `isize` and `usize`.
## Floating-point types
Rust also has two floating point types: `f32` and `f64`. These correspond to
IEEE-754 single and double precision numbers.
# 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]; // m: [i32; 3]
```
Arrays have type `[T; N]`. Well talk about this `T` notation [in the generics
section][generics]. The `N` is a compile-time constant, for the length of the
array.
Theres 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]
```
You can get the number of elements in an array `a` with `a.len()`:
```rust
let a = [1, 2, 3];
println!("a has {} elements", a.len());
```
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.
You can find more documentation for `array`s [in the standard library
documentation][array].
[array]: ../../std/primitive.array.html
# Slices
A slice is a reference to (or “view” into) another data structure. They are
useful for allowing safe, efficient access to a portion of an array without
copying. For example, you might want to reference only one line of a file read
into memory. By nature, a slice is not created directly, but from an existing
variable binding. Slices have a defined length, and can be mutable or immutable.
Internally, slices are represented as a pointer to the beginning of the data
and a length.
## Slicing syntax
You can use a combo of `&` and `[]` to create a slice from various things. The
`&` indicates that slices are similar to [references], which we will cover in
detail later in this section. The `[]`s, with a range, let you define the
length of the slice:
```rust
let a = [0, 1, 2, 3, 4];
let complete = &a[..]; // A slice containing all of the elements in `a`.
let middle = &a[1..4]; // A slice of `a`: only the elements `1`, `2`, and `3`.
```
Slices have type `&[T]`. Well talk about that `T` when we cover
[generics][generics].
[generics]: generics.html
You can find more documentation for slices [in the standard library
documentation][slice].
[slice]: ../../std/primitive.slice.html
# `str`
Rusts `str` type is the most primitive string type. As an [unsized type][dst],
its not very useful by itself, but becomes useful when placed behind a
reference, like `&str`. We'll elaborate further when we cover
[Strings][strings] and [references].
[dst]: unsized-types.html
[strings]: strings.html
[references]: references-and-borrowing.html
You can find more documentation for `str` [in the standard library
documentation][str].
[str]: ../../std/primitive.str.html
# Tuples
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. Heres 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 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.
In systems programming languages, strings are a bit more complex than in other
languages. For now, read `&str` as a *string slice*, and well learn more
soon.
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.
[arity]: glossary.html#arity
```rust
let mut x = (1, 2); // x: (i32, i32)
let y = (2, 3); // y: (i32, i32)
x = y;
```
You can access the fields in a tuple through a *destructuring let*. Heres
an example:
```rust
let (x, y, z) = (1, 2, 3);
println!("x is {}", x);
```
Remember [before][let] when I said the left-hand side of a `let` statement was more
powerful than 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.
[let]: variable-bindings.html
This pattern is very powerful, and well see it repeated more later.
You can disambiguate a single-element tuple from a value in parentheses with a
comma:
```rust
(0,); // A single-element tuple.
(0); // A zero in parentheses.
```
## Tuple Indexing
You can also access fields of a tuple with indexing syntax:
```rust
let tuple = (1, 2, 3);
let x = tuple.0;
let y = tuple.1;
let z = tuple.2;
println!("x is {}", x);
```
Like array indexing, it starts at zero, but unlike array indexing, it uses a
`.`, rather than `[]`s.
You can find more documentation for tuples [in the standard library
documentation][tuple].
[tuple]: ../../std/primitive.tuple.html
# Functions
Functions also have a type! They look like this:
```rust
fn foo(x: i32) -> i32 { x }
let x: fn(i32) -> i32 = foo;
```
In this case, `x` is a function pointer to a function that takes an `i32` and
returns an `i32`.
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/primitive-types.html).

View File

@ -1,286 +1,10 @@
# Procedural Macros (and custom Derive)
As you've seen throughout the rest of the book, Rust provides a mechanism
called "derive" that lets you implement traits easily. For example,
The first edition of the book is no longer distributed with Rust's documentation.
```rust
#[derive(Debug)]
struct Point {
x: i32,
y: i32,
}
```
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
is a lot simpler than
```rust
struct Point {
x: i32,
y: i32,
}
use std::fmt;
impl fmt::Debug for Point {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Point {{ x: {}, y: {} }}", self.x, self.y)
}
}
```
Rust includes several traits that you can derive, but it also lets you define
your own. We can accomplish this task through a feature of Rust called
"procedural macros." Eventually, procedural macros will allow for all sorts of
advanced metaprogramming in Rust, but today, they're only for custom derive.
Let's build a very simple trait, and derive it with custom derive.
## Hello World
So the first thing we need to do is start a new crate for our project.
```bash
$ cargo new --bin hello-world
```
All we want is to be able to call `hello_world()` on a derived type. Something
like this:
```rust,ignore
#[derive(HelloWorld)]
struct Pancakes;
fn main() {
Pancakes::hello_world();
}
```
With some kind of nice output, like `Hello, World! My name is Pancakes.`.
Let's go ahead and write up what we think our macro will look like from a user
perspective. In `src/main.rs` we write:
```rust,ignore
#[macro_use]
extern crate hello_world_derive;
trait HelloWorld {
fn hello_world();
}
#[derive(HelloWorld)]
struct FrenchToast;
#[derive(HelloWorld)]
struct Waffles;
fn main() {
FrenchToast::hello_world();
Waffles::hello_world();
}
```
Great. So now we just need to actually write the procedural macro. At the
moment, procedural macros need to be in their own crate. Eventually, this
restriction may be lifted, but for now, it's required. As such, there's a
convention; for a crate named `foo`, a custom derive procedural macro is called
`foo-derive`. Let's start a new crate called `hello-world-derive` inside our
`hello-world` project.
```bash
$ cargo new hello-world-derive
```
To make sure that our `hello-world` crate is able to find this new crate we've
created, we'll add it to our toml:
```toml
[dependencies]
hello-world-derive = { path = "hello-world-derive" }
```
As for the source of our `hello-world-derive` crate, here's an example:
```rust,ignore
extern crate proc_macro;
extern crate syn;
#[macro_use]
extern crate quote;
use proc_macro::TokenStream;
#[proc_macro_derive(HelloWorld)]
pub fn hello_world(input: TokenStream) -> TokenStream {
// Construct a string representation of the type definition
let s = input.to_string();
// Parse the string representation
let ast = syn::parse_derive_input(&s).unwrap();
// Build the impl
let gen = impl_hello_world(&ast);
// Return the generated impl
gen.parse().unwrap()
}
```
So there is a lot going on here. We have introduced two new crates: [`syn`] and
[`quote`]. As you may have noticed, `input: TokenSteam` is immediately converted
to a `String`. This `String` is a string representation of the Rust code for which
we are deriving `HelloWorld`. At the moment, the only thing you can do with a
`TokenStream` is convert it to a string. A richer API will exist in the future.
So what we really need is to be able to _parse_ Rust code into something
usable. This is where `syn` comes to play. `syn` is a crate for parsing Rust
code. The other crate we've introduced is `quote`. It's essentially the dual of
`syn` as it will make generating Rust code really easy. We could write this
stuff on our own, but it's much simpler to use these libraries. Writing a full
parser for Rust code is no simple task.
[`syn`]: https://crates.io/crates/syn
[`quote`]: https://crates.io/crates/quote
The comments seem to give us a pretty good idea of our overall strategy. We
are going to take a `String` of the Rust code for the type we are deriving, parse
it using `syn`, construct the implementation of `hello_world` (using `quote`),
then pass it back to Rust compiler.
One last note: you'll see some `unwrap()`s there. If you want to provide an
error for a procedural macro, then you should `panic!` with the error message.
In this case, we're keeping it as simple as possible.
Great, so let's write `impl_hello_world(&ast)`.
```rust,ignore
fn impl_hello_world(ast: &syn::DeriveInput) -> quote::Tokens {
let name = &ast.ident;
quote! {
impl HelloWorld for #name {
fn hello_world() {
println!("Hello, World! My name is {}", stringify!(#name));
}
}
}
}
```
So this is where quotes comes in. The `ast` argument is a struct that gives us
a representation of our type (which can be either a `struct` or an `enum`).
Check out the [docs](https://docs.rs/syn/0.11.11/syn/struct.DeriveInput.html),
there is some useful information there. We are able to get the name of the
type using `ast.ident`. The `quote!` macro lets us write up the Rust code
that we wish to return and convert it into `Tokens`. `quote!` lets us use some
really cool templating mechanics; we simply write `#name` and `quote!` will
replace it with the variable named `name`. You can even do some repetition
similar to regular macros work. You should check out the
[docs](https://docs.rs/quote) for a good introduction.
So I think that's it. Oh, well, we do need to add dependencies for `syn` and
`quote` in the `Cargo.toml` for `hello-world-derive`.
```toml
[dependencies]
syn = "0.11.11"
quote = "0.3.15"
```
That should be it. Let's try to compile `hello-world`.
```bash
error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type
--> hello-world-derive/src/lib.rs:8:3
|
8 | #[proc_macro_derive(HelloWorld)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```
Oh, so it appears that we need to declare that our `hello-world-derive` crate is
a `proc-macro` crate type. How do we do this? Like this:
```toml
[lib]
proc-macro = true
```
Ok so now, let's compile `hello-world`. Executing `cargo run` now yields:
```bash
Hello, World! My name is FrenchToast
Hello, World! My name is Waffles
```
We've done it!
## Custom Attributes
In some cases it might make sense to allow users some kind of configuration.
For example, the user might want to overwrite the name that is printed in the `hello_world()` method.
This can be achieved with custom attributes:
```rust,ignore
#[derive(HelloWorld)]
#[HelloWorldName = "the best Pancakes"]
struct Pancakes;
fn main() {
Pancakes::hello_world();
}
```
If we try to compile this though, the compiler will respond with an error:
```bash
error: The attribute `HelloWorldName` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
```
The compiler needs to know that we're handling this attribute and to not respond with an error.
This is done in the `hello-world-derive` crate by adding `attributes` to the `proc_macro_derive` attribute:
```rust,ignore
#[proc_macro_derive(HelloWorld, attributes(HelloWorldName))]
pub fn hello_world(input: TokenStream) -> TokenStream
```
Multiple attributes can be specified that way.
## Raising Errors
Let's assume that we do not want to accept enums as input to our custom derive method.
This condition can be easily checked with the help of `syn`.
But how do we tell the user, that we do not accept enums?
The idiomatic way to report errors in procedural macros is to panic:
```rust,ignore
fn impl_hello_world(ast: &syn::DeriveInput) -> quote::Tokens {
let name = &ast.ident;
// Check if derive(HelloWorld) was specified for a struct
if let syn::Body::Struct(_) = ast.body {
// Yes, this is a struct
quote! {
impl HelloWorld for #name {
fn hello_world() {
println!("Hello, World! My name is {}", stringify!(#name));
}
}
}
} else {
// Nope. This is an Enum. We cannot handle these!
panic!("#[derive(HelloWorld)] is only defined for structs, not for enums!");
}
}
```
If a user now tries to derive `HelloWorld` from an enum they will be greeted with following, hopefully helpful, error:
```bash
error: custom derive attribute panicked
--> src/main.rs
|
| #[derive(HelloWorld)]
| ^^^^^^^^^^
|
= help: message: #[derive(HelloWorld)] is only defined for structs, not for enums!
```
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/procedural-macros.html).

View File

@ -1,121 +1,10 @@
# Raw Pointers
Rust has a number of different smart pointer types in its standard library, but
there are two types that are extra-special. Much of Rusts safety comes from
compile-time checks, but raw pointers dont have such guarantees, and are
[unsafe][unsafe] to use.
The first edition of the book is no longer distributed with Rust's documentation.
`*const T` and `*mut T` are called raw pointers in Rust. Sometimes, when
writing certain kinds of libraries, youll need to get around Rusts safety
guarantees for some reason. In this case, you can use raw pointers to implement
your library, while exposing a safe interface for your users. For example, `*`
pointers are allowed to alias, allowing them to be used to write
shared-ownership types, and even thread-safe shared memory types (the `Rc<T>`
and `Arc<T>` types are both implemented entirely in Rust).
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
Here are some things to remember about raw pointers that are different than
other pointer types. They:
- are not guaranteed to point to valid memory and are not even
guaranteed to be non-NULL (unlike both `Box` and `&`);
- do not have any automatic clean-up, unlike `Box`, and so require
manual resource management;
- are plain-old-data, that is, they don't move ownership, again unlike
`Box`, hence the Rust compiler cannot protect against bugs like
use-after-free;
- lack any form of lifetimes, unlike `&`, and so the compiler cannot
reason about dangling pointers; and
- have no guarantees about aliasing or mutability other than mutation
not being allowed directly through a `*const T`.
# Basics
Creating a raw pointer is perfectly safe:
```rust
let x = 5;
let raw = &x as *const i32;
let mut y = 10;
let raw_mut = &mut y as *mut i32;
```
However, dereferencing one is not. This wont work:
```rust,ignore
let x = 5;
let raw = &x as *const i32;
println!("raw points at {}", *raw);
```
It gives this error:
```text
error: dereference of raw pointer requires unsafe function or block [E0133]
println!("raw points at {}", *raw);
^~~~
```
When you dereference a raw pointer, youre taking responsibility that its not
pointing somewhere that would be incorrect. As such, you need `unsafe`:
```rust
let x = 5;
let raw = &x as *const i32;
let points_at = unsafe { *raw };
println!("raw points at {}", points_at);
```
For more operations on raw pointers, see [their API documentation][rawapi].
[unsafe]: unsafe.html
[rawapi]: ../../std/primitive.pointer.html
# FFI
Raw pointers are useful for FFI: Rusts `*const T` and `*mut T` are similar to
Cs `const T*` and `T*`, respectively. For more about this use, consult the
[FFI chapter][ffi].
[ffi]: ffi.html
# References and raw pointers
At runtime, a raw pointer `*` and a reference pointing to the same piece of
data have an identical representation. In fact, an `&T` reference will
implicitly coerce to an `*const T` raw pointer in safe code and similarly for
the `mut` variants (both coercions can be performed explicitly with,
respectively, `value as *const T` and `value as *mut T`).
Going the opposite direction, from `*const` to a reference `&`, is not safe. A
`&T` is always valid, and so, at a minimum, the raw pointer `*const T` has to
point to a valid instance of type `T`. Furthermore, the resulting pointer must
satisfy the aliasing and mutability laws of references. The compiler assumes
these properties are true for any references, no matter how they are created,
and so any conversion from raw pointers is asserting that they hold. The
programmer *must* guarantee this.
The recommended method for the conversion is:
```rust
// Explicit cast:
let i: u32 = 1;
let p_imm: *const u32 = &i as *const u32;
// Implicit coercion:
let mut m: u32 = 2;
let p_mut: *mut u32 = &mut m;
unsafe {
let ref_imm: &u32 = &*p_imm;
let ref_mut: &mut u32 = &mut *p_mut;
}
```
The `&*x` dereferencing style is preferred to using a `transmute`. The latter
is far more powerful than necessary, and the more restricted operation is
harder to use incorrectly; for example, it requires that `x` is a pointer
(unlike `transmute`).
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/raw-pointers.html).

View File

@ -1,411 +1,10 @@
# References and Borrowing
This is the second of three sections presenting Rusts ownership system. This is one of
Rusts most distinct and compelling features, with which Rust developers should
become quite acquainted. Ownership is how Rust achieves its largest goal,
memory safety. There are a few distinct concepts, each with its own
chapter:
The first edition of the book is no longer distributed with Rust's documentation.
* [ownership][ownership], the key concept
* borrowing, which youre reading now
* [lifetimes][lifetimes], an advanced concept of borrowing
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
These three chapters are related, and in order. Youll need all three to fully
understand the ownership system.
[ownership]: ownership.html
[lifetimes]: lifetimes.html
# Meta
Before we get to the details, two important notes about the ownership system.
Rust has a focus on safety and speed. It accomplishes these goals through many
zero-cost abstractions, which means that in Rust, abstractions cost as little
as possible in order to make them work. The ownership system is a prime example
of a zero-cost abstraction. All of the analysis well talk about in this guide
is _done at compile time_. You do not pay any run-time cost for any of these
features.
However, this system does have a certain cost: learning curve. Many new users
to Rust experience something we like to call fighting with the borrow
checker, where the Rust compiler refuses to compile a program that the author
thinks is valid. This often happens because the programmers mental model of
how ownership should work doesnt match the actual rules that Rust implements.
You probably will experience similar things at first. There is good news,
however: more experienced Rust developers report that once they work with the
rules of the ownership system for a period of time, they fight the borrow
checker less and less.
With that in mind, lets learn about borrowing.
# Borrowing
At the end of the [ownership][ownership] section, we had a nasty function that looked
like this:
```rust
fn foo(v1: Vec<i32>, v2: Vec<i32>) -> (Vec<i32>, Vec<i32>, i32) {
// Do stuff with `v1` and `v2`.
// Hand back ownership, and the result of our function.
(v1, v2, 42)
}
let v1 = vec![1, 2, 3];
let v2 = vec![1, 2, 3];
let (v1, v2, answer) = foo(v1, v2);
```
This is not idiomatic Rust, however, as it doesnt take advantage of borrowing. Heres
the first step:
```rust
fn foo(v1: &Vec<i32>, v2: &Vec<i32>) -> i32 {
// Do stuff with `v1` and `v2`.
// Return the answer.
42
}
let v1 = vec![1, 2, 3];
let v2 = vec![1, 2, 3];
let answer = foo(&v1, &v2);
// We can use `v1` and `v2` here!
```
A more concrete example:
```rust
fn main() {
// Don't worry if you don't understand how `fold` works, the point here is that an immutable reference is borrowed.
fn sum_vec(v: &Vec<i32>) -> i32 {
v.iter().fold(0, |a, &b| a + b)
}
// Borrow two vectors and sum them.
// This kind of borrowing does not allow mutation through the borrowed reference.
fn foo(v1: &Vec<i32>, v2: &Vec<i32>) -> i32 {
// Do stuff with `v1` and `v2`.
let s1 = sum_vec(v1);
let s2 = sum_vec(v2);
// Return the answer.
s1 + s2
}
let v1 = vec![1, 2, 3];
let v2 = vec![4, 5, 6];
let answer = foo(&v1, &v2);
println!("{}", answer);
}
```
Instead of taking `Vec<i32>`s as our arguments, we take a reference:
`&Vec<i32>`. And instead of passing `v1` and `v2` directly, we pass `&v1` and
`&v2`. We call the `&T` type a reference, and rather than owning the resource,
it borrows ownership. A binding that borrows something does not deallocate the
resource when it goes out of scope. This means that after the call to `foo()`,
we can use our original bindings again.
References are immutable, like bindings. This means that inside of `foo()`,
the vectors cant be changed at all:
```rust,ignore
fn foo(v: &Vec<i32>) {
v.push(5);
}
let v = vec![];
foo(&v);
```
will give us this error:
```text
error: cannot borrow immutable borrowed content `*v` as mutable
v.push(5);
^
```
Pushing a value mutates the vector, and so we arent allowed to do it.
# &mut references
Theres a second kind of reference: `&mut T`. A mutable reference allows you
to mutate the resource youre borrowing. For example:
```rust
let mut x = 5;
{
let y = &mut x;
*y += 1;
}
println!("{}", x);
```
This will print `6`. We make `y` a mutable reference to `x`, then add one to
the thing `y` points at. Youll notice that `x` had to be marked `mut` as well.
If it wasnt, we couldnt take a mutable borrow to an immutable value.
You'll also notice we added an asterisk (`*`) in front of `y`, making it `*y`,
this is because `y` is a `&mut` reference. You'll need to use asterisks to
access the contents of a reference as well.
Otherwise, `&mut` references are like references. There _is_ a large
difference between the two, and how they interact, though. You can tell
something is fishy in the above example, because we need that extra scope, with
the `{` and `}`. If we remove them, we get an error:
```text
error: cannot borrow `x` as immutable because it is also borrowed as mutable
println!("{}", x);
^
note: previous borrow of `x` occurs here; the mutable borrow prevents
subsequent moves, borrows, or modification of `x` until the borrow ends
let y = &mut x;
^
note: previous borrow ends here
fn main() {
}
^
```
As it turns out, there are rules.
# The Rules
Here are the rules for borrowing in Rust:
First, any borrow must last for a scope no greater than that of the owner.
Second, you may have one or the other of these two kinds of borrows, but not
both at the same time:
* one or more references (`&T`) to a resource,
* exactly one mutable reference (`&mut T`).
You may notice that this is very similar to, though not exactly the same as,
the definition of a data race:
> There is a data race when two or more pointers access the same memory
> location at the same time, where at least one of them is writing, and the
> operations are not synchronized.
With references, you may have as many as youd like, since none of them are
writing. However, as we can only have one `&mut` at a time, it is impossible to
have a data race. This is how Rust prevents data races at compile time: well
get errors if we break the rules.
With this in mind, lets consider our example again.
## Thinking in scopes
Heres the code:
```rust,ignore
fn main() {
let mut x = 5;
let y = &mut x;
*y += 1;
println!("{}", x);
}
```
This code gives us this error:
```text
error: cannot borrow `x` as immutable because it is also borrowed as mutable
println!("{}", x);
^
```
This is because weve violated the rules: we have a `&mut T` pointing to `x`,
and so we arent allowed to create any `&T`s. It's one or the other. The note
hints at how to think about this problem:
```text
note: previous borrow ends here
fn main() {
}
^
```
In other words, the mutable borrow is held through the rest of our example. What
we want is for the mutable borrow by `y` to end so that the resource can be
returned to the owner, `x`. `x` can then provide an immutable borrow to `println!`.
In Rust, borrowing is tied to the scope that the borrow is valid for. And our
scopes look like this:
```rust,ignore
fn main() {
let mut x = 5;
let y = &mut x; // -+ &mut borrow of `x` starts here.
// |
*y += 1; // |
// |
println!("{}", x); // -+ - Try to borrow `x` here.
} // -+ &mut borrow of `x` ends here.
```
The scopes conflict: we cant make an `&x` while `y` is in scope.
So when we add the curly braces:
```rust
let mut x = 5;
{
let y = &mut x; // -+ &mut borrow starts here.
*y += 1; // |
} // -+ ... and ends here.
println!("{}", x); // <- Try to borrow `x` here.
```
Theres no problem. Our mutable borrow goes out of scope before we create an
immutable one. So scope is the key to seeing how long a borrow lasts for.
## Issues borrowing prevents
Why have these restrictive rules? Well, as we noted, these rules prevent data
races. What kinds of issues do data races cause? Here are a few.
### Iterator invalidation
One example is iterator invalidation, which happens when you try to mutate a
collection that youre iterating over. Rusts borrow checker prevents this from
happening:
```rust
let mut v = vec![1, 2, 3];
for i in &v {
println!("{}", i);
}
```
This prints out one through three. As we iterate through the vector, were
only given references to the elements. And `v` is itself borrowed as immutable,
which means we cant change it while were iterating:
```rust,ignore
let mut v = vec![1, 2, 3];
for i in &v {
println!("{}", i);
v.push(34);
}
```
Heres the error:
```text
error: cannot borrow `v` as mutable because it is also borrowed as immutable
v.push(34);
^
note: previous borrow of `v` occurs here; the immutable borrow prevents
subsequent moves or mutable borrows of `v` until the borrow ends
for i in &v {
^
note: previous borrow ends here
for i in &v {
println!(“{}”, i);
v.push(34);
}
^
```
We cant modify `v` because its borrowed by the loop.
### Use after free
References must not live longer than the resource they refer to. Rust will
check the scopes of your references to ensure that this is true.
If Rust didnt check this property, we could accidentally use a reference
which was invalid. For example:
```rust,ignore
let y: &i32;
{
let x = 5;
y = &x;
}
println!("{}", y);
```
We get this error:
```text
error: `x` does not live long enough
y = &x;
^
note: reference must be valid for the block suffix following statement 0 at
2:16...
let y: &i32;
{
let x = 5;
y = &x;
}
note: ...but borrowed value is only valid for the block suffix following
statement 0 at 4:18
let x = 5;
y = &x;
}
```
In other words, `y` is only valid for the scope where `x` exists. As soon as
`x` goes away, it becomes invalid to refer to it. As such, the error says that
the borrow doesnt live long enough because its not valid for the right
amount of time.
The same problem occurs when the reference is declared _before_ the variable it
refers to. This is because resources within the same scope are freed in the
opposite order they were declared:
```rust,ignore
let y: &i32;
let x = 5;
y = &x;
println!("{}", y);
```
We get this error:
```text
error: `x` does not live long enough
y = &x;
^
note: reference must be valid for the block suffix following statement 0 at
2:16...
let y: &i32;
let x = 5;
y = &x;
println!("{}", y);
}
note: ...but borrowed value is only valid for the block suffix following
statement 1 at 3:14
let x = 5;
y = &x;
println!("{}", y);
}
```
In the above example, `y` is declared before `x`, meaning that `y` lives longer
than `x`, which is not allowed.
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/references-and-borrowing.html).

View File

@ -1,68 +1,10 @@
# Release Channels
The Rust project uses a concept called release channels to manage releases.
Its important to understand this process to choose which version of Rust
your project should use.
The first edition of the book is no longer distributed with Rust's documentation.
# Overview
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
There are three channels for Rust releases:
* Nightly
* Beta
* Stable
New nightly releases are created once a day. Every six weeks, the latest
nightly release is promoted to Beta. At that point, it will only receive
patches to fix serious errors. Six weeks later, the beta is promoted to
Stable, and becomes the next release of `1.x`.
This process happens in parallel. So every six weeks, on the same day,
nightly goes to beta, beta goes to stable. When `1.x` is released, at
the same time, `1.(x + 1)-beta` is released, and the nightly becomes the
first version of `1.(x + 2)-nightly`.
# Choosing a version
Generally speaking, unless you have a specific reason, you should be using the
stable release channel. These releases are intended for a general audience.
However, depending on your interest in Rust, you may choose to use nightly
instead. The basic trade-off is this: in the nightly channel, you can use
unstable, new Rust features. However, unstable features are subject to change,
and so any new nightly release may break your code. If you use the stable
release, you cannot use experimental features, but the next release of Rust
will not cause significant issues through breaking changes.
# Helping the ecosystem through CI
What about beta? We encourage all Rust users who use the stable release channel
to also test against the beta channel in their continuous integration systems.
This will help alert the team in case theres an accidental regression.
Additionally, testing against nightly can catch regressions even sooner, and so
if you dont mind a third build, wed appreciate testing against all channels.
As an example, many Rust programmers use [Travis](https://travis-ci.org/) to
test their crates, which is free for open source projects. Travis [supports
Rust directly][travis], and you can use a `.travis.yml` file like this to
test on all channels:
```yaml
language: rust
rust:
- nightly
- beta
- stable
matrix:
allow_failures:
- rust: nightly
```
[travis]: http://docs.travis-ci.com/user/languages/rust/
With this configuration, Travis will test all three channels, but if something
breaks on nightly, it wont fail your build. A similar configuration is
recommended for any CI system, check the documentation of the one youre
using for more details.
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/release-channels.html).

View File

@ -1,195 +1,10 @@
# Strings
Strings are an important concept for any programmer to master. Rusts string
handling system is a bit different from other languages, due to its systems
focus. Any time you have a data structure of variable size, things can get
tricky, and strings are a re-sizable data structure. That being said, Rusts
strings also work differently than in some other systems languages, such as C.
The first edition of the book is no longer distributed with Rust's documentation.
Lets dig into the details. A string is a sequence of Unicode scalar values
encoded as a stream of UTF-8 bytes. All strings are guaranteed to be a valid
encoding of UTF-8 sequences. Additionally, unlike some systems languages,
strings are not NUL-terminated and can contain NUL bytes.
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
Rust has two main types of strings: `&str` and `String`. Lets talk about
`&str` first. These are called string slices. A string slice has a fixed
size, and cannot be mutated. It is a reference to a sequence of UTF-8 bytes.
```rust
let greeting = "Hello there."; // greeting: &'static str
```
`"Hello there."` is a string literal and its type is `&'static str`. A string
literal is a string slice that is statically allocated, meaning that its saved
inside our compiled program, and exists for the entire duration it runs. The
`greeting` binding is a reference to this statically allocated string. Any
function expecting a string slice will also accept a string literal.
String literals can span multiple lines. There are two forms. The first will
include the newline and the leading spaces:
```rust
let s = "foo
bar";
assert_eq!("foo\n bar", s);
```
The second, with a `\`, trims the spaces and the newline:
```rust
let s = "foo\
bar";
assert_eq!("foobar", s);
```
Note that you normally cannot access a `str` directly, but only through a `&str`
reference. This is because `str` is an unsized type which requires additional
runtime information to be usable. For more information see the chapter on
[unsized types][ut].
Rust has more than only `&str`s though. 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.
```rust
let mut s = "Hello".to_string(); // mut s: String
println!("{}", s);
s.push_str(", world.");
println!("{}", s);
```
`String`s will coerce into `&str` with an `&`:
```rust
fn takes_slice(slice: &str) {
println!("Got: {}", slice);
}
fn main() {
let s = "Hello".to_string();
takes_slice(&s);
}
```
This coercion does not happen for functions that accept one of `&str`s traits
instead of `&str`. For example, [`TcpStream::connect`][connect] has a parameter
of type `ToSocketAddrs`. A `&str` is okay but a `String` must be explicitly
converted using `&*`.
```rust,no_run
use std::net::TcpStream;
TcpStream::connect("192.168.0.1:3000"); // Parameter is of type &str.
let addr_string = "192.168.0.1:3000".to_string();
TcpStream::connect(&*addr_string); // Convert `addr_string` to &str.
```
Viewing a `String` as a `&str` is cheap, but converting the `&str` to a
`String` involves allocating memory. No reason to do that unless you have to!
## Indexing
Because strings are valid UTF-8, they do not support indexing:
```rust,ignore
let s = "hello";
println!("The first letter of s is {}", s[0]); // ERROR!!!
```
Usually, access to a vector with `[]` is very fast. But, because each character
in a UTF-8 encoded string can be multiple bytes, you have to walk over the
string to find the nᵗʰ letter of a string. This is a significantly more
expensive operation, and we dont want to be misleading. Furthermore, letter
isnt something defined in Unicode, exactly. We can choose to look at a string as
individual bytes, or as codepoints:
```rust
let hachiko = "忠犬ハチ公";
for b in hachiko.as_bytes() {
print!("{}, ", b);
}
println!("");
for c in hachiko.chars() {
print!("{}, ", c);
}
println!("");
```
This prints:
```text
229, 191, 160, 231, 138, 172, 227, 131, 143, 227, 131, 129, 229, 133, 172,
忠, 犬, ハ, チ, 公,
```
As you can see, there are more bytes than `char`s.
You can get something similar to an index like this:
```rust
# let hachiko = "忠犬ハチ公";
let dog = hachiko.chars().nth(1); // Kinda like `hachiko[1]`.
```
This emphasizes that we have to walk from the beginning of the list of `chars`.
## Slicing
You can get a slice of a string with the slicing syntax:
```rust
let dog = "hachiko";
let hachi = &dog[0..5];
```
But note that these are _byte_ offsets, not _character_ offsets. So
this will fail at runtime:
```rust,should_panic
let dog = "忠犬ハチ公";
let hachi = &dog[0..2];
```
with this error:
```text
thread 'main' panicked at 'byte index 2 is not a char boundary; it is inside '忠'
(bytes 0..3) of `忠犬ハチ公`'
```
## Concatenation
If you have a `String`, you can concatenate a `&str` to the end of it:
```rust
let hello = "Hello ".to_string();
let world = "world!";
let hello_world = hello + world;
```
But if you have two `String`s, you need an `&`:
```rust
let hello = "Hello ".to_string();
let world = "world!".to_string();
let hello_world = hello + &world;
```
This is because `&String` can automatically coerce to a `&str`. This is a
feature called [`Deref` coercions][dc].
[ut]: unsized-types.html
[dc]: deref-coercions.html
[connect]: ../../std/net/struct.TcpStream.html#method.connect
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/strings.html).

View File

@ -1,279 +1,10 @@
# Structs
`struct`s are a way of creating more complex data types. For example, if we were
doing calculations involving coordinates in 2D space, we would need both an `x`
and a `y` value:
The first edition of the book is no longer distributed with Rust's documentation.
```rust
let origin_x = 0;
let origin_y = 0;
```
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
A `struct` lets us combine these two into a single, unified datatype with `x`
and `y` as field labels:
```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);
}
```
Theres a lot going on here, so lets break it down. We declare a `struct` with
the `struct` keyword, and then with a name. By convention, `struct`s begin with
a capital letter and are 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 doesnt need to be the same as
in the original declaration.
Finally, because fields have names, we can access them through dot
notation: `origin.x`.
The values in `struct`s 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)`.
Rust does not support field mutability at the language level, so you cannot
write something like this:
```rust,ignore
struct Point {
mut x: i32, // This causes an error.
y: i32,
}
```
Mutability is a property of the binding, not of the structure itself. If youre
used to field-level mutability, this may seem strange at first, but it
significantly simplifies things. It even lets you make things mutable on a temporary
basis:
```rust,ignore
struct Point {
x: i32,
y: i32,
}
fn main() {
let mut point = Point { x: 0, y: 0 };
point.x = 5;
let point = point; // `point` is now immutable.
point.y = 6; // This causes an error.
}
```
Your structure can still contain `&mut` references, which will let
you do some kinds of mutation:
```rust
struct Point {
x: i32,
y: i32,
}
struct PointRef<'a> {
x: &'a mut i32,
y: &'a mut i32,
}
fn main() {
let mut point = Point { x: 0, y: 0 };
{
let r = PointRef { x: &mut point.x, y: &mut point.y };
*r.x = 5;
*r.y = 6;
}
assert_eq!(5, point.x);
assert_eq!(6, point.y);
}
```
Initialization of a data structure (struct, enum, union) can be simplified when
fields of the data structure are initialized with variables of the same
names as the fields.
```rust
#[derive(Debug)]
struct Person<'a> {
name: &'a str,
age: u8
}
fn main() {
// Create struct with field init shorthand
let name = "Peter";
let age = 27;
let peter = Person { name, age };
// Debug-print struct
println!("{:?}", peter);
}
```
# Update syntax
A `struct` can include `..` to indicate that you want to use a copy of some
other `struct` for some of the values. For example:
```rust
struct Point3d {
x: i32,
y: i32,
z: i32,
}
let mut point = Point3d { x: 0, y: 0, z: 0 };
point = Point3d { y: 1, .. point };
```
This gives `point` a new `y`, but keeps the old `x` and `z` values. It doesnt
have to be the same `struct` either, you can use this syntax when making new
ones, and it will copy the values you dont specify:
```rust
# struct Point3d {
# x: i32,
# y: i32,
# z: i32,
# }
let origin = Point3d { x: 0, y: 0, z: 0 };
let point = Point3d { z: 1, x: 2, .. origin };
```
# Tuple structs
Rust has another data type thats like a hybrid between a [tuple][tuple] and a
`struct`, called a tuple struct. Tuple structs have a name, but their fields
don't. They are declared with the `struct` keyword, and then with a name
followed by a tuple:
[tuple]: primitive-types.html#tuples
```rust
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
```
Here, `black` and `origin` are not the same type, even though they contain the
same values.
The members of a tuple struct may be accessed by dot notation or destructuring
`let`, just like regular tuples:
```rust
# struct Color(i32, i32, i32);
# struct Point(i32, i32, i32);
# let black = Color(0, 0, 0);
# let origin = Point(0, 0, 0);
let black_r = black.0;
let Point(_, origin_y, origin_z) = origin;
```
Patterns like `Point(_, origin_y, origin_z)` are also used in
[match expressions][match].
One case when a tuple struct is very useful is when it has only one element.
We call this the newtype pattern, because it allows you to create a new type
that is distinct from its contained value and also expresses its own semantic
meaning:
```rust
struct Inches(i32);
let length = Inches(10);
let Inches(integer_length) = length;
println!("length is {} inches", integer_length);
```
As above, you can extract the inner integer type through a destructuring `let`.
In this case, the `let Inches(integer_length)` assigns `10` to `integer_length`.
We could have used dot notation to do the same thing:
```rust
# struct Inches(i32);
# let length = Inches(10);
let integer_length = length.0;
```
It's always possible to use a `struct` instead of a tuple struct, and can be
clearer. We could write `Color` and `Point` like this instead:
```rust
struct Color {
red: i32,
blue: i32,
green: i32,
}
struct Point {
x: i32,
y: i32,
z: i32,
}
```
Good names are important, and while values in a tuple struct can be
referenced with dot notation as well, a `struct` gives us actual names,
rather than positions.
[match]: match.html
# Unit-like structs
You can define a `struct` with no members at all:
```rust,ignore
struct Electron {} // Use empty braces...
struct Proton; // ...or just a semicolon.
// Use the same notation when creating an instance.
let x = Electron {};
let y = Proton;
let z = Electron; // Error
```
Such a `struct` is called unit-like because it resembles the empty
tuple, `()`, sometimes called unit. Like a tuple struct, it defines a
new type.
This is rarely useful on its own (although sometimes it can serve as a
marker type), but in combination with other features, it can become
useful. For instance, a library may ask you to create a structure that
implements a certain [trait][trait] to handle events. If you dont have
any data you need to store in the structure, you can create a
unit-like `struct`.
[trait]: traits.html
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/structs.html).

View File

@ -1,10 +1,10 @@
# Syntax and Semantics
This chapter breaks Rust down into small chunks, one for each concept.
The first edition of the book is no longer distributed with Rust's documentation.
If youd like to learn Rust from the bottom up, reading this in order is a
great way to do that.
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
These sections also form a reference for each concept, so if youre reading
another tutorial and find something confusing, you can find it explained
somewhere in here.
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/syntax-and-semantics.html).

View File

@ -1,253 +1,10 @@
# Syntax Index
## Keywords
The first edition of the book is no longer distributed with Rust's documentation.
* `as`: primitive casting, or disambiguating the specific trait containing an item. See [Casting Between Types (`as`)], [Universal Function Call Syntax (Angle-bracket Form)], [Associated Types].
* `break`: break out of loop. See [Loops (Ending Iteration Early)].
* `const`: constant items and constant raw pointers. See [`const` and `static`], [Raw Pointers].
* `continue`: continue to next loop iteration. See [Loops (Ending Iteration Early)].
* `crate`: external crate linkage. See [Crates and Modules (Importing External Crates)].
* `else`: fallback for `if` and `if let` constructs. See [`if`], [`if let`].
* `enum`: defining enumeration. See [Enums].
* `extern`: external crate, function, and variable linkage. See [Crates and Modules (Importing External Crates)], [Foreign Function Interface].
* `false`: boolean false literal. See [Primitive Types (Booleans)].
* `fn`: function definition and function pointer types. See [Functions].
* `for`: iterator loop, part of trait `impl` syntax, and higher-ranked lifetime syntax. See [Loops (`for`)], [Method Syntax].
* `if`: conditional branching. See [`if`], [`if let`].
* `impl`: inherent and trait implementation blocks. See [Method Syntax].
* `in`: part of `for` loop syntax. See [Loops (`for`)].
* `let`: variable binding. See [Variable Bindings].
* `loop`: unconditional, infinite loop. See [Loops (`loop`)].
* `match`: pattern matching. See [Match].
* `mod`: module declaration. See [Crates and Modules (Defining Modules)].
* `move`: part of closure syntax. See [Closures (`move` closures)].
* `mut`: denotes mutability in pointer types and pattern bindings. See [Mutability].
* `pub`: denotes public visibility in `struct` fields, `impl` blocks, and modules. See [Crates and Modules (Exporting a Public Interface)].
* `ref`: by-reference binding. See [Patterns (`ref` and `ref mut`)].
* `return`: return from function. See [Functions (Early Returns)].
* `Self`: implementor type alias. See [Traits].
* `self`: method subject. See [Method Syntax (Method Calls)].
* `static`: global variable. See [`const` and `static` (`static`)].
* `struct`: structure definition. See [Structs].
* `trait`: trait definition. See [Traits].
* `true`: boolean true literal. See [Primitive Types (Booleans)].
* `type`: type alias, and associated type definition. See [`type` Aliases], [Associated Types].
* `unsafe`: denotes unsafe code, functions, traits, and implementations. See [Unsafe].
* `use`: import symbols into scope. See [Crates and Modules (Importing Modules with `use`)].
* `where`: type constraint clauses. See [Traits (`where` clause)].
* `while`: conditional loop. See [Loops (`while`)].
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
## Operators and Symbols
* `!` (`ident!(…)`, `ident!{…}`, `ident![…]`): denotes macro expansion. See [Macros].
* `!` (`!expr`): bitwise or logical complement. Overloadable (`Not`).
* `!=` (`var != expr`): nonequality comparison. Overloadable (`PartialEq`).
* `%` (`expr % expr`): arithmetic remainder. Overloadable (`Rem`).
* `%=` (`var %= expr`): arithmetic remainder & assignment. Overloadable (`RemAssign`).
* `&` (`expr & expr`): bitwise and. Overloadable (`BitAnd`).
* `&` (`&expr`, `&mut expr`): borrow. See [References and Borrowing].
* `&` (`&type`, `&mut type`, `&'a type`, `&'a mut type`): borrowed pointer type. See [References and Borrowing].
* `&=` (`var &= expr`): bitwise and & assignment. Overloadable (`BitAndAssign`).
* `&&` (`expr && expr`): logical and.
* `*` (`expr * expr`): arithmetic multiplication. Overloadable (`Mul`).
* `*` (`*expr`): dereference.
* `*` (`*const type`, `*mut type`): raw pointer. See [Raw Pointers].
* `*=` (`var *= expr`): arithmetic multiplication & assignment. Overloadable (`MulAssign`).
* `+` (`expr + expr`): arithmetic addition. Overloadable (`Add`).
* `+` (`trait + trait`, `'a + trait`): compound type constraint. See [Traits (Multiple Trait Bounds)].
* `+=` (`var += expr`): arithmetic addition & assignment. Overloadable (`AddAssign`).
* `,`: argument and element separator. See [Attributes], [Functions], [Structs], [Generics], [Match], [Closures], [Crates and Modules (Importing Modules with `use`)].
* `-` (`expr - expr`): arithmetic subtraction. Overloadable (`Sub`).
* `-` (`- expr`): arithmetic negation. Overloadable (`Neg`).
* `-=` (`var -= expr`): arithmetic subtraction & assignment. Overloadable (`SubAssign`).
* `->` (`fn(…) -> type`, `|…| -> type`): function and closure return type. See [Functions], [Closures].
* `.` (`expr.ident`): member access. See [Structs], [Method Syntax].
* `..` (`..`, `expr..`, `..expr`, `expr..expr`): right-exclusive range literal.
* `..` (`..expr`): struct literal update syntax. See [Structs (Update syntax)].
* `..` (`variant(x, ..)`, `struct_type { x, .. }`): "and the rest" pattern binding. See [Patterns (Ignoring bindings)].
* `...` (`...expr`, `expr...expr`) *in an expression*: inclusive range expression. See [Iterators].
* `...` (`expr...expr`) *in a pattern*: inclusive range pattern. See [Patterns (Ranges)].
* `/` (`expr / expr`): arithmetic division. Overloadable (`Div`).
* `/=` (`var /= expr`): arithmetic division & assignment. Overloadable (`DivAssign`).
* `:` (`pat: type`, `ident: type`): constraints. See [Variable Bindings], [Functions], [Structs], [Traits].
* `:` (`ident: expr`): struct field initializer. See [Structs].
* `:` (`'a: loop {…}`): loop label. See [Loops (Loops Labels)].
* `;`: statement and item terminator.
* `;` (`[…; len]`): part of fixed-size array syntax. See [Primitive Types (Arrays)].
* `<<` (`expr << expr`): left-shift. Overloadable (`Shl`).
* `<<=` (`var <<= expr`): left-shift & assignment. Overloadable (`ShlAssign`).
* `<` (`expr < expr`): less-than comparison. Overloadable (`PartialOrd`).
* `<=` (`var <= expr`): less-than or equal-to comparison. Overloadable (`PartialOrd`).
* `=` (`var = expr`, `ident = type`): assignment/equivalence. See [Variable Bindings], [`type` Aliases], generic parameter defaults.
* `==` (`var == expr`): equality comparison. Overloadable (`PartialEq`).
* `=>` (`pat => expr`): part of match arm syntax. See [Match].
* `>` (`expr > expr`): greater-than comparison. Overloadable (`PartialOrd`).
* `>=` (`var >= expr`): greater-than or equal-to comparison. Overloadable (`PartialOrd`).
* `>>` (`expr >> expr`): right-shift. Overloadable (`Shr`).
* `>>=` (`var >>= expr`): right-shift & assignment. Overloadable (`ShrAssign`).
* `@` (`ident @ pat`): pattern binding. See [Patterns (Bindings)].
* `^` (`expr ^ expr`): bitwise exclusive or. Overloadable (`BitXor`).
* `^=` (`var ^= expr`): bitwise exclusive or & assignment. Overloadable (`BitXorAssign`).
* `|` (`expr | expr`): bitwise or. Overloadable (`BitOr`).
* `|` (`pat | pat`): pattern alternatives. See [Patterns (Multiple patterns)].
* `|` (`|…| expr`): closures. See [Closures].
* `|=` (`var |= expr`): bitwise or & assignment. Overloadable (`BitOrAssign`).
* `||` (`expr || expr`): logical or.
* `_`: "ignored" pattern binding (see [Patterns (Ignoring bindings)]). Also used to make integer-literals readable (see [Reference (Integer literals)]).
* `?` (`expr?`): Error propagation. Returns early when `Err(_)` is encountered, unwraps otherwise. Similar to the [`try!` macro].
## Other Syntax
<!-- Various bits of standalone stuff. -->
* `'ident`: named lifetime or loop label. See [Lifetimes], [Loops (Loops Labels)].
* `…u8`, `…i32`, `…f64`, `…usize`, …: numeric literal of specific type.
* `"…"`: string literal. See [Strings].
* `r"…"`, `r#"…"#`, `r##"…"##`, …: raw string literal, escape characters are not processed. See [Reference (Raw String Literals)].
* `b"…"`: byte string literal, constructs a `[u8]` instead of a string. See [Reference (Byte String Literals)].
* `br"…"`, `br#"…"#`, `br##"…"##`, …: raw byte string literal, combination of raw and byte string literal. See [Reference (Raw Byte String Literals)].
* `'…'`: character literal. See [Primitive Types (`char`)].
* `b'…'`: ASCII byte literal.
* `|…| expr`: closure. See [Closures].
<!-- Path-related syntax -->
* `ident::ident`: path. See [Crates and Modules (Defining Modules)].
* `::path`: path relative to the crate root (*i.e.* an explicitly absolute path). See [Crates and Modules (Re-exporting with `pub use`)].
* `self::path`: path relative to the current module (*i.e.* an explicitly relative path). See [Crates and Modules (Re-exporting with `pub use`)].
* `super::path`: path relative to the parent of the current module. See [Crates and Modules (Re-exporting with `pub use`)].
* `type::ident`, `<type as trait>::ident`: associated constants, functions, and types. See [Associated Types].
* `<type>::…`: associated item for a type which cannot be directly named (*e.g.* `<&T>::…`, `<[T]>::…`, *etc.*). See [Associated Types].
* `trait::method(…)`: disambiguating a method call by naming the trait which defines it. See [Universal Function Call Syntax].
* `type::method(…)`: disambiguating a method call by naming the type for which it's defined. See [Universal Function Call Syntax].
* `<type as trait>::method(…)`: disambiguating a method call by naming the trait _and_ type. See [Universal Function Call Syntax (Angle-bracket Form)].
<!-- Generics -->
* `path<…>` (*e.g.* `Vec<u8>`): specifies parameters to generic type *in a type*. See [Generics].
* `path::<…>`, `method::<…>` (*e.g.* `"42".parse::<i32>()`): specifies parameters to generic type, function, or method *in an expression*. See [Generics § Resolving ambiguities](generics.html#resolving-ambiguities).
* `fn ident<…> …`: define generic function. See [Generics].
* `struct ident<…> …`: define generic structure. See [Generics].
* `enum ident<…> …`: define generic enumeration. See [Generics].
* `impl<…> …`: define generic implementation.
* `for<…> type`: higher-ranked lifetime bounds.
* `type<ident=type>` (*e.g.* `Iterator<Item=T>`): a generic type where one or more associated types have specific assignments. See [Associated Types].
<!-- Constraints -->
* `T: U`: generic parameter `T` constrained to types that implement `U`. See [Traits].
* `T: 'a`: generic type `T` must outlive lifetime `'a`. When we say that a type 'outlives' the lifetime, we mean that it cannot transitively contain any references with lifetimes shorter than `'a`.
* `T : 'static`: The generic type `T` contains no borrowed references other than `'static` ones.
* `'b: 'a`: generic lifetime `'b` must outlive lifetime `'a`.
* `T: ?Sized`: allow generic type parameter to be a dynamically-sized type. See [Unsized Types (`?Sized`)].
* `'a + trait`, `trait + trait`: compound type constraint. See [Traits (Multiple Trait Bounds)].
<!-- Macros and attributes -->
* `#[meta]`: outer attribute. See [Attributes].
* `#![meta]`: inner attribute. See [Attributes].
* `$ident`: macro substitution. See [Macros].
* `$ident:kind`: macro capture. See [Macros].
* `$(…)…`: macro repetition. See [Macros].
<!-- Comments -->
* `//`: line comment. See [Comments].
* `//!`: inner line doc comment. See [Comments].
* `///`: outer line doc comment. See [Comments].
* `/*…*/`: block comment. See [Comments].
* `/*!…*/`: inner block doc comment. See [Comments].
* `/**…*/`: outer block doc comment. See [Comments].
<!-- Special types -->
* `!`: always empty Never type. See [Diverging Functions].
<!-- Various things involving parens and tuples -->
* `()`: empty tuple (*a.k.a.* unit), both literal and type.
* `(expr)`: parenthesized expression.
* `(expr,)`: single-element tuple expression. See [Primitive Types (Tuples)].
* `(type,)`: single-element tuple type. See [Primitive Types (Tuples)].
* `(expr, …)`: tuple expression. See [Primitive Types (Tuples)].
* `(type, …)`: tuple type. See [Primitive Types (Tuples)].
* `expr(expr, …)`: function call expression. Also used to initialize tuple `struct`s and tuple `enum` variants. See [Functions].
* `ident!(…)`, `ident!{…}`, `ident![…]`: macro invocation. See [Macros].
* `expr.0`, `expr.1`, …: tuple indexing. See [Primitive Types (Tuple Indexing)].
<!-- Bracey things -->
* `{…}`: block expression.
* `Type {…}`: `struct` literal. See [Structs].
<!-- Brackety things -->
* `[…]`: array literal. See [Primitive Types (Arrays)].
* `[expr; len]`: array literal containing `len` copies of `expr`. See [Primitive Types (Arrays)].
* `[type; len]`: array type containing `len` instances of `type`. See [Primitive Types (Arrays)].
* `expr[expr]`: collection indexing. Overloadable (`Index`, `IndexMut`).
* `expr[..]`, `expr[a..]`, `expr[..b]`, `expr[a..b]`: collection indexing pretending to be collection slicing, using `Range`, `RangeFrom`, `RangeTo`, `RangeFull` as the "index".
[`const` and `static` (`static`)]: const-and-static.html#static
[`const` and `static`]: const-and-static.html
[`if let`]: if-let.html
[`if`]: if.html
[`type` Aliases]: type-aliases.html
[Associated Types]: associated-types.html
[Attributes]: attributes.html
[Casting Between Types (`as`)]: casting-between-types.html#as
[Closures (`move` closures)]: closures.html#move-closures
[Closures]: closures.html
[Comments]: comments.html
[Crates and Modules (Defining Modules)]: crates-and-modules.html#defining-modules
[Crates and Modules (Exporting a Public Interface)]: crates-and-modules.html#exporting-a-public-interface
[Crates and Modules (Importing External Crates)]: crates-and-modules.html#importing-external-crates
[Crates and Modules (Importing Modules with `use`)]: crates-and-modules.html#importing-modules-with-use
[Crates and Modules (Re-exporting with `pub use`)]: crates-and-modules.html#re-exporting-with-pub-use
[Diverging Functions]: functions.html#diverging-functions
[Enums]: enums.html
[Foreign Function Interface]: ffi.html
[Functions (Early Returns)]: functions.html#early-returns
[Functions]: functions.html
[Generics]: generics.html
[Iterators]: iterators.html
[`try!` macro]: error-handling.html#the-try-macro
[Lifetimes]: lifetimes.html
[Loops (`for`)]: loops.html#for
[Loops (`loop`)]: loops.html#loop
[Loops (`while`)]: loops.html#while
[Loops (Ending Iteration Early)]: loops.html#ending-iteration-early
[Loops (Loops Labels)]: loops.html#loop-labels
[Macros]: macros.html
[Match]: match.html
[Method Syntax (Method Calls)]: method-syntax.html#method-calls
[Method Syntax]: method-syntax.html
[Mutability]: mutability.html
[Operators and Overloading]: operators-and-overloading.html
[Patterns (`ref` and `ref mut`)]: patterns.html#ref-and-ref-mut
[Patterns (Bindings)]: patterns.html#bindings
[Patterns (Ignoring bindings)]: patterns.html#ignoring-bindings
[Patterns (Multiple patterns)]: patterns.html#multiple-patterns
[Patterns (Ranges)]: patterns.html#ranges
[Primitive Types (`char`)]: primitive-types.html#char
[Primitive Types (Arrays)]: primitive-types.html#arrays
[Primitive Types (Booleans)]: primitive-types.html#booleans
[Primitive Types (Tuple Indexing)]: primitive-types.html#tuple-indexing
[Primitive Types (Tuples)]: primitive-types.html#tuples
[Raw Pointers]: raw-pointers.html
[Reference (Byte String Literals)]: ../../reference/tokens.html#byte-and-byte-string-literals
[Reference (Integer literals)]: ../../reference/tokens.html#integer-literals
[Reference (Raw Byte String Literals)]: ../../reference/tokens.html#raw-byte-string-literals
[Reference (Raw String Literals)]: ../../reference/tokens.html#raw-string-literals
[References and Borrowing]: references-and-borrowing.html
[Strings]: strings.html
[Structs (Update syntax)]: structs.html#update-syntax
[Structs]: structs.html
[Traits (`where` clause)]: traits.html#where-clause
[Traits (Multiple Trait Bounds)]: traits.html#multiple-trait-bounds
[Traits]: traits.html
[Universal Function Call Syntax]: ufcs.html
[Universal Function Call Syntax (Angle-bracket Form)]: ufcs.html#angle-bracket-form
[Unsafe]: unsafe.html
[Unsized Types (`?Sized`)]: unsized-types.html#sized
[Variable Bindings]: variable-bindings.html
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/syntax-index.html).

View File

@ -1,633 +1,10 @@
# Testing
> Program testing can be a very effective way to show the presence of bugs, but
> it is hopelessly inadequate for showing their absence.
>
> Edsger W. Dijkstra, "The Humble Programmer" (1972)
The first edition of the book is no longer distributed with Rust's documentation.
Let's talk about how to test Rust code. What we will not be talking about is
the right way to test Rust code. There are many schools of thought regarding
the right and wrong way to write tests. All of these approaches use the same
basic tools, and so we'll show you the syntax for using them.
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
# The `test` attribute
At its simplest, a test in Rust is a function that's annotated with the `test`
attribute. Let's make a new project with Cargo called `adder`:
```bash
$ cargo new adder
$ cd adder
```
Cargo will automatically generate a simple test when you make a new project.
Here's the contents of `src/lib.rs`:
```rust,ignore
# // The next line exists to trick play.rust-lang.org into running our code as a
# // test:
# // fn main
#
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
}
}
```
For now, let's remove the `mod` bit, and focus on just the function:
```rust,ignore
# // The next line exists to trick play.rust-lang.org into running our code as a
# // test:
# // fn main
#
#[test]
fn it_works() {
}
```
Note the `#[test]`. This attribute indicates that this is a test function. It
currently has no body. That's good enough to pass! We can run the tests with
`cargo test`:
```bash
$ cargo test
Compiling adder v0.1.0 (file:///home/you/projects/adder)
Finished debug [unoptimized + debuginfo] target(s) in 0.15 secs
Running target/debug/deps/adder-941f01916ca4a642
running 1 test
test it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
Doc-tests adder
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
```
Cargo compiled and ran our tests. There are two sets of output here: one
for the test we wrote, and another for documentation tests. We'll talk about
those later. For now, see this line:
```text
test it_works ... ok
```
Note the `it_works`. This comes from the name of our function:
```rust
# fn main() {
fn it_works() {
}
# }
```
We also get a summary line:
```text
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
```
So why does our do-nothing test pass? Any test which doesn't `panic!` passes,
and any test that does `panic!` fails. Let's make our test fail:
```rust,ignore
# // The next line exists to trick play.rust-lang.org into running our code as a
# // test:
# // fn main
#
#[test]
fn it_works() {
assert!(false);
}
```
`assert!` is a macro provided by Rust which takes one argument: if the argument
is `true`, nothing happens. If the argument is `false`, it will `panic!`. Let's
run our tests again:
```bash
$ cargo test
Compiling adder v0.1.0 (file:///home/you/projects/adder)
Finished debug [unoptimized + debuginfo] target(s) in 0.17 secs
Running target/debug/deps/adder-941f01916ca4a642
running 1 test
test it_works ... FAILED
failures:
---- it_works stdout ----
thread 'it_works' panicked at 'assertion failed: false', src/lib.rs:5
note: Run with `RUST_BACKTRACE=1` for a backtrace.
failures:
it_works
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured
error: test failed
```
Rust indicates that our test failed:
```text
test it_works ... FAILED
```
And that's reflected in the summary line:
```text
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured
```
We also get a non-zero status code. We can use `$?` on macOS and Linux:
```bash
$ echo $?
101
```
On Windows, if youre using `cmd`:
```bash
> echo %ERRORLEVEL%
```
And if youre using PowerShell:
```bash
> echo $LASTEXITCODE # the code itself
> echo $? # a boolean, fail or succeed
```
This is useful if you want to integrate `cargo test` into other tooling.
We can invert our test's failure with another attribute: `should_panic`:
```rust,ignore
# // The next line exists to trick play.rust-lang.org into running our code as a
# // test:
# // fn main
#
#[test]
#[should_panic]
fn it_works() {
assert!(false);
}
```
This test will now succeed if we `panic!` and fail if we complete. Let's try it:
```bash
$ cargo test
Compiling adder v0.1.0 (file:///home/you/projects/adder)
Finished debug [unoptimized + debuginfo] target(s) in 0.17 secs
Running target/debug/deps/adder-941f01916ca4a642
running 1 test
test it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
Doc-tests adder
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
```
Rust provides another macro, `assert_eq!`, that compares two arguments for
equality:
```rust,ignore
# // The next line exists to trick play.rust-lang.org into running our code as a
# // test:
# // fn main
#
#[test]
#[should_panic]
fn it_works() {
assert_eq!("Hello", "world");
}
```
Does this test pass or fail? Because of the `should_panic` attribute, it
passes:
```bash
$ cargo test
Compiling adder v0.1.0 (file:///home/you/projects/adder)
Finished debug [unoptimized + debuginfo] target(s) in 0.21 secs
Running target/debug/deps/adder-941f01916ca4a642
running 1 test
test it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
Doc-tests adder
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
```
`should_panic` tests can be fragile, as it's hard to guarantee that the test
didn't fail for an unexpected reason. To help with this, an optional `expected`
parameter can be added to the `should_panic` attribute. The test harness will
make sure that the failure message contains the provided text. A safer version
of the example above would be:
```rust,ignore
# // The next line exists to trick play.rust-lang.org into running our code as a
# // test:
# // fn main
#
#[test]
#[should_panic(expected = "assertion failed")]
fn it_works() {
assert_eq!("Hello", "world");
}
```
That's all there is to the basics! Let's write one 'real' test:
```rust,ignore
# // The next line exists to trick play.rust-lang.org into running our code as a
# // test:
# // fn main
#
pub fn add_two(a: i32) -> i32 {
a + 2
}
#[test]
fn it_works() {
assert_eq!(4, add_two(2));
}
```
This is a very common use of `assert_eq!`: call some function with
some known arguments and compare it to the expected output.
# The `ignore` attribute
Sometimes a few specific tests can be very time-consuming to execute. These
can be disabled by default by using the `ignore` attribute:
```rust,ignore
# // The next line exists to trick play.rust-lang.org into running our code as a
# // test:
# // fn main
#
pub fn add_two(a: i32) -> i32 {
a + 2
}
#[test]
fn it_works() {
assert_eq!(4, add_two(2));
}
#[test]
#[ignore]
fn expensive_test() {
// Code that takes an hour to run...
}
```
Now we run our tests and see that `it_works` is run, but `expensive_test` is
not:
```bash
$ cargo test
Compiling adder v0.1.0 (file:///home/you/projects/adder)
Finished debug [unoptimized + debuginfo] target(s) in 0.20 secs
Running target/debug/deps/adder-941f01916ca4a642
running 2 tests
test expensive_test ... ignored
test it_works ... ok
test result: ok. 1 passed; 0 failed; 1 ignored; 0 measured
Doc-tests adder
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
```
The expensive tests can be run explicitly using `cargo test -- --ignored`:
```bash
$ cargo test -- --ignored
Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs
Running target/debug/deps/adder-941f01916ca4a642
running 1 test
test expensive_test ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
Doc-tests adder
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
```
The `--ignored` argument is an argument to the test binary, and not to Cargo,
which is why the command is `cargo test -- --ignored`.
# The `tests` module
There is one way in which our existing example is not idiomatic: it's
missing the `tests` module. You might have noticed this test module was
present in the code that was initially generated with `cargo new` but
was missing from our last example. Let's explain what this does.
The idiomatic way of writing our example looks like this:
```rust,ignore
# // The next line exists to trick play.rust-lang.org into running our code as a
# // test:
# // fn main
#
pub fn add_two(a: i32) -> i32 {
a + 2
}
#[cfg(test)]
mod tests {
use super::add_two;
#[test]
fn it_works() {
assert_eq!(4, add_two(2));
}
}
```
There's a few changes here. The first is the introduction of a `mod tests` with
a `cfg` attribute. The module allows us to group all of our tests together, and
to also define helper functions if needed, that don't become a part of the rest
of our crate. The `cfg` attribute only compiles our test code if we're
currently trying to run the tests. This can save compile time, and also ensures
that our tests are entirely left out of a normal build.
The second change is the `use` declaration. Because we're in an inner module,
we need to bring the tested function into scope. This can be annoying if you have
a large module, and so this is a common use of globs. Let's change our
`src/lib.rs` to make use of it:
```rust,ignore
# // The next line exists to trick play.rust-lang.org into running our code as a
# // test:
# // fn main
#
pub fn add_two(a: i32) -> i32 {
a + 2
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
assert_eq!(4, add_two(2));
}
}
```
Note the different `use` line. Now we run our tests:
```bash
$ cargo test
Updating registry `https://github.com/rust-lang/crates.io-index`
Compiling adder v0.1.0 (file:///home/you/projects/adder)
Running target/debug/deps/adder-91b3e234d4ed382a
running 1 test
test tests::it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
Doc-tests adder
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
```
It works!
The current convention is to use the `tests` module to hold your "unit-style"
tests. Anything that tests one small bit of functionality makes sense to
go here. But what about "integration-style" tests instead? For that, we have
the `tests` directory.
# The `tests` directory
Each file in `tests/*.rs` directory is treated as an individual crate.
To write an integration test, let's make a `tests` directory and
put a `tests/integration_test.rs` file inside with this as its contents:
```rust,ignore
# // The next line exists to trick play.rust-lang.org into running our code as a
# // test:
# // fn main
#
# // Sadly, this code will not work in play.rust-lang.org, because we have no
# // crate adder to import. You'll need to try this part on your own machine.
extern crate adder;
#[test]
fn it_works() {
assert_eq!(4, adder::add_two(2));
}
```
This looks similar to our previous tests, but slightly different. We now have
an `extern crate adder` at the top. This is because each test in the `tests`
directory is an entirely separate crate, and so we need to import our library.
This is also why `tests` is a suitable place to write integration-style tests:
they use the library like any other consumer of it would.
Let's run them:
```bash
$ cargo test
Compiling adder v0.1.0 (file:///home/you/projects/adder)
Running target/debug/deps/adder-91b3e234d4ed382a
running 1 test
test tests::it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
Running target/debug/integration_test-68064b69521c828a
running 1 test
test it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
Doc-tests adder
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
```
Now we have three sections: our previous test is also run, as well as our new
one.
Cargo will ignore files in subdirectories of the `tests/` directory.
Therefore shared modules in integrations tests are possible.
For example `tests/common/mod.rs` is not separately compiled by cargo but can
be imported in every test with `mod common;`
That's all there is to the `tests` directory. The `tests` module isn't needed
here, since the whole thing is focused on tests.
Note, when building integration tests, cargo will not pass the `test` attribute
to the compiler. It means that all parts in `cfg(test)` won't be included in
the build used in your integration tests.
Let's finally check out that third section: documentation tests.
# Documentation tests
Nothing is better than documentation with examples. Nothing is worse than
examples that don't actually work, because the code has changed since the
documentation has been written. To this end, Rust supports automatically
running examples in your documentation (**note:** this only works in library
crates, not binary crates). Here's a fleshed-out `src/lib.rs` with examples:
```rust,ignore
# // The next line exists to trick play.rust-lang.org into running our code as a
# // test:
# // fn main
#
//! The `adder` crate provides functions that add numbers to other numbers.
//!
//! # Examples
//!
//! ```
//! assert_eq!(4, adder::add_two(2));
//! ```
/// This function adds two to its argument.
///
/// # Examples
///
/// ```
/// use adder::add_two;
///
/// assert_eq!(4, add_two(2));
/// ```
pub fn add_two(a: i32) -> i32 {
a + 2
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
assert_eq!(4, add_two(2));
}
}
```
Note the module-level documentation with `//!` and the function-level
documentation with `///`. Rust's documentation supports Markdown in comments,
and so triple graves mark code blocks. It is conventional to include the
`# Examples` section, exactly like that, with examples following.
Let's run the tests again:
```bash
$ cargo test
Compiling adder v0.1.0. (file:///home/you/projects/adder)
Running target/debug/deps/adder-91b3e234d4ed382a
running 1 test
test tests::it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
Running target/debug/integration_test-68064b69521c828a
running 1 test
test it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
Doc-tests adder
running 2 tests
test add_two_0 ... ok
test _0 ... ok
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured
```
Now we have all three kinds of tests running! Note the names of the
documentation tests: the `_0` is generated for the module test, and `add_two_0`
for the function test. These will auto increment with names like `add_two_1` as
you add more examples.
We havent covered all of the details with writing documentation tests. For more,
please see the [Documentation chapter](documentation.html).
# Testing and concurrency
It is important to note that tests are run concurrently using threads. For this
reason, care should be taken to ensure your tests do not depend on each-other,
or on any shared state. "Shared state" can also include the environment, such
as the current working directory, or environment variables.
If this is an issue it is possible to control this concurrency, either by
setting the environment variable `RUST_TEST_THREADS`, or by passing the argument
`--test-threads` to the tests:
```bash
$ RUST_TEST_THREADS=1 cargo test # Run tests with no concurrency
...
$ cargo test -- --test-threads=1 # Same as above
...
```
# Test output
By default Rust's test library captures and discards output to standard
out/error, e.g. output from `println!()`. This too can be controlled using the
environment or a switch:
```bash
$ RUST_TEST_NOCAPTURE=1 cargo test # Preserve stdout/stderr
...
$ cargo test -- --nocapture # Same as above
...
```
However a better method avoiding capture is to use logging rather than raw
output. Rust has a [standard logging API][log], which provides a frontend to
multiple logging implementations. This can be used in conjunction with the
default [env_logger] to output any debugging information in a manner that can be
controlled at runtime.
[log]: https://crates.io/crates/log
[env_logger]: https://crates.io/crates/env_logger
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/testing.html).

View File

@ -1,585 +1,10 @@
# The Stack and the Heap
As a systems language, Rust operates at a low level. If youre coming from a
high-level language, there are some aspects of systems programming that you may
not be familiar with. The most important one is how memory works, with a stack
and a heap. If youre familiar with how C-like languages use stack allocation,
this chapter will be a refresher. If youre not, youll learn about this more
general concept, but with a Rust-y focus.
The first edition of the book is no longer distributed with Rust's documentation.
As with most things, when learning about them, well use a simplified model to
start. This lets you get a handle on the basics, without getting bogged down
with details which are, for now, irrelevant. The examples well use arent 100%
accurate, but are representative for the level were trying to learn at right
now. Once you have the basics down, learning more about how allocators are
implemented, virtual memory, and other advanced topics will reveal the leaks in
this particular abstraction.
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
# Memory management
These two terms are about memory management. The stack and the heap are
abstractions that help you determine when to allocate and deallocate memory.
Heres a high-level comparison:
The stack is very fast, and is where memory is allocated in Rust by default.
But the allocation is local to a function call, and is limited in size. The
heap, on the other hand, is slower, and is explicitly allocated by your
program. But its effectively unlimited in size, and is globally accessible.
Note this meaning of heap, which allocates arbitrary-sized blocks of memory in arbitrary
order, is quite different from the heap data structure.
# The Stack
Lets talk about this Rust program:
```rust
fn main() {
let x = 42;
}
```
This program has one variable binding, `x`. This memory needs to be allocated
from somewhere. Rust stack allocates by default, which means that basic
values go on the stack. What does that mean?
Well, when a function gets called, some memory gets allocated for all of its
local variables and some other information. This is called a stack frame, and
for the purpose of this tutorial, were going to ignore the extra information
and only consider the local variables were allocating. So in this case, when
`main()` is run, well allocate a single 32-bit integer for our stack frame.
This is automatically handled for you, as you can see; we didnt have to write
any special Rust code or anything.
When the function exits, its stack frame gets deallocated. This happens
automatically as well.
Thats all there is for this simple program. The key thing to understand here
is that stack allocation is very, very fast. Since we know all the local
variables we have ahead of time, we can grab the memory all at once. And since
well throw them all away at the same time as well, we can get rid of it very
fast too.
The downside is that we cant keep values around if we need them for longer
than a single function. We also havent talked about what the word, stack,
means. To do that, we need a slightly more complicated example:
```rust
fn foo() {
let y = 5;
let z = 100;
}
fn main() {
let x = 42;
foo();
}
```
This program has three variables total: two in `foo()`, one in `main()`. Just
as before, when `main()` is called, a single integer is allocated for its stack
frame. But before we can show what happens when `foo()` is called, we need to
visualize whats going on with memory. Your operating system presents a view of
memory to your program thats pretty simple: a huge list of addresses, from 0
to a large number, representing how much RAM your computer has. For example, if
you have a gigabyte of RAM, your addresses go from `0` to `1,073,741,823`. That
number comes from 2<sup>30</sup>, the number of bytes in a gigabyte. [^gigabyte]
[^gigabyte]: Gigabyte can mean two things: 10<sup>9</sup>, or 2<sup>30</sup>. The IEC standard resolved this by stating that gigabyte is 10<sup>9</sup>, and gibibyte is 2<sup>30</sup>. However, very few people use this terminology, and rely on context to differentiate. We follow in that tradition here.
This memory is kind of like a giant array: addresses start at zero and go
up to the final number. So heres a diagram of our first stack frame:
| Address | Name | Value |
|---------|------|-------|
| 0 | x | 42 |
Weve got `x` located at address `0`, with the value `42`.
When `foo()` is called, a new stack frame is allocated:
| Address | Name | Value |
|---------|------|-------|
| 2 | z | 100 |
| 1 | y | 5 |
| 0 | x | 42 |
Because `0` was taken by the first frame, `1` and `2` are used for `foo()`s
stack frame. It grows upward, the more functions we call. Notice that we are **not**
taking into account the size of each variable (for example, a 32 bit variable would
use the memory addresses from 0 to 3, or 4 bytes).
There are some important things we have to take note of here. The numbers 0, 1,
and 2 are all solely for illustrative purposes, and bear no relationship to the
address values the computer will use in reality. In particular, the series of
addresses are in reality going to be separated by some number of bytes that
separate each address, and that separation may even exceed the size of the
value being stored.
After `foo()` is over, its frame is deallocated:
| Address | Name | Value |
|---------|------|-------|
| 0 | x | 42 |
And then, after `main()`, even this last value goes away. Easy!
Its called a stack because it works like a stack of dinner plates: the first
plate you put down is the last plate to pick back up. Stacks are sometimes
called last in, first out queues for this reason, as the last value you put
on the stack is the first one you retrieve from it.
Lets try a three-deep example:
```rust
fn italic() {
let i = 6;
}
fn bold() {
let a = 5;
let b = 100;
let c = 1;
italic();
}
fn main() {
let x = 42;
bold();
}
```
We have some kooky function names to make the diagrams clearer.
Okay, first, we call `main()`:
| Address | Name | Value |
|---------|------|-------|
| 0 | x | 42 |
Next up, `main()` calls `bold()`:
| Address | Name | Value |
|---------|------|-------|
| **3** | **c**|**1** |
| **2** | **b**|**100**|
| **1** | **a**| **5** |
| 0 | x | 42 |
And then `bold()` calls `italic()`:
| Address | Name | Value |
|---------|------|-------|
| *4* | *i* | *6* |
| **3** | **c**|**1** |
| **2** | **b**|**100**|
| **1** | **a**| **5** |
| 0 | x | 42 |
Whew! Our stack is growing tall.
After `italic()` is over, its frame is deallocated, leaving only `bold()` and
`main()`:
| Address | Name | Value |
|---------|------|-------|
| **3** | **c**|**1** |
| **2** | **b**|**100**|
| **1** | **a**| **5** |
| 0 | x | 42 |
And then `bold()` ends, leaving only `main()`:
| Address | Name | Value |
|---------|------|-------|
| 0 | x | 42 |
And then were done. Getting the hang of it? Its like piling up dishes: you
add to the top, you take away from the top.
# The Heap
Now, this works pretty well, but not everything can work like this. Sometimes,
you need to pass some memory between different functions, or keep it alive for
longer than a single functions execution. For this, we can use the heap.
In Rust, you can allocate memory on the heap with the [`Box<T>` type][box].
Heres an example:
```rust
fn main() {
let x = Box::new(5);
let y = 42;
}
```
[box]: ../../std/boxed/index.html
Heres what happens in memory when `main()` is called:
| Address | Name | Value |
|---------|------|--------|
| 1 | y | 42 |
| 0 | x | ?????? |
We allocate space for two variables on the stack. `y` is `42`, as it always has
been, but what about `x`? Well, `x` is a `Box<i32>`, and boxes allocate memory
on the heap. The actual value of the box is a structure which has a pointer to
the heap. When we start executing the function, and `Box::new()` is called,
it allocates some memory for the heap, and puts `5` there. The memory now looks
like this:
| Address | Name | Value |
|----------------------|------|------------------------|
| (2<sup>30</sup>) - 1 | | 5 |
| ... | ... | ... |
| 1 | y | 42 |
| 0 | x | → (2<sup>30</sup>) - 1 |
We have (2<sup>30</sup>) addresses in our hypothetical computer with 1GiB of RAM. And since
our stack grows from zero, the easiest place to allocate memory is from the
other end. So our first value is at the highest place in memory. And the value
of the struct at `x` has a [raw pointer][rawpointer] to the place weve
allocated on the heap, so the value of `x` is (2<sup>30</sup>) - 1, the memory
location weve asked for.
[rawpointer]: raw-pointers.html
We havent really talked too much about what it actually means to allocate and
deallocate memory in these contexts. Getting into very deep detail is out of
the scope of this tutorial, but whats important to point out here is that
the heap isnt a stack that grows from the opposite end. Well have an
example of this later in the book, but because the heap can be allocated and
freed in any order, it can end up with holes. Heres a diagram of the memory
layout of a program which has been running for a while now:
| Address | Name | Value |
|----------------------|------|------------------------|
| (2<sup>30</sup>) - 1 | | 5 |
| (2<sup>30</sup>) - 2 | | |
| (2<sup>30</sup>) - 3 | | |
| (2<sup>30</sup>) - 4 | | 42 |
| ... | ... | ... |
| 2 | z | → (2<sup>30</sup>) - 4 |
| 1 | y | 42 |
| 0 | x | → (2<sup>30</sup>) - 1 |
In this case, weve allocated four things on the heap, but deallocated two of
them. Theres a gap between (2<sup>30</sup>) - 1 and (2<sup>30</sup>) - 4 which isnt
currently being used. The specific details of how and why this happens depends
on what kind of strategy you use to manage the heap. Different programs can use
different memory allocators, which are libraries that manage this for you.
Rust programs use [jemalloc][jemalloc] for this purpose.
[jemalloc]: http://www.canonware.com/jemalloc/
Anyway, back to our example. Since this memory is on the heap, it can stay
alive longer than the function which allocates the box. In this case, however,
it doesnt.[^moving] When the function is over, we need to free the stack frame
for `main()`. `Box<T>`, though, has a trick up its sleeve: [Drop][drop]. The
implementation of `Drop` for `Box` deallocates the memory that was allocated
when it was created. Great! So when `x` goes away, it first frees the memory
allocated on the heap:
| Address | Name | Value |
|---------|------|--------|
| 1 | y | 42 |
| 0 | x | ?????? |
[drop]: drop.html
[^moving]: We can make the memory live longer by transferring ownership,
sometimes called moving out of the box. More complex examples will
be covered later.
And then the stack frame goes away, freeing all of our memory.
# Arguments and borrowing
Weve got some basic examples with the stack and the heap going, but what about
function arguments and borrowing? Heres a small Rust program:
```rust
fn foo(i: &i32) {
let z = 42;
}
fn main() {
let x = 5;
let y = &x;
foo(y);
}
```
When we enter `main()`, memory looks like this:
| Address | Name | Value |
|---------|------|--------|
| 1 | y | → 0 |
| 0 | x | 5 |
`x` is a plain old `5`, and `y` is a reference to `x`. So its value is the
memory location that `x` lives at, which in this case is `0`.
What about when we call `foo()`, passing `y` as an argument?
| Address | Name | Value |
|---------|------|--------|
| 3 | z | 42 |
| 2 | i | → 0 |
| 1 | y | → 0 |
| 0 | x | 5 |
Stack frames arent only for local bindings, theyre for arguments too. So in
this case, we need to have both `i`, our argument, and `z`, our local variable
binding. `i` is a copy of the argument, `y`. Since `y`s value is `0`, so is
`i`s.
This is one reason why borrowing a variable doesnt deallocate any memory: the
value of a reference is a pointer to a memory location. If we got rid of
the underlying memory, things wouldnt work very well.
# A complex example
Okay, lets go through this complex program step-by-step:
```rust
fn foo(x: &i32) {
let y = 10;
let z = &y;
baz(z);
bar(x, z);
}
fn bar(a: &i32, b: &i32) {
let c = 5;
let d = Box::new(5);
let e = &d;
baz(e);
}
fn baz(f: &i32) {
let g = 100;
}
fn main() {
let h = 3;
let i = Box::new(20);
let j = &h;
foo(j);
}
```
First, we call `main()`:
| Address | Name | Value |
|----------------------|------|------------------------|
| (2<sup>30</sup>) - 1 | | 20 |
| ... | ... | ... |
| 2 | j | → 0 |
| 1 | i | → (2<sup>30</sup>) - 1 |
| 0 | h | 3 |
We allocate memory for `j`, `i`, and `h`. `i` is on the heap, and so has a
value pointing there.
Next, at the end of `main()`, `foo()` gets called:
| Address | Name | Value |
|----------------------|------|------------------------|
| (2<sup>30</sup>) - 1 | | 20 |
| ... | ... | ... |
| 5 | z | → 4 |
| 4 | y | 10 |
| 3 | x | → 0 |
| 2 | j | → 0 |
| 1 | i | → (2<sup>30</sup>) - 1 |
| 0 | h | 3 |
Space gets allocated for `x`, `y`, and `z`. The argument `x` has the same value
as `j`, since thats what we passed it in. Its a pointer to the `0` address,
since `j` points at `h`.
Next, `foo()` calls `baz()`, passing `z`:
| Address | Name | Value |
|----------------------|------|------------------------|
| (2<sup>30</sup>) - 1 | | 20 |
| ... | ... | ... |
| 7 | g | 100 |
| 6 | f | → 4 |
| 5 | z | → 4 |
| 4 | y | 10 |
| 3 | x | → 0 |
| 2 | j | → 0 |
| 1 | i | → (2<sup>30</sup>) - 1 |
| 0 | h | 3 |
Weve allocated memory for `f` and `g`. `baz()` is very short, so when its
over, we get rid of its stack frame:
| Address | Name | Value |
|----------------------|------|------------------------|
| (2<sup>30</sup>) - 1 | | 20 |
| ... | ... | ... |
| 5 | z | → 4 |
| 4 | y | 10 |
| 3 | x | → 0 |
| 2 | j | → 0 |
| 1 | i | → (2<sup>30</sup>) - 1 |
| 0 | h | 3 |
Next, `foo()` calls `bar()` with `x` and `z`:
| Address | Name | Value |
|----------------------|------|------------------------|
| (2<sup>30</sup>) - 1 | | 20 |
| (2<sup>30</sup>) - 2 | | 5 |
| ... | ... | ... |
| 10 | e | → 9 |
| 9 | d | → (2<sup>30</sup>) - 2 |
| 8 | c | 5 |
| 7 | b | → 4 |
| 6 | a | → 0 |
| 5 | z | → 4 |
| 4 | y | 10 |
| 3 | x | → 0 |
| 2 | j | → 0 |
| 1 | i | → (2<sup>30</sup>) - 1 |
| 0 | h | 3 |
We end up allocating another value on the heap, and so we have to subtract one
from (2<sup>30</sup>) - 1. Its easier to write that than `1,073,741,822`. In any
case, we set up the variables as usual.
At the end of `bar()`, it calls `baz()`:
| Address | Name | Value |
|----------------------|------|------------------------|
| (2<sup>30</sup>) - 1 | | 20 |
| (2<sup>30</sup>) - 2 | | 5 |
| ... | ... | ... |
| 12 | g | 100 |
| 11 | f | → (2<sup>30</sup>) - 2 |
| 10 | e | → 9 |
| 9 | d | → (2<sup>30</sup>) - 2 |
| 8 | c | 5 |
| 7 | b | → 4 |
| 6 | a | → 0 |
| 5 | z | → 4 |
| 4 | y | 10 |
| 3 | x | → 0 |
| 2 | j | → 0 |
| 1 | i | → (2<sup>30</sup>) - 1 |
| 0 | h | 3 |
With this, were at our deepest point! Whew! Congrats for following along this
far.
After `baz()` is over, we get rid of `f` and `g`:
| Address | Name | Value |
|----------------------|------|------------------------|
| (2<sup>30</sup>) - 1 | | 20 |
| (2<sup>30</sup>) - 2 | | 5 |
| ... | ... | ... |
| 10 | e | → 9 |
| 9 | d | → (2<sup>30</sup>) - 2 |
| 8 | c | 5 |
| 7 | b | → 4 |
| 6 | a | → 0 |
| 5 | z | → 4 |
| 4 | y | 10 |
| 3 | x | → 0 |
| 2 | j | → 0 |
| 1 | i | → (2<sup>30</sup>) - 1 |
| 0 | h | 3 |
Next, we return from `bar()`. `d` in this case is a `Box<T>`, so it also frees
what it points to: (2<sup>30</sup>) - 2.
| Address | Name | Value |
|----------------------|------|------------------------|
| (2<sup>30</sup>) - 1 | | 20 |
| ... | ... | ... |
| 5 | z | → 4 |
| 4 | y | 10 |
| 3 | x | → 0 |
| 2 | j | → 0 |
| 1 | i | → (2<sup>30</sup>) - 1 |
| 0 | h | 3 |
And after that, `foo()` returns:
| Address | Name | Value |
|----------------------|------|------------------------|
| (2<sup>30</sup>) - 1 | | 20 |
| ... | ... | ... |
| 2 | j | → 0 |
| 1 | i | → (2<sup>30</sup>) - 1 |
| 0 | h | 3 |
And then, finally, `main()`, which cleans the rest up. When `i` is `Drop`ped,
it will clean up the last of the heap too.
# What do other languages do?
Most languages with a garbage collector heap-allocate by default. This means
that every value is boxed. There are a number of reasons why this is done, but
theyre out of scope for this tutorial. There are some possible optimizations
that dont make it true 100% of the time, too. Rather than relying on the stack
and `Drop` to clean up memory, the garbage collector deals with the heap
instead.
# Which to use?
So if the stack is faster and easier to manage, why do we need the heap? A big
reason is that Stack-allocation alone means you only have 'Last In First Out (LIFO)' semantics for
reclaiming storage. Heap-allocation is strictly more general, allowing storage
to be taken from and returned to the pool in arbitrary order, but at a
complexity cost.
Generally, you should prefer stack allocation, and so, Rust stack-allocates by
default. The LIFO model of the stack is simpler, at a fundamental level. This
has two big impacts: runtime efficiency and semantic impact.
## Runtime Efficiency
Managing the memory for the stack is trivial: The machine
increments or decrements a single value, the so-called “stack pointer”.
Managing memory for the heap is non-trivial: heap-allocated memory is freed at
arbitrary points, and each block of heap-allocated memory can be of arbitrary
size, so the memory manager must generally work much harder to
identify memory for reuse.
If youd like to dive into this topic in greater detail, [this paper][wilson]
is a great introduction.
[wilson]: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.143.4688
## Semantic impact
Stack-allocation impacts the Rust language itself, and thus the developers
mental model. The LIFO semantics is what drives how the Rust language handles
automatic memory management. Even the deallocation of a uniquely-owned
heap-allocated box can be driven by the stack-based LIFO semantics, as
discussed throughout this chapter. The flexibility (i.e. expressiveness) of non
LIFO-semantics means that in general the compiler cannot automatically infer at
compile-time where memory should be freed; it has to rely on dynamic protocols,
potentially from outside the language itself, to drive deallocation (reference
counting, as used by `Rc<T>` and `Arc<T>`, is one example of this).
When taken to the extreme, the increased expressive power of heap allocation
comes at the cost of either significant runtime support (e.g. in the form of a
garbage collector) or significant programmer effort (in the form of explicit
memory management calls that require verification not provided by the Rust
compiler).
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/the-stack-and-the-heap.html).

View File

@ -1,335 +1,10 @@
# 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
two major forms of dispatch: static dispatch and dynamic dispatch. While Rust
favors static dispatch, it also supports dynamic dispatch through a mechanism
called trait objects.
The first edition of the book is no longer distributed with Rust's documentation.
## Background
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
For the rest of this chapter, well need a trait and some implementations.
Lets make a simple one, `Foo`. It has one method that is expected to return a
`String`.
```rust
trait Foo {
fn method(&self) -> String;
}
```
Well also implement this trait for `u8` and `String`:
```rust
# trait Foo { fn method(&self) -> String; }
impl Foo for u8 {
fn method(&self) -> String { format!("u8: {}", *self) }
}
impl Foo for String {
fn method(&self) -> String { format!("string: {}", *self) }
}
```
## Static dispatch
We can use this trait to perform static dispatch with trait bounds:
```rust
# trait Foo { fn method(&self) -> String; }
# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } }
# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } }
fn do_something<T: Foo>(x: T) {
x.method();
}
fn main() {
let x = 5u8;
let y = "Hello".to_string();
do_something(x);
do_something(y);
}
```
Rust uses monomorphization to perform static dispatch here. This means that
Rust will create a special version of `do_something()` for both `u8` and
`String`, and then replace the call sites with calls to these specialized
functions. In other words, Rust generates something like this:
```rust
# trait Foo { fn method(&self) -> String; }
# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } }
# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } }
fn do_something_u8(x: u8) {
x.method();
}
fn do_something_string(x: String) {
x.method();
}
fn main() {
let x = 5u8;
let y = "Hello".to_string();
do_something_u8(x);
do_something_string(y);
}
```
This has a great upside: static dispatch allows function calls to be
inlined because the callee is known at compile time, and inlining is
the key to good optimization. Static dispatch is fast, but it comes at
a tradeoff: code bloat, due to many copies of the same function
existing in the binary, one for each type.
Furthermore, compilers arent perfect and may “optimize” code to become slower.
For example, functions inlined too eagerly will bloat the instruction cache
(cache rules everything around us). This is part of the reason that `#[inline]`
and `#[inline(always)]` should be used carefully, and one reason why using a
dynamic dispatch is sometimes more efficient.
However, the common case is that it is more efficient to use static dispatch,
and one can always have a thin statically-dispatched wrapper function that does
a dynamic dispatch, but not vice versa, meaning static calls are more flexible.
The standard library tries to be statically dispatched where possible for this
reason.
## Dynamic dispatch
Rust provides dynamic dispatch through a feature called trait objects. Trait
objects, like `&Foo` or `Box<Foo>`, are normal values that store a value of
*any* type that implements the given trait, where the precise type can only be
known at runtime.
A trait object can be obtained from a pointer to a concrete type that
implements the trait by *casting* it (e.g. `&x as &Foo`) or *coercing* it
(e.g. using `&x` as an argument to a function that takes `&Foo`).
These trait object coercions and casts also work for pointers like `&mut T` to
`&mut Foo` and `Box<T>` to `Box<Foo>`, but thats all at the moment. Coercions
and casts are identical.
This operation can be seen as erasing the compilers knowledge about the
specific type of the pointer, and hence trait objects are sometimes referred to
as type erasure.
Coming back to the example above, we can use the same trait to perform dynamic
dispatch with trait objects by casting:
```rust
# trait Foo { fn method(&self) -> String; }
# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } }
# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } }
fn do_something(x: &Foo) {
x.method();
}
fn main() {
let x = 5u8;
do_something(&x as &Foo);
}
```
or by coercing:
```rust
# trait Foo { fn method(&self) -> String; }
# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } }
# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } }
fn do_something(x: &Foo) {
x.method();
}
fn main() {
let x = "Hello".to_string();
do_something(&x);
}
```
A function that takes a trait object is not specialized to each of the types
that implements `Foo`: only one copy is generated, often (but not always)
resulting in less code bloat. However, this comes at the cost of requiring
slower virtual function calls, and effectively inhibiting any chance of
inlining and related optimizations from occurring.
### Why pointers?
Rust does not put things behind a pointer by default, unlike many managed
languages, so types can have different sizes. Knowing the size of the value at
compile time is important for things like passing it as an argument to a
function, moving it about on the stack and allocating (and deallocating) space
on the heap to store it.
For `Foo`, we would need to have a value that could be at least either a
`String` (24 bytes) or a `u8` (1 byte), as well as any other type for which
dependent crates may implement `Foo` (any number of bytes at all). Theres no
way to guarantee that this last point can work if the values are stored without
a pointer, because those other types can be arbitrarily large.
Putting the value behind a pointer means the size of the value is not relevant
when we are tossing a trait object around, only the size of the pointer itself.
### Representation
The methods of the trait can be called on a trait object via a special record
of function pointers traditionally called a vtable (created and managed by
the compiler).
Trait objects are both simple and complicated: their core representation and
layout is quite straight-forward, but there are some curly error messages and
surprising behaviors to discover.
Lets start simple, with the runtime representation of a trait object. The
`std::raw` module contains structs with layouts that are the same as the
complicated built-in types, [including trait objects][stdraw]:
```rust
# mod foo {
pub struct TraitObject {
pub data: *mut (),
pub vtable: *mut (),
}
# }
```
[stdraw]: ../../std/raw/struct.TraitObject.html
That is, a trait object like `&Foo` consists of a data pointer and a vtable
pointer.
The data pointer addresses the data (of some unknown type `T`) that the trait
object is storing, and the vtable pointer points to the vtable (virtual method
table) corresponding to the implementation of `Foo` for `T`.
A vtable is essentially a struct of function pointers, pointing to the concrete
piece of machine code for each method in the implementation. A method call like
`trait_object.method()` will retrieve the correct pointer out of the vtable and
then do a dynamic call of it. For example:
```rust,ignore
struct FooVtable {
destructor: fn(*mut ()),
size: usize,
align: usize,
method: fn(*const ()) -> String,
}
// u8:
fn call_method_on_u8(x: *const ()) -> String {
// The compiler guarantees that this function is only called
// with `x` pointing to a u8.
let byte: &u8 = unsafe { &*(x as *const u8) };
byte.method()
}
static Foo_for_u8_vtable: FooVtable = FooVtable {
destructor: /* compiler magic */,
size: 1,
align: 1,
// Cast to a function pointer:
method: call_method_on_u8 as fn(*const ()) -> String,
};
// String:
fn call_method_on_String(x: *const ()) -> String {
// The compiler guarantees that this function is only called
// with `x` pointing to a String.
let string: &String = unsafe { &*(x as *const String) };
string.method()
}
static Foo_for_String_vtable: FooVtable = FooVtable {
destructor: /* compiler magic */,
// Values for a 64-bit computer, halve them for 32-bit ones.
size: 24,
align: 8,
method: call_method_on_String as fn(*const ()) -> String,
};
```
The `destructor` field in each vtable points to a function that will clean up
any resources of the vtables type: for `u8` it is trivial, but for `String` it
will free the memory. This is necessary for owning trait objects like
`Box<Foo>`, which need to clean-up both the `Box` allocation as well as the
internal type when they go out of scope. The `size` and `align` fields store
the size of the erased type, and its alignment requirements.
Suppose weve got some values that implement `Foo`. The explicit form of
construction and use of `Foo` trait objects might look a bit like (ignoring the
type mismatches: theyre all pointers anyway):
```rust,ignore
let a: String = "foo".to_string();
let x: u8 = 1;
// let b: &Foo = &a;
let b = TraitObject {
// Store the data:
data: &a,
// Store the methods:
vtable: &Foo_for_String_vtable
};
// let y: &Foo = x;
let y = TraitObject {
// Store the data:
data: &x,
// Store the methods:
vtable: &Foo_for_u8_vtable
};
// b.method();
(b.vtable.method)(b.data);
// y.method();
(y.vtable.method)(y.data);
```
## Object Safety
Not every trait can be used to make a trait object. For example, vectors implement
`Clone`, but if we try to make a trait object:
```rust,ignore
let v = vec![1, 2, 3];
let o = &v as &Clone;
```
We get an error:
```text
error: cannot convert to a trait object because trait `core::clone::Clone` is not object-safe [E0038]
let o = &v as &Clone;
^~
note: the trait cannot require that `Self : Sized`
let o = &v as &Clone;
^~
```
The error says that `Clone` is not object-safe. Only traits that are
object-safe can be made into trait objects. A trait is object-safe if both of
these are true:
* the trait does not require that `Self: Sized`
* all of its methods are object-safe
So what makes a method object-safe? Each method must require that `Self: Sized`
or all of the following:
* must not have any type parameters
* must not use `Self`
Whew! As we can see, almost all of these rules talk about `Self`. A good intuition
is “except in special circumstances, if your traits method uses `Self`, it is not
object-safe.”
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/trait-objects.html).

View File

@ -1,551 +1,10 @@
# Traits
A trait is a language feature that tells the Rust compiler about
functionality a type must provide.
The first edition of the book is no longer distributed with Rust's documentation.
Recall the `impl` keyword, used to call a function with [method
syntax][methodsyntax]:
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
```rust
struct Circle {
x: f64,
y: f64,
radius: f64,
}
impl Circle {
fn area(&self) -> f64 {
std::f64::consts::PI * (self.radius * self.radius)
}
}
```
[methodsyntax]: method-syntax.html
Traits are similar, except that we first define a trait with a method
signature, then implement the trait for a type. In this example, we implement the trait `HasArea` for `Circle`:
```rust
struct Circle {
x: f64,
y: f64,
radius: f64,
}
trait HasArea {
fn area(&self) -> f64;
}
impl HasArea for Circle {
fn area(&self) -> f64 {
std::f64::consts::PI * (self.radius * self.radius)
}
}
```
As you can see, the `trait` block looks very similar to the `impl` block,
but we dont define a body, only a type signature. When we `impl` a trait,
we use `impl Trait for Item`, rather than only `impl Item`.
`Self` may be used in a type annotation to refer to an instance of the type
implementing this trait passed as a parameter. `Self`, `&Self` or `&mut Self`
may be used depending on the level of ownership required.
```rust
struct Circle {
x: f64,
y: f64,
radius: f64,
}
trait HasArea {
fn area(&self) -> f64;
fn is_larger(&self, &Self) -> bool;
}
impl HasArea for Circle {
fn area(&self) -> f64 {
std::f64::consts::PI * (self.radius * self.radius)
}
fn is_larger(&self, other: &Self) -> bool {
self.area() > other.area()
}
}
```
## Trait bounds on generic functions
Traits are useful because they allow a type to make certain promises about its
behavior. Generic functions can exploit this to constrain, or [bound][bounds], the types they
accept. Consider this function, which does not compile:
[bounds]: glossary.html#bounds
```rust,ignore
fn print_area<T>(shape: T) {
println!("This shape has an area of {}", shape.area());
}
```
Rust complains:
```text
error: no method named `area` found for type `T` in the current scope
```
Because `T` can be any type, we cant be sure that it implements the `area`
method. But we can add a trait bound to our generic `T`, ensuring
that it does:
```rust
# trait HasArea {
# fn area(&self) -> f64;
# }
fn print_area<T: HasArea>(shape: T) {
println!("This shape has an area of {}", shape.area());
}
```
The syntax `<T: HasArea>` means “any type that implements the `HasArea` trait.”
Because traits define function type signatures, we can be sure that any type
which implements `HasArea` will have an `.area()` method.
Heres an extended example of how this works:
```rust
trait HasArea {
fn area(&self) -> f64;
}
struct Circle {
x: f64,
y: f64,
radius: f64,
}
impl HasArea for Circle {
fn area(&self) -> f64 {
std::f64::consts::PI * (self.radius * self.radius)
}
}
struct Square {
x: f64,
y: f64,
side: f64,
}
impl HasArea for Square {
fn area(&self) -> f64 {
self.side * self.side
}
}
fn print_area<T: HasArea>(shape: T) {
println!("This shape has an area of {}", shape.area());
}
fn main() {
let c = Circle {
x: 0.0f64,
y: 0.0f64,
radius: 1.0f64,
};
let s = Square {
x: 0.0f64,
y: 0.0f64,
side: 1.0f64,
};
print_area(c);
print_area(s);
}
```
This program outputs:
```text
This shape has an area of 3.141593
This shape has an area of 1
```
As you can see, `print_area` is now generic, but also ensures that we have
passed in the correct types. If we pass in an incorrect type:
```rust,ignore
print_area(5);
```
We get a compile-time error:
```text
error: the trait bound `_ : HasArea` is not satisfied [E0277]
```
## Trait bounds on generic structs
Your generic structs can also benefit from trait bounds. All you need to
do is append the bound when you declare type parameters. Here is a new
type `Rectangle<T>` and its operation `is_square()`:
```rust
struct Rectangle<T> {
x: T,
y: T,
width: T,
height: T,
}
impl<T: PartialEq> Rectangle<T> {
fn is_square(&self) -> bool {
self.width == self.height
}
}
fn main() {
let mut r = Rectangle {
x: 0,
y: 0,
width: 47,
height: 47,
};
assert!(r.is_square());
r.height = 42;
assert!(!r.is_square());
}
```
`is_square()` needs to check that the sides are equal, so the sides must be of
a type that implements the [`core::cmp::PartialEq`][PartialEq] trait:
```rust,ignore
impl<T: PartialEq> Rectangle<T> { ... }
```
Now, a rectangle can be defined in terms of any type that can be compared for
equality.
[PartialEq]: ../../core/cmp/trait.PartialEq.html
Here we defined a new struct `Rectangle` that accepts numbers of any
precision—really, objects of pretty much any type—as long as they can be
compared for equality. Could we do the same for our `HasArea` structs, `Square`
and `Circle`? Yes, but they need multiplication, and to work with that we need
to know more about [operator traits][operators-and-overloading].
[operators-and-overloading]: operators-and-overloading.html
# Rules for implementing traits
So far, weve only added trait implementations to structs, but you can
implement a trait for any type such as `f32`:
```rust
trait ApproxEqual {
fn approx_equal(&self, other: &Self) -> bool;
}
impl ApproxEqual for f32 {
fn approx_equal(&self, other: &Self) -> bool {
// Appropriate for `self` and `other` being close to 1.0.
(self - other).abs() <= ::std::f32::EPSILON
}
}
println!("{}", 1.0.approx_equal(&1.00000001));
```
This may seem like the Wild West, but there are two restrictions around
implementing traits that prevent this from getting out of hand. The first is
that if the trait isnt defined in your scope, it doesnt apply. Heres an
example: the standard library provides a [`Write`][write] trait which adds
extra functionality to `File`s, for doing file I/O. By default, a `File`
wont have its methods:
[write]: ../../std/io/trait.Write.html
```rust,ignore
let mut f = std::fs::File::create("foo.txt").expect("Couldnt create foo.txt");
let buf = b"whatever"; // buf: &[u8; 8], a byte string literal.
let result = f.write(buf);
# result.unwrap(); // Ignore the error.
```
Heres the error:
```text
error: type `std::fs::File` does not implement any method in scope named `write`
let result = f.write(buf);
^~~~~~~~~~
```
We need to `use` the `Write` trait first:
```rust,no_run
use std::io::Write;
let mut f = std::fs::File::create("foo.txt").expect("Couldnt create foo.txt");
let buf = b"whatever";
let result = f.write(buf);
# result.unwrap(); // Ignore the error.
```
This will compile without error.
This means that even if someone does something bad like add methods to `i32`,
it wont affect you, unless you `use` that trait.
Theres one more restriction on implementing traits: either the trait
or the type youre implementing it for must be defined by you. Or more
precisely, one of them must be defined in the same crate as the `impl`
you're writing. For more on Rust's module and package system, see the
chapter on [crates and modules][cm].
So, we could implement the `HasArea` type for `i32`, because we defined
`HasArea` in our code. But if we tried to implement `ToString`, a trait
provided by Rust, for `i32`, we could not, because neither the trait nor
the type are defined in our crate.
One last thing about traits: generic functions with a trait bound use
monomorphization (mono: one, morph: form), so they are statically dispatched.
Whats that mean? Check out the chapter on [trait objects][to] for more details.
[cm]: crates-and-modules.html
[to]: trait-objects.html
# Multiple trait bounds
Youve seen that you can bound a generic type parameter with a trait:
```rust
fn foo<T: Clone>(x: T) {
x.clone();
}
```
If you need more than one bound, you can use `+`:
```rust
use std::fmt::Debug;
fn foo<T: Clone + Debug>(x: T) {
x.clone();
println!("{:?}", x);
}
```
`T` now needs to be both `Clone` as well as `Debug`.
# Where clause
Writing functions with only a few generic types and a small number of trait
bounds isnt too bad, but as the number increases, the syntax gets increasingly
awkward:
```rust
use std::fmt::Debug;
fn foo<T: Clone, K: Clone + Debug>(x: T, y: K) {
x.clone();
y.clone();
println!("{:?}", y);
}
```
The name of the function is on the far left, and the parameter list is on the
far right. The bounds are getting in the way.
Rust has a solution, and its called a `where` clause:
```rust
use std::fmt::Debug;
fn foo<T: Clone, K: Clone + Debug>(x: T, y: K) {
x.clone();
y.clone();
println!("{:?}", y);
}
fn bar<T, K>(x: T, y: K) where T: Clone, K: Clone + Debug {
x.clone();
y.clone();
println!("{:?}", y);
}
fn main() {
foo("Hello", "world");
bar("Hello", "world");
}
```
`foo()` uses the syntax we showed earlier, and `bar()` uses a `where` clause.
All you need to do is leave off the bounds when defining your type parameters,
and then add `where` after the parameter list. For longer lists, whitespace can
be added:
```rust
use std::fmt::Debug;
fn bar<T, K>(x: T, y: K)
where T: Clone,
K: Clone + Debug {
x.clone();
y.clone();
println!("{:?}", y);
}
```
This flexibility can add clarity in complex situations.
`where` is also more powerful than the simpler syntax. For example:
```rust
trait ConvertTo<Output> {
fn convert(&self) -> Output;
}
impl ConvertTo<i64> for i32 {
fn convert(&self) -> i64 { *self as i64 }
}
// Can be called with T == i32.
fn convert_t_to_i64<T: ConvertTo<i64>>(x: T) -> i64 {
x.convert()
}
// Can be called with T == i64.
fn convert_i32_to_t<T>(x: i32) -> T
// This is using ConvertTo as if it were "ConvertTo<i64>".
where i32: ConvertTo<T> {
x.convert()
}
```
This shows off the additional feature of `where` clauses: they allow bounds
on the left-hand side not only of type parameters `T`, but also of types (`i32` in this case). In this example, `i32` must implement
`ConvertTo<T>`. Rather than defining what `i32` is (since that's obvious), the
`where` clause here constrains `T`.
# Default methods
A default method can be added to a trait definition if it is already known how a typical implementor will define a method. For example, `is_invalid()` is defined as the opposite of `is_valid()`:
```rust
trait Foo {
fn is_valid(&self) -> bool;
fn is_invalid(&self) -> bool { !self.is_valid() }
}
```
Implementors of the `Foo` trait need to implement `is_valid()` but not `is_invalid()` due to the added default behavior. This default behavior can still be overridden as in:
```rust
# trait Foo {
# fn is_valid(&self) -> bool;
#
# fn is_invalid(&self) -> bool { !self.is_valid() }
# }
struct UseDefault;
impl Foo for UseDefault {
fn is_valid(&self) -> bool {
println!("Called UseDefault.is_valid.");
true
}
}
struct OverrideDefault;
impl Foo for OverrideDefault {
fn is_valid(&self) -> bool {
println!("Called OverrideDefault.is_valid.");
true
}
fn is_invalid(&self) -> bool {
println!("Called OverrideDefault.is_invalid!");
true // Overrides the expected value of `is_invalid()`.
}
}
let default = UseDefault;
assert!(!default.is_invalid()); // Prints "Called UseDefault.is_valid."
let over = OverrideDefault;
assert!(over.is_invalid()); // Prints "Called OverrideDefault.is_invalid!"
```
# Inheritance
Sometimes, implementing a trait requires implementing another trait:
```rust
trait Foo {
fn foo(&self);
}
trait FooBar : Foo {
fn foobar(&self);
}
```
Implementors of `FooBar` must also implement `Foo`, like this:
```rust
# trait Foo {
# fn foo(&self);
# }
# trait FooBar : Foo {
# fn foobar(&self);
# }
struct Baz;
impl Foo for Baz {
fn foo(&self) { println!("foo"); }
}
impl FooBar for Baz {
fn foobar(&self) { println!("foobar"); }
}
```
If we forget to implement `Foo`, Rust will tell us:
```text
error: the trait bound `main::Baz : main::Foo` is not satisfied [E0277]
```
# Deriving
Implementing traits like `Debug` and `Default` repeatedly can become
quite tedious. For that reason, Rust provides an [attribute][attributes] that
allows you to let Rust automatically implement traits for you:
```rust
#[derive(Debug)]
struct Foo;
fn main() {
println!("{:?}", Foo);
}
```
[attributes]: attributes.html
However, deriving is limited to a certain set of traits:
- [`Clone`](../../core/clone/trait.Clone.html)
- [`Copy`](../../core/marker/trait.Copy.html)
- [`Debug`](../../core/fmt/trait.Debug.html)
- [`Default`](../../core/default/trait.Default.html)
- [`Eq`](../../core/cmp/trait.Eq.html)
- [`Hash`](../../core/hash/trait.Hash.html)
- [`Ord`](../../core/cmp/trait.Ord.html)
- [`PartialEq`](../../core/cmp/trait.PartialEq.html)
- [`PartialOrd`](../../core/cmp/trait.PartialOrd.html)
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/traits.html).

View File

@ -1,78 +1,10 @@
# Type Aliases
The `type` keyword lets you declare an alias of another type:
The first edition of the book is no longer distributed with Rust's documentation.
```rust
type Name = String;
```
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
You can then use this type as if it were a real type:
```rust
type Name = String;
let x: Name = "Hello".to_string();
```
Note, however, that this is an _alias_, not a new type entirely. In other
words, because Rust is strongly typed, youd expect a comparison between two
different types to fail:
```rust,ignore
let x: i32 = 5;
let y: i64 = 5;
if x == y {
// ...
}
```
this gives
```text
error: mismatched types:
expected `i32`,
found `i64`
(expected i32,
found i64) [E0308]
if x == y {
^
```
But, if we had an alias:
```rust
type Num = i32;
let x: i32 = 5;
let y: Num = 5;
if x == y {
// ...
}
```
This compiles without error. Values of a `Num` type are the same as a value of
type `i32`, in every way. You can use [tuple struct] to really get a new type.
[tuple struct]: structs.html#tuple-structs
You can also use type aliases with generics:
```rust
use std::result;
enum ConcreteError {
Foo,
Bar,
}
type Result<T> = result::Result<T, ConcreteError>;
```
This creates a specialized version of the `Result` type, which always has a
`ConcreteError` for the `E` part of `Result<T, E>`. This is commonly used
in the standard library to create custom errors for each subsection. For
example, [io::Result][ioresult].
[ioresult]: ../../std/io/type.Result.html
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/type-aliases.html).

View File

@ -1,136 +1,10 @@
# Universal Function Call Syntax
Sometimes, functions can have the same names. Consider this code:
The first edition of the book is no longer distributed with Rust's documentation.
```rust
trait Foo {
fn f(&self);
}
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
trait Bar {
fn f(&self);
}
struct Baz;
impl Foo for Baz {
fn f(&self) { println!("Bazs impl of Foo"); }
}
impl Bar for Baz {
fn f(&self) { println!("Bazs impl of Bar"); }
}
let b = Baz;
```
If we were to try to call `b.f()`, wed get an error:
```text
error: multiple applicable methods in scope [E0034]
b.f();
^~~
note: candidate #1 is defined in an impl of the trait `main::Foo` for the type
`main::Baz`
fn f(&self) { println!("Bazs impl of Foo"); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: candidate #2 is defined in an impl of the trait `main::Bar` for the type
`main::Baz`
fn f(&self) { println!("Bazs impl of Bar"); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
We need a way to disambiguate which method we need. This feature is called
universal function call syntax, and it looks like this:
```rust
# trait Foo {
# fn f(&self);
# }
# trait Bar {
# fn f(&self);
# }
# struct Baz;
# impl Foo for Baz {
# fn f(&self) { println!("Bazs impl of Foo"); }
# }
# impl Bar for Baz {
# fn f(&self) { println!("Bazs impl of Bar"); }
# }
# let b = Baz;
Foo::f(&b);
Bar::f(&b);
```
Lets break it down.
```rust,ignore
Foo::
Bar::
```
These halves of the invocation are the types of the two traits: `Foo` and
`Bar`. This is what ends up actually doing the disambiguation between the two:
Rust calls the one from the trait name you use.
```rust,ignore
f(&b)
```
When we call a method like `b.f()` using [method syntax][methodsyntax], Rust
will automatically borrow `b` if `f()` takes `&self`. In this case, Rust will
not, and so we need to pass an explicit `&b`.
[methodsyntax]: method-syntax.html
# Angle-bracket Form
The form of UFCS we just talked about:
```rust,ignore
Trait::method(args);
```
Is a short-hand. Theres an expanded form of this thats needed in some
situations:
```rust,ignore
<Type as Trait>::method(args);
```
The `<>::` syntax is a means of providing a type hint. The type goes inside
the `<>`s. In this case, the type is `Type as Trait`, indicating that we want
`Trait`s version of `method` to be called here. The `as Trait` part is
optional if its not ambiguous. Same with the angle brackets, hence the
shorter form.
Heres an example of using the longer form.
```rust
trait Foo {
fn foo() -> i32;
}
struct Bar;
impl Bar {
fn foo() -> i32 {
20
}
}
impl Foo for Bar {
fn foo() -> i32 {
10
}
}
fn main() {
assert_eq!(10, <Bar as Foo>::foo());
assert_eq!(20, Bar::foo());
}
```
Using the angle bracket syntax lets you call the trait method instead of the
inherent one.
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/ufcs.html).

View File

@ -1,142 +1,10 @@
# Unsafe
Rusts main draw is its powerful static guarantees about behavior. But safety
checks are conservative by nature: there are some programs that are actually
safe, but the compiler is not able to verify this is true. To write these kinds
of programs, we need to tell the compiler to relax its restrictions a bit. For
this, Rust has a keyword, `unsafe`. Code using `unsafe` has fewer restrictions
than normal code does.
The first edition of the book is no longer distributed with Rust's documentation.
Lets go over the syntax, and then well talk semantics. `unsafe` is used in
four contexts. The first one is to mark a function as unsafe:
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
```rust
unsafe fn danger_will_robinson() {
// Scary stuff...
}
```
All functions called from [FFI][ffi] must be marked as `unsafe`, for example.
The second use of `unsafe` is an unsafe block:
[ffi]: ffi.html
```rust
unsafe {
// Scary stuff...
}
```
The third is for unsafe traits:
```rust
unsafe trait Scary { }
```
And the fourth is for `impl`ementing one of those traits:
```rust
# unsafe trait Scary { }
unsafe impl Scary for i32 {}
```
Its important to be able to explicitly delineate code that may have bugs that
cause big problems. If a Rust program segfaults, you can be sure the cause is
related to something marked `unsafe`.
# What does safe mean?
Safe, in the context of Rust, means doesnt do anything unsafe. Its also
important to know that there are certain behaviors that are probably not
desirable in your code, but are expressly _not_ unsafe:
* Deadlocks
* Leaks of memory or other resources
* Exiting without calling destructors
* Integer overflow
Rust cannot prevent all kinds of software problems. Buggy code can and will be
written in Rust. These things arent great, but they dont qualify as `unsafe`
specifically.
In addition, the following are all undefined behaviors in Rust, and must be
avoided, even when writing `unsafe` code:
* Data races
* Dereferencing a NULL/dangling raw pointer
* Reads of [undef][undef] (uninitialized) memory
* Breaking the [pointer aliasing rules][aliasing] with raw pointers.
* `&mut T` and `&T` follow LLVMs scoped [noalias][noalias] model, except if
the `&T` contains an `UnsafeCell<U>`. Unsafe code must not violate these
aliasing guarantees.
* Mutating an immutable value/reference without `UnsafeCell<U>`
* Invoking undefined behavior via compiler intrinsics:
* Indexing outside of the bounds of an object with `std::ptr::offset`
(`offset` intrinsic), with
the exception of one byte past the end which is permitted.
* Using `std::ptr::copy_nonoverlapping_memory` (`memcpy32`/`memcpy64`
intrinsics) on overlapping buffers
* Invalid values in primitive types, even in private fields/locals:
* NULL/dangling references or boxes
* A value other than `false` (0) or `true` (1) in a `bool`
* A discriminant in an `enum` not included in its type definition
* A value in a `char` which is a surrogate or above `char::MAX`
* Non-UTF-8 byte sequences in a `str`
* Unwinding into Rust from foreign code or unwinding from Rust into foreign
code.
[noalias]: http://llvm.org/docs/LangRef.html#noalias
[undef]: http://llvm.org/docs/LangRef.html#undefined-values
[aliasing]: http://llvm.org/docs/LangRef.html#pointer-aliasing-rules
# Unsafe Superpowers
In both unsafe functions and unsafe blocks, Rust will let you do three things
that you normally can not do. Just three. Here they are:
1. Access or update a [static mutable variable][static].
2. Dereference a raw pointer.
3. Call unsafe functions. This is the most powerful ability.
Thats it. Its important that `unsafe` does not, for example, turn off the
borrow checker. Adding `unsafe` to some random Rust code doesnt change its
semantics, it wont start accepting anything. But it will let you write
things that _do_ break some of the rules.
You will also encounter the `unsafe` keyword when writing bindings to foreign
(non-Rust) interfaces. You're encouraged to write a safe, native Rust interface
around the methods provided by the library.
Lets go over the basic three abilities listed, in order.
## Access or update a `static mut`
Rust has a feature called `static mut` which allows for mutable global state.
Doing so can cause a data race, and as such is inherently not safe. For more
details, see the [static][static] section of the book.
[static]: const-and-static.html#static
## Dereference a raw pointer
Raw pointers let you do arbitrary pointer arithmetic, and can cause a number of
different memory safety and security issues. In some senses, the ability to
dereference an arbitrary pointer is one of the most dangerous things you can
do. For more on raw pointers, see [their section of the book][rawpointers].
[rawpointers]: raw-pointers.html
## Call unsafe functions
This last ability works with both aspects of `unsafe`: you can only call
functions marked `unsafe` from inside an unsafe block.
This ability is powerful and varied. Rust exposes some [compiler
intrinsics][intrinsics] as unsafe functions, and some unsafe functions bypass
safety checks, trading safety for speed.
Ill repeat again: even though you _can_ do arbitrary things in unsafe blocks
and functions doesnt mean you should. The compiler will act as though youre
upholding its invariants, so be careful!
[intrinsics]: ../../unstable-book/language-features/intrinsics.html
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/unsafe.html).

View File

@ -1,61 +1,10 @@
# Unsized Types
Most types have a particular size, in bytes, that is knowable at compile time.
For example, an `i32` is thirty-two bits big, or four bytes. However, there are
some types which are useful to express, but do not have a defined size. These are
called unsized or dynamically sized types. One example is `[T]`. This type
represents a certain number of `T` in sequence. But we dont know how many
there are, so the size is not known.
The first edition of the book is no longer distributed with Rust's documentation.
Rust understands a few of these types, but they have some restrictions. There
are three:
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
1. We can only manipulate an instance of an unsized type via a pointer. An
`&[T]` works fine, but a `[T]` does not.
2. Variables and arguments cannot have dynamically sized types.
3. Only the last field in a `struct` may have a dynamically sized type; the
other fields must not. Enum variants must not have dynamically sized types as
data.
So why bother? Well, because `[T]` can only be used behind a pointer, if we
didnt have language support for unsized types, it would be impossible to write
this:
```rust,ignore
impl Foo for str {
```
or
```rust,ignore
impl<T> Foo for [T] {
```
Instead, you would have to write:
```rust,ignore
impl Foo for &str {
```
Meaning, this implementation would only work for [references][ref], and not
other types of pointers. With the `impl for str`, all pointers, including (at
some point, there are some bugs to fix first) user-defined custom smart
pointers, can use this `impl`.
[ref]: references-and-borrowing.html
# ?Sized
If you want to write a function that accepts a dynamically sized type, you
can use the special bound syntax, `?Sized`:
```rust
struct Foo<T: ?Sized> {
f: T,
}
```
This `?Sized`, read as “T may or may not be `Sized`”, which allows us to match
both sized and unsized types. All generic type parameters implicitly
have the `Sized` bound, so the `?Sized` can be used to opt-out of the implicit
bound.
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/unsized-types.html).

View File

@ -1,44 +1,10 @@
# Using Rust Without the Standard Library
Rusts standard library provides a lot of useful functionality, but assumes
support for various features of its host system: threads, networking, heap
allocation, and others. There are systems that do not have these features,
however, and Rust can work with those too! To do so, we tell Rust that we
dont want to use the standard library via an attribute: `#![no_std]`.
The first edition of the book is no longer distributed with Rust's documentation.
> Note: This feature is technically stable, but there are some caveats. For
> one, you can build a `#![no_std]` _library_ on stable, but not a _binary_.
> For details on binaries without the standard library, see [the nightly
> chapter on 'lang items'][unstable book lang items]
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
To use `#![no_std]`, add it to your crate root:
```rust,ignore
#![no_std]
fn plus_one(x: i32) -> i32 {
x + 1
}
```
Much of the functionality thats exposed in the standard library is also
available via the [`core` crate](../../core/index.html). When were using the
standard library, Rust automatically brings `std` into scope, allowing you to
use its features without an explicit import. By the same token, when using
`#![no_std]`, Rust will bring `core` into scope for you, as well as [its
prelude](../../core/prelude/v1/index.html). This means that a lot of code will Just
Work:
```rust,ignore
#![no_std]
fn may_fail(failure: bool) -> Result<(), &'static str> {
if failure {
Err("this didnt work!")
} else {
Ok(())
}
}
```
[unstable book lang items]: ../../unstable-book/language-features/lang-items.html#using-libc
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/using-rust-without-the-standard-library.html).

View File

@ -1,256 +1,10 @@
# Variable Bindings
Virtually every non-'Hello World Rust program uses *variable bindings*. They
bind some value to a name, so it can be used later. `let` is
used to introduce a binding, like this:
The first edition of the book is no longer distributed with Rust's documentation.
```rust
fn main() {
let x = 5;
}
```
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
Putting `fn main() {` in each example is a bit tedious, so well leave that out
in the future. If youre following along, make sure to edit your `main()`
function, rather than leaving it off. Otherwise, youll get an error.
# Patterns
In many languages, a variable binding would be called a *variable*, but Rusts
variable bindings have a few tricks up their sleeves. For example the
left-hand side of a `let` statement is a [pattern][pattern], not a
variable name. This means we can do things like:
```rust
let (x, y) = (1, 2);
```
After this statement is evaluated, `x` will be one, and `y` will be two.
Patterns are really powerful, and have [their own section][pattern] in the
book. We dont need those features for now, so well keep this in the back
of our minds as we go forward.
[pattern]: patterns.html
# Type annotations
Rust is a statically typed language, which means that we specify our types up
front, and theyre checked at compile time. So why does our first example
compile? Well, Rust has this thing called type inference. If it can figure
out what the type of something is, Rust doesnt require you to explicitly type
it out.
We can add the type if we want to, though. Types come after a colon (`:`):
```rust
let x: i32 = 5;
```
If I asked you to read this out loud to the rest of the class, youd say “`x`
is a binding with the type `i32` and the value `5`.”
In this case we chose to represent `x` as a 32-bit signed integer. Rust has
many different primitive integer types. They begin with `i` for signed integers
and `u` for unsigned integers. The possible integer sizes are 8, 16, 32, and 64
bits.
In future examples, we may annotate the type in a comment. The examples will
look like this:
```rust
fn main() {
let x = 5; // x: i32
}
```
Note the similarities between this annotation and the syntax you use with
`let`. Including these kinds of comments is not idiomatic Rust, but we'll
occasionally include them to help you understand what the types that Rust
infers are.
# Mutability
By default, bindings are *immutable*. This code will not compile:
```rust,ignore
let x = 5;
x = 10;
```
It will give you this error:
```text
error: re-assignment of immutable variable `x`
x = 10;
^~~~~~~
```
If you want a binding to be mutable, you can use `mut`:
```rust
let mut x = 5; // mut x: i32
x = 10;
```
There is no single reason that bindings are immutable by default, but we can
think about it through one of Rusts primary focuses: safety. If you forget to
say `mut`, the compiler will catch it, and let you know that you have mutated
something you may not have intended to mutate. If bindings were mutable by
default, the compiler would not be able to tell you this. If you _did_ intend
mutation, then the solution is quite easy: add `mut`.
There are other good reasons to avoid mutable state when possible, but theyre
out of the scope of this guide. In general, you can often avoid explicit
mutation, and so it is preferable in Rust. That said, sometimes, mutation is
what you need, so its not forbidden.
# Initializing bindings
Rust variable bindings have one more aspect that differs from other languages:
bindings are required to be initialized with a value before you're allowed to
use them.
Lets try it out. Change your `src/main.rs` file to look like this:
```rust
fn main() {
let x: i32;
println!("Hello world!");
}
```
You can use `cargo build` on the command line to build it. Youll get a
warning, but it will still print "Hello, world!":
```text
Compiling hello_world v0.0.1 (file:///home/you/projects/hello_world)
src/main.rs:2:9: 2:10 warning: unused variable: `x`, #[warn(unused_variables)]
on by default
src/main.rs:2 let x: i32;
^
```
Rust warns us that we never use the variable binding, but since we never use
it, no harm, no foul. Things change if we try to actually use this `x`,
however. Lets do that. Change your program to look like this:
```rust,ignore
fn main() {
let x: i32;
println!("The value of x is: {}", x);
}
```
And try to build it. Youll get an error:
```bash
$ cargo build
Compiling hello_world v0.0.1 (file:///home/you/projects/hello_world)
src/main.rs:4:39: 4:40 error: use of possibly uninitialized variable: `x`
src/main.rs:4 println!("The value of x is: {}", x);
^
note: in expansion of format_args!
<std macros>:2:23: 2:77 note: expansion site
<std macros>:1:1: 3:2 note: in expansion of println!
src/main.rs:4:5: 4:42 note: expansion site
error: aborting due to previous error
Could not compile `hello_world`.
```
Rust will not let us use a value that has not been initialized.
Let us take a minute to talk about this stuff we've added to `println!`.
If you include two curly braces (`{}`, some call them moustaches...) in your
string to print, Rust will interpret this as a request to interpolate some sort
of value. *String interpolation* is a computer science term that means "stick
in the middle of a string." We add a comma, and then `x`, to indicate that we
want `x` to be the value were interpolating. The comma is used to separate
arguments we pass to functions and macros, if youre passing more than one.
When you use the curly braces, Rust will attempt to display the value in a
meaningful way by checking out its type. If you want to specify the format in a
more detailed manner, there are a [wide number of options available][format].
For now, we'll stick to the default: integers aren't very complicated to
print.
[format]: ../../std/fmt/index.html
# Scope and shadowing
Lets get back to bindings. Variable bindings have a scope - they are
constrained to live in the block they were defined in. A block is a collection
of statements enclosed by `{` and `}`. Function definitions are also blocks!
In the following example we define two variable bindings, `x` and `y`, which
live in different blocks. `x` can be accessed from inside the `fn main() {}`
block, while `y` can be accessed only from inside the inner block:
```rust,ignore
fn main() {
let x: i32 = 17;
{
let y: i32 = 3;
println!("The value of x is {} and value of y is {}", x, y);
}
println!("The value of x is {} and value of y is {}", x, y); // This won't work.
}
```
The first `println!` would print "The value of x is 17 and the value of y is
3", but this example cannot be compiled successfully, because the second
`println!` cannot access the value of `y`, since it is not in scope anymore.
Instead we get this error:
```bash
$ cargo build
Compiling hello v0.1.0 (file:///home/you/projects/hello_world)
main.rs:7:62: 7:63 error: unresolved name `y`. Did you mean `x`? [E0425]
main.rs:7 println!("The value of x is {} and value of y is {}", x, y); // This won't work.
^
note: in expansion of format_args!
<std macros>:2:25: 2:56 note: expansion site
<std macros>:1:1: 2:62 note: in expansion of print!
<std macros>:3:1: 3:54 note: expansion site
<std macros>:1:1: 3:58 note: in expansion of println!
main.rs:7:5: 7:65 note: expansion site
main.rs:7:62: 7:63 help: run `rustc --explain E0425` to see a detailed explanation
error: aborting due to previous error
Could not compile `hello`.
To learn more, run the command again with --verbose.
```
Additionally, variable bindings can be shadowed. This means that a later
variable binding with the same name as another binding that is currently in
scope will override the previous binding.
```rust
let x: i32 = 8;
{
println!("{}", x); // Prints "8".
let x = 12;
println!("{}", x); // Prints "12".
}
println!("{}", x); // Prints "8".
let x = 42;
println!("{}", x); // Prints "42".
```
Shadowing and mutable bindings may appear as two sides of the same coin, but
they are two distinct concepts that can't always be used interchangeably. For
one, shadowing enables us to rebind a name to a value of a different type. It
is also possible to change the mutability of a binding. Note that shadowing a
name does not alter or destroy the value it was bound to, and the value will
continue to exist until it goes out of scope, even if it is no longer accessible
by any means.
```rust
let mut x: i32 = 1;
x = 7;
let x = x; // `x` is now immutable and is bound to `7`.
let y = 4;
let y = "I can also be bound to text!"; // `y` is now of a different type.
```
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/variable-bindings.html).

View File

@ -1,156 +1,10 @@
# Vectors
A vector is a dynamic or growable array, implemented as the standard
library type [`Vec<T>`][vec]. The `T` means that we can have vectors
of any type (see the chapter on [generics][generic] for more).
Vectors always allocate their data on the heap.
You can create them with the `vec!` macro:
The first edition of the book is no longer distributed with Rust's documentation.
```rust
let v = vec![1, 2, 3, 4, 5]; // v: Vec<i32>
```
If you came here via a link or web search, you may want to check out [the current
version of the book](../index.html) instead.
(Notice that unlike the `println!` macro weve used in the past, we use square
brackets `[]` with `vec!` macro. Rust allows you to use either in either
situation, this is just convention.)
Theres an alternate form of `vec!` for repeating an initial value:
```rust
let v = vec![0; 10]; // A vector of ten zeroes.
```
Vectors store their contents as contiguous arrays of `T` on the heap. This means
that they must be able to know the size of `T` at compile time (that is, how
many bytes are needed to store a `T`?). The size of some things can't be known
at compile time. For these you'll have to store a pointer to that thing:
thankfully, the [`Box`][box] type works perfectly for this.
## Accessing elements
To get the value at a particular index in the vector, we use `[]`s:
```rust
let v = vec![1, 2, 3, 4, 5];
println!("The third element of v is {}", v[2]);
```
The indices count from `0`, so the third element is `v[2]`.
Its also important to note that you must index with the `usize` type:
```rust,ignore
let v = vec![1, 2, 3, 4, 5];
let i: usize = 0;
let j: i32 = 0;
// Works:
v[i];
// Doesnt:
v[j];
```
Indexing with a non-`usize` type gives an error that looks like this:
```text
error: the trait bound `collections::vec::Vec<_> : core::ops::Index<i32>`
is not satisfied [E0277]
v[j];
^~~~
note: the type `collections::vec::Vec<_>` cannot be indexed by `i32`
error: aborting due to previous error
```
Theres a lot of punctuation in that message, but the core of it makes sense:
you cannot index with an `i32`.
## Out-of-bounds Access
If you try to access an index that doesnt exist:
```rust,ignore
let v = vec![1, 2, 3];
println!("Item 7 is {}", v[7]);
```
then the current thread will [panic] with a message like this:
```text
thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 7'
```
If you want to handle out-of-bounds errors without panicking, you can use
methods like [`get`][get] or [`get_mut`][get_mut] that return `None` when
given an invalid index:
```rust
let v = vec![1, 2, 3];
match v.get(7) {
Some(x) => println!("Item 7 is {}", x),
None => println!("Sorry, this vector is too short.")
}
```
## Iterating
Once you have a vector, you can iterate through its elements with `for`. There
are three versions:
```rust
let mut v = vec![1, 2, 3, 4, 5];
for i in &v {
println!("A reference to {}", i);
}
for i in &mut v {
println!("A mutable reference to {}", i);
}
for i in v {
println!("Take ownership of the vector and its element {}", i);
}
```
Note: You cannot use the vector again once you have iterated by taking ownership of the vector.
You can iterate the vector multiple times by taking a reference to the vector whilst iterating.
For example, the following code does not compile.
```rust,ignore
let v = vec![1, 2, 3, 4, 5];
for i in v {
println!("Take ownership of the vector and its element {}", i);
}
for i in v {
println!("Take ownership of the vector and its element {}", i);
}
```
Whereas the following works perfectly,
```rust
let v = vec![1, 2, 3, 4, 5];
for i in &v {
println!("This is a reference to {}", i);
}
for i in &v {
println!("This is a reference to {}", i);
}
```
Vectors have many more useful methods, which you can read about in [their
API documentation][vec].
[vec]: ../../std/vec/index.html
[box]: ../../std/boxed/index.html
[generic]: generics.html
[panic]: concurrency.html#panics
[get]: ../../std/vec/struct.Vec.html#method.get
[get_mut]: ../../std/vec/struct.Vec.html#method.get_mut
If you have an internet connection, you can [find a copy distributed with
Rust
1.30](https://doc.rust-lang.org/1.30.0/book/first-edition/vectors.html).