2014-12-02 08:20:48 -06:00
|
|
|
|
% The Rust Programming Language
|
|
|
|
|
|
2015-04-09 11:47:08 -05:00
|
|
|
|
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 aren’t
|
|
|
|
|
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
|
2015-04-25 09:46:34 -05:00
|
|
|
|
eliminating all data races. Rust also aims to achieve ‘zero-cost abstractions’
|
2015-04-09 11:47:08 -05:00
|
|
|
|
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.
|
2014-12-02 08:20:48 -06:00
|
|
|
|
|
2015-04-09 11:47:08 -05:00
|
|
|
|
[rust]: http://rust-lang.org
|
2014-12-02 08:20:48 -06:00
|
|
|
|
|
2015-05-29 13:29:35 -05:00
|
|
|
|
“The Rust Programming Language” is split into eight sections. This introduction
|
2015-04-09 11:47:08 -05:00
|
|
|
|
is the first. After this:
|
2014-12-02 08:20:48 -06:00
|
|
|
|
|
2015-04-09 11:47:08 -05:00
|
|
|
|
* [Getting started][gs] - Set up your computer for Rust development.
|
|
|
|
|
* [Learn Rust][lr] - Learn Rust programming through small projects.
|
|
|
|
|
* [Effective Rust][er] - Higher-level concepts for writing excellent Rust code.
|
|
|
|
|
* [Syntax and Semantics][ss] - Each bit of Rust, broken down into small chunks.
|
|
|
|
|
* [Nightly Rust][nr] - Cutting-edge features that aren’t in stable builds yet.
|
|
|
|
|
* [Glossary][gl] - A reference of terms used in the book.
|
2015-04-21 12:49:23 -05:00
|
|
|
|
* [Academic Research][ar] - Literature that influenced Rust.
|
2014-12-02 08:20:48 -06:00
|
|
|
|
|
2015-04-09 11:47:08 -05:00
|
|
|
|
[gs]: getting-started.html
|
|
|
|
|
[lr]: learn-rust.html
|
|
|
|
|
[er]: effective-rust.html
|
|
|
|
|
[ss]: syntax-and-semantics.html
|
|
|
|
|
[nr]: nightly-rust.html
|
|
|
|
|
[gl]: glossary.html
|
2015-04-21 12:49:23 -05:00
|
|
|
|
[ar]: academic-research.html
|
2014-12-02 08:20:48 -06:00
|
|
|
|
|
2015-04-09 11:47:08 -05:00
|
|
|
|
After reading this introduction, you’ll want to dive into either ‘Learn Rust’
|
|
|
|
|
or ‘Syntax and Semantics’, depending on your preference: ‘Learn Rust’ if you
|
|
|
|
|
want to dive in with a project, or ‘Syntax and Semantics’ if you prefer to
|
|
|
|
|
start small, and learn a single concept thoroughly before moving onto the next.
|
|
|
|
|
Copious cross-linking connects these parts together.
|
2014-12-02 08:20:48 -06:00
|
|
|
|
|
2015-05-02 07:40:07 -05:00
|
|
|
|
### Contributing
|
|
|
|
|
|
|
|
|
|
The source files from which this book is generated can be found on Github:
|
|
|
|
|
[github.com/rust-lang/rust/tree/master/src/doc/trpl](https://github.com/rust-lang/rust/tree/master/src/doc/trpl)
|
|
|
|
|
|
2015-04-09 11:47:08 -05:00
|
|
|
|
## A brief introduction to Rust
|
2014-12-02 08:20:48 -06:00
|
|
|
|
|
2015-04-09 11:47:08 -05:00
|
|
|
|
Is Rust a language you might be interested in? Let’s examine a few small code
|
|
|
|
|
samples to show off a few of its strengths.
|
2014-12-02 08:20:48 -06:00
|
|
|
|
|
2015-04-09 11:47:08 -05:00
|
|
|
|
The main concept that makes Rust unique is called ‘ownership’. Consider this
|
|
|
|
|
small example:
|
2014-12-02 08:20:48 -06:00
|
|
|
|
|
2015-04-09 11:47:08 -05:00
|
|
|
|
```rust
|
|
|
|
|
fn main() {
|
|
|
|
|
let mut x = vec!["Hello", "world"];
|
|
|
|
|
}
|
|
|
|
|
```
|
2014-12-02 08:20:48 -06:00
|
|
|
|
|
2015-04-09 11:47:08 -05:00
|
|
|
|
This program makes a [variable binding][var] named `x`. The value of this
|
|
|
|
|
binding is a `Vec<T>`, a ‘vector’, that we create through a [macro][macro]
|
|
|
|
|
defined in the standard library. This macro is called `vec`, and we invoke
|
|
|
|
|
macros with a `!`. This follows a general principle of Rust: make things
|
|
|
|
|
explicit. Macros can do significantly more complicated things than function
|
|
|
|
|
calls, and so they’re visually distinct. The `!` also helps with parsing,
|
|
|
|
|
making tooling easier to write, which is also important.
|
2015-03-25 17:35:51 -05:00
|
|
|
|
|
2015-04-09 11:47:08 -05:00
|
|
|
|
We used `mut` to make `x` mutable: bindings are immutable by default in Rust.
|
|
|
|
|
We’ll be mutating this vector later in the example.
|
2015-03-25 17:35:51 -05:00
|
|
|
|
|
2015-04-09 11:47:08 -05:00
|
|
|
|
It’s also worth noting that we didn’t need a type annotation here: while Rust
|
|
|
|
|
is statically typed, we didn’t need to explicitly annotate the type. Rust has
|
|
|
|
|
type inference to balance out the power of static typing with the verbosity of
|
|
|
|
|
annotating types.
|
|
|
|
|
|
|
|
|
|
Rust prefers stack allocation to heap allocation: `x` is placed directly on the
|
|
|
|
|
stack. However, the `Vec<T>` type allocates space for the elements of the
|
|
|
|
|
vector on the heap. If you’re not familiar with this distinction, you can
|
|
|
|
|
ignore it for now, or check out [‘The Stack and the Heap’][heap]. As a systems
|
|
|
|
|
programming language, Rust gives you the ability to control how your memory is
|
|
|
|
|
allocated, but when we’re getting started, it’s less of a big deal.
|
|
|
|
|
|
|
|
|
|
[var]: variable-bindings.html
|
|
|
|
|
[macro]: macros.html
|
|
|
|
|
[heap]: the-stack-and-the-heap.html
|
|
|
|
|
|
|
|
|
|
Earlier, we mentioned that ‘ownership’ is the key new concept in Rust. In Rust
|
|
|
|
|
parlance, `x` is said to ‘own’ the vector. This means that when `x` goes out of
|
|
|
|
|
scope, the vector’s memory will be de-allocated. This is done deterministically
|
|
|
|
|
by the Rust compiler, rather than through a mechanism such as a garbage
|
|
|
|
|
collector. In other words, in Rust, you don’t call functions like `malloc` and
|
|
|
|
|
`free` yourself: the compiler statically determines when you need to allocate
|
|
|
|
|
or deallocate memory, and inserts those calls itself. To err is to be human,
|
|
|
|
|
but compilers never forget.
|
|
|
|
|
|
|
|
|
|
Let’s add another line to our example:
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
fn main() {
|
|
|
|
|
let mut x = vec!["Hello", "world"];
|
|
|
|
|
|
|
|
|
|
let y = &x[0];
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
We’ve introduced another binding, `y`. In this case, `y` is a ‘reference’ to
|
|
|
|
|
the first element of the vector. Rust’s references are similar to pointers in
|
|
|
|
|
other languages, but with additional compile-time safety checks. References
|
|
|
|
|
interact with the ownership system by [‘borrowing’][borrowing] what they point
|
|
|
|
|
to, rather than owning it. The difference is, when the reference goes out of
|
|
|
|
|
scope, it will not deallocate the underlying memory. If it did, we’d
|
|
|
|
|
de-allocate twice, which is bad!
|
|
|
|
|
|
|
|
|
|
[borrowing]: references-and-borrowing.html
|
|
|
|
|
|
|
|
|
|
Let’s add a third line. It looks innocent enough, but causes a compiler error:
|
|
|
|
|
|
|
|
|
|
```rust,ignore
|
|
|
|
|
fn main() {
|
|
|
|
|
let mut x = vec!["Hello", "world"];
|
|
|
|
|
|
|
|
|
|
let y = &x[0];
|
|
|
|
|
|
2015-04-11 10:39:36 -05:00
|
|
|
|
x.push("foo");
|
2015-04-09 11:47:08 -05:00
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`push` is a method on vectors that appends another element to the end of the
|
|
|
|
|
vector. When we try to compile this program, we get an error:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
error: cannot borrow `x` as mutable because it is also borrowed as immutable
|
2015-04-27 05:21:26 -05:00
|
|
|
|
x.push("foo");
|
2015-04-09 11:47:08 -05:00
|
|
|
|
^
|
|
|
|
|
note: previous borrow of `x` occurs here; the immutable borrow prevents
|
|
|
|
|
subsequent moves or mutable borrows of `x` until the borrow ends
|
|
|
|
|
let y = &x[0];
|
|
|
|
|
^
|
|
|
|
|
note: previous borrow ends here
|
|
|
|
|
fn main() {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
^
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Whew! The Rust compiler gives quite detailed errors at times, and this is one
|
|
|
|
|
of those times. As the error explains, while we made our binding mutable, we
|
|
|
|
|
still cannot call `push`. This is because we already have a reference to an
|
|
|
|
|
element of the vector, `y`. Mutating something while another reference exists
|
|
|
|
|
is dangerous, because we may invalidate the reference. In this specific case,
|
2015-05-21 07:30:32 -05:00
|
|
|
|
when we create the vector, we may have only allocated space for two elements.
|
|
|
|
|
Adding a third would mean allocating a new chunk of memory for all those elements,
|
2015-04-09 11:47:08 -05:00
|
|
|
|
copying the old values over, and updating the internal pointer to that memory.
|
|
|
|
|
That all works just fine. The problem is that `y` wouldn’t get updated, and so
|
|
|
|
|
we’d have a ‘dangling pointer’. That’s bad. Any use of `y` would be an error in
|
|
|
|
|
this case, and so the compiler has caught this for us.
|
|
|
|
|
|
|
|
|
|
So how do we solve this problem? There are two approaches we can take. The first
|
|
|
|
|
is making a copy rather than using a reference:
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
fn main() {
|
|
|
|
|
let mut x = vec!["Hello", "world"];
|
|
|
|
|
|
|
|
|
|
let y = x[0].clone();
|
|
|
|
|
|
2015-04-11 10:39:36 -05:00
|
|
|
|
x.push("foo");
|
2015-04-09 11:47:08 -05:00
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Rust has [move semantics][move] by default, so if we want to make a copy of some
|
|
|
|
|
data, we call the `clone()` method. In this example, `y` is no longer a reference
|
2015-04-20 09:42:17 -05:00
|
|
|
|
to the vector stored in `x`, but a copy of its first element, `"Hello"`. Now
|
2015-04-09 11:47:08 -05:00
|
|
|
|
that we don’t have a reference, our `push()` works just fine.
|
|
|
|
|
|
2015-05-13 13:41:25 -05:00
|
|
|
|
[move]: ownership.html#move-semantics
|
2015-04-09 11:47:08 -05:00
|
|
|
|
|
|
|
|
|
If we truly want a reference, we need the other option: ensure that our reference
|
|
|
|
|
goes out of scope before we try to do the mutation. That looks like this:
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
fn main() {
|
|
|
|
|
let mut x = vec!["Hello", "world"];
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
let y = &x[0];
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-11 10:39:36 -05:00
|
|
|
|
x.push("foo");
|
2015-04-09 11:47:08 -05:00
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
We created an inner scope with an additional set of curly braces. `y` will go out of
|
|
|
|
|
scope before we call `push()`, and so we’re all good.
|
|
|
|
|
|
2015-05-01 18:54:57 -05:00
|
|
|
|
This concept of ownership isn’t just good for preventing dangling pointers, but an
|
2015-04-09 11:47:08 -05:00
|
|
|
|
entire set of related problems, like iterator invalidation, concurrency, and more.
|