|
1 | 1 | % The Rust Programming Language
|
2 | 2 |
|
3 |
| -Welcome! This book will teach you about [the Rust Programming |
4 |
| -Language](http://www.rust-lang.org/). Rust is a modern systems programming |
5 |
| -language focusing on safety and speed. It accomplishes these goals by being |
6 |
| -memory safe without using garbage collection. |
| 3 | +Welcome! This book will teach you about the [Rust Programming Language][rust]. |
| 4 | +Rust is a systems programming language focused on three goals: safety, speed, |
| 5 | +and concurrency. It maintains these goals without having a garbage collector, |
| 6 | +making it a useful language for a number of use cases other languages aren’t |
| 7 | +good at: embedding in other languages, programs with specific space and time |
| 8 | +requirements, and writing low-level code, like device drivers and operating |
| 9 | +systems. It improves on current languages targeting this space by having a |
| 10 | +number of compile-time safety checks that produce no runtime overhead, while |
| 11 | +eliminating all data races. Rust also aims to achieve ‘zero-cost abstrations’ |
| 12 | +even though some of these abstractions feel like those of a high-level |
| 13 | +language. Even then, Rust still allows precise control like a low-level |
| 14 | +language would. |
7 | 15 |
|
8 |
| -"The Rust Programming Language" is split into three sections, which you can |
9 |
| -navigate through the menu on the left. |
| 16 | +[rust]: http://rust-lang.org |
10 | 17 |
|
11 |
| -<h2 class="section-header"><a href="basic.html">Basics</a></h2> |
| 18 | +“The Rust Programming Language” is split into seven sections. This introduction |
| 19 | +is the first. After this: |
12 | 20 |
|
13 |
| -This section is a linear introduction to the basic syntax and semantics of |
14 |
| -Rust. It has individual sections on each part of Rust's syntax. |
| 21 | +* [Getting started][gs] - Set up your computer for Rust development. |
| 22 | +* [Learn Rust][lr] - Learn Rust programming through small projects. |
| 23 | +* [Effective Rust][er] - Higher-level concepts for writing excellent Rust code. |
| 24 | +* [Syntax and Semantics][ss] - Each bit of Rust, broken down into small chunks. |
| 25 | +* [Nightly Rust][nr] - Cutting-edge features that aren’t in stable builds yet. |
| 26 | +* [Glossary][gl] - A reference of terms used in the book. |
15 | 27 |
|
16 |
| -After reading "Basics," you will have a good foundation to learn more about |
17 |
| -Rust, and can write very simple programs. |
| 28 | +[gs]: getting-started.html |
| 29 | +[lr]: learn-rust.html |
| 30 | +[er]: effective-rust.html |
| 31 | +[ss]: syntax-and-semantics.html |
| 32 | +[nr]: nightly-rust.html |
| 33 | +[gl]: glossary.html |
18 | 34 |
|
19 |
| -<h2 class="section-header"><a href="intermediate.html">Intermediate</a></h2> |
| 35 | +After reading this introduction, you’ll want to dive into either ‘Learn Rust’ |
| 36 | +or ‘Syntax and Semantics’, depending on your preference: ‘Learn Rust’ if you |
| 37 | +want to dive in with a project, or ‘Syntax and Semantics’ if you prefer to |
| 38 | +start small, and learn a single concept thoroughly before moving onto the next. |
| 39 | +Copious cross-linking connects these parts together. |
20 | 40 |
|
21 |
| -This section contains individual chapters, which are self-contained. They focus |
22 |
| -on specific topics, and can be read in any order. |
| 41 | +## A brief introduction to Rust |
23 | 42 |
|
24 |
| -After reading "Intermediate," you will have a solid understanding of Rust, |
25 |
| -and will be able to understand most Rust code and write more complex programs. |
| 43 | +Is Rust a language you might be interested in? Let’s examine a few small code |
| 44 | +samples to show off a few of its strengths. |
26 | 45 |
|
27 |
| -<h2 class="section-header"><a href="advanced.html">Advanced</a></h2> |
| 46 | +The main concept that makes Rust unique is called ‘ownership’. Consider this |
| 47 | +small example: |
28 | 48 |
|
29 |
| -In a similar fashion to "Intermediate," this section is full of individual, |
30 |
| -deep-dive chapters, which stand alone and can be read in any order. These |
31 |
| -chapters focus on Rust's most complex features. |
| 49 | +```rust |
| 50 | +fn main() { |
| 51 | + let mut x = vec!["Hello", "world"]; |
| 52 | +} |
| 53 | +``` |
32 | 54 |
|
33 |
| -<h2 class="section-header"><a href="unstable.html">Unstable</a></h2> |
| 55 | +This program makes a [variable binding][var] named `x`. The value of this |
| 56 | +binding is a `Vec<T>`, a ‘vector’, that we create through a [macro][macro] |
| 57 | +defined in the standard library. This macro is called `vec`, and we invoke |
| 58 | +macros with a `!`. This follows a general principle of Rust: make things |
| 59 | +explicit. Macros can do significantly more complicated things than function |
| 60 | +calls, and so they’re visually distinct. The `!` also helps with parsing, |
| 61 | +making tooling easier to write, which is also important. |
34 | 62 |
|
35 |
| -In a similar fashion to "Intermediate," this section is full of individual, |
36 |
| -deep-dive chapters, which stand alone and can be read in any order. |
| 63 | +We used `mut` to make `x` mutable: bindings are immutable by default in Rust. |
| 64 | +We’ll be mutating this vector later in the example. |
37 | 65 |
|
38 |
| -This chapter contains things that are only available on the nightly channel of |
39 |
| -Rust. |
| 66 | +It’s also worth noting that we didn’t need a type annotation here: while Rust |
| 67 | +is statically typed, we didn’t need to explicitly annotate the type. Rust has |
| 68 | +type inference to balance out the power of static typing with the verbosity of |
| 69 | +annotating types. |
| 70 | + |
| 71 | +Rust prefers stack allocation to heap allocation: `x` is placed directly on the |
| 72 | +stack. However, the `Vec<T>` type allocates space for the elements of the |
| 73 | +vector on the heap. If you’re not familiar with this distinction, you can |
| 74 | +ignore it for now, or check out [‘The Stack and the Heap’][heap]. As a systems |
| 75 | +programming language, Rust gives you the ability to control how your memory is |
| 76 | +allocated, but when we’re getting started, it’s less of a big deal. |
| 77 | + |
| 78 | +[var]: variable-bindings.html |
| 79 | +[macro]: macros.html |
| 80 | +[heap]: the-stack-and-the-heap.html |
| 81 | + |
| 82 | +Earlier, we mentioned that ‘ownership’ is the key new concept in Rust. In Rust |
| 83 | +parlance, `x` is said to ‘own’ the vector. This means that when `x` goes out of |
| 84 | +scope, the vector’s memory will be de-allocated. This is done deterministically |
| 85 | +by the Rust compiler, rather than through a mechanism such as a garbage |
| 86 | +collector. In other words, in Rust, you don’t call functions like `malloc` and |
| 87 | +`free` yourself: the compiler statically determines when you need to allocate |
| 88 | +or deallocate memory, and inserts those calls itself. To err is to be human, |
| 89 | +but compilers never forget. |
| 90 | + |
| 91 | +Let’s add another line to our example: |
| 92 | + |
| 93 | +```rust |
| 94 | +fn main() { |
| 95 | + let mut x = vec!["Hello", "world"]; |
| 96 | + |
| 97 | + let y = &x[0]; |
| 98 | +} |
| 99 | +``` |
| 100 | + |
| 101 | +We’ve introduced another binding, `y`. In this case, `y` is a ‘reference’ to |
| 102 | +the first element of the vector. Rust’s references are similar to pointers in |
| 103 | +other languages, but with additional compile-time safety checks. References |
| 104 | +interact with the ownership system by [‘borrowing’][borrowing] what they point |
| 105 | +to, rather than owning it. The difference is, when the reference goes out of |
| 106 | +scope, it will not deallocate the underlying memory. If it did, we’d |
| 107 | +de-allocate twice, which is bad! |
| 108 | + |
| 109 | +[borrowing]: references-and-borrowing.html |
| 110 | + |
| 111 | +Let’s add a third line. It looks innocent enough, but causes a compiler error: |
| 112 | + |
| 113 | +```rust,ignore |
| 114 | +fn main() { |
| 115 | + let mut x = vec!["Hello", "world"]; |
| 116 | +
|
| 117 | + let y = &x[0]; |
| 118 | +
|
| 119 | + x.push("foo"); |
| 120 | +} |
| 121 | +``` |
| 122 | + |
| 123 | +`push` is a method on vectors that appends another element to the end of the |
| 124 | +vector. When we try to compile this program, we get an error: |
| 125 | + |
| 126 | +```text |
| 127 | +error: cannot borrow `x` as mutable because it is also borrowed as immutable |
| 128 | + x.push(4); |
| 129 | + ^ |
| 130 | +note: previous borrow of `x` occurs here; the immutable borrow prevents |
| 131 | +subsequent moves or mutable borrows of `x` until the borrow ends |
| 132 | + let y = &x[0]; |
| 133 | + ^ |
| 134 | +note: previous borrow ends here |
| 135 | +fn main() { |
| 136 | +
|
| 137 | +} |
| 138 | +^ |
| 139 | +``` |
| 140 | + |
| 141 | +Whew! The Rust compiler gives quite detailed errors at times, and this is one |
| 142 | +of those times. As the error explains, while we made our binding mutable, we |
| 143 | +still cannot call `push`. This is because we already have a reference to an |
| 144 | +element of the vector, `y`. Mutating something while another reference exists |
| 145 | +is dangerous, because we may invalidate the reference. In this specific case, |
| 146 | +when we create the vector, we may have only allocated space for three elements. |
| 147 | +Adding a fourth would mean allocating a new chunk of memory for all those elements, |
| 148 | +copying the old values over, and updating the internal pointer to that memory. |
| 149 | +That all works just fine. The problem is that `y` wouldn’t get updated, and so |
| 150 | +we’d have a ‘dangling pointer’. That’s bad. Any use of `y` would be an error in |
| 151 | +this case, and so the compiler has caught this for us. |
| 152 | + |
| 153 | +So how do we solve this problem? There are two approaches we can take. The first |
| 154 | +is making a copy rather than using a reference: |
| 155 | + |
| 156 | +```rust |
| 157 | +fn main() { |
| 158 | + let mut x = vec!["Hello", "world"]; |
| 159 | + |
| 160 | + let y = x[0].clone(); |
| 161 | + |
| 162 | + x.push("foo"); |
| 163 | +} |
| 164 | +``` |
| 165 | + |
| 166 | +Rust has [move semantics][move] by default, so if we want to make a copy of some |
| 167 | +data, we call the `clone()` method. In this example, `y` is no longer a reference |
| 168 | +to the vector stored in `x`, but a copy of its first element, `"hello"`. Now |
| 169 | +that we don’t have a reference, our `push()` works just fine. |
| 170 | + |
| 171 | +[move]: move-semantics.html |
| 172 | + |
| 173 | +If we truly want a reference, we need the other option: ensure that our reference |
| 174 | +goes out of scope before we try to do the mutation. That looks like this: |
| 175 | + |
| 176 | +```rust |
| 177 | +fn main() { |
| 178 | + let mut x = vec!["Hello", "world"]; |
| 179 | + |
| 180 | + { |
| 181 | + let y = &x[0]; |
| 182 | + } |
| 183 | + |
| 184 | + x.push("foo"); |
| 185 | +} |
| 186 | +``` |
| 187 | + |
| 188 | +We created an inner scope with an additional set of curly braces. `y` will go out of |
| 189 | +scope before we call `push()`, and so we’re all good. |
| 190 | + |
| 191 | +This concept of ownership isn’t just good for preventing danging pointers, but an |
| 192 | +entire set of related problems, like iterator invalidation, concurrency, and more. |
0 commit comments