]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | % The Rust Programming Language |
2 | ||
9346a6ac AL |
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 | |
bd371182 | 11 | eliminating all data races. Rust also aims to achieve ‘zero-cost abstractions’ |
9346a6ac AL |
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. | |
1a4d82fc | 15 | |
9346a6ac | 16 | [rust]: http://rust-lang.org |
1a4d82fc | 17 | |
62682a34 | 18 | “The Rust Programming Language” is split into eight sections. This introduction |
9346a6ac | 19 | is the first. After this: |
1a4d82fc | 20 | |
9346a6ac AL |
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. | |
bd371182 | 27 | * [Academic Research][ar] - Literature that influenced Rust. |
1a4d82fc | 28 | |
9346a6ac AL |
29 | [gs]: getting-started.html |
30 | [lr]: learn-rust.html | |
31 | [er]: effective-rust.html | |
32 | [ss]: syntax-and-semantics.html | |
33 | [nr]: nightly-rust.html | |
34 | [gl]: glossary.html | |
bd371182 | 35 | [ar]: academic-research.html |
1a4d82fc | 36 | |
9346a6ac AL |
37 | After reading this introduction, you’ll want to dive into either ‘Learn Rust’ |
38 | or ‘Syntax and Semantics’, depending on your preference: ‘Learn Rust’ if you | |
39 | want to dive in with a project, or ‘Syntax and Semantics’ if you prefer to | |
40 | start small, and learn a single concept thoroughly before moving onto the next. | |
41 | Copious cross-linking connects these parts together. | |
1a4d82fc | 42 | |
bd371182 AL |
43 | ### Contributing |
44 | ||
45 | The source files from which this book is generated can be found on Github: | |
46 | [github.com/rust-lang/rust/tree/master/src/doc/trpl](https://github.com/rust-lang/rust/tree/master/src/doc/trpl) | |
47 | ||
9346a6ac | 48 | ## A brief introduction to Rust |
1a4d82fc | 49 | |
9346a6ac AL |
50 | Is Rust a language you might be interested in? Let’s examine a few small code |
51 | samples to show off a few of its strengths. | |
1a4d82fc | 52 | |
9346a6ac AL |
53 | The main concept that makes Rust unique is called ‘ownership’. Consider this |
54 | small example: | |
1a4d82fc | 55 | |
9346a6ac AL |
56 | ```rust |
57 | fn main() { | |
58 | let mut x = vec!["Hello", "world"]; | |
59 | } | |
60 | ``` | |
1a4d82fc | 61 | |
9346a6ac AL |
62 | This program makes a [variable binding][var] named `x`. The value of this |
63 | binding is a `Vec<T>`, a ‘vector’, that we create through a [macro][macro] | |
64 | defined in the standard library. This macro is called `vec`, and we invoke | |
65 | macros with a `!`. This follows a general principle of Rust: make things | |
66 | explicit. Macros can do significantly more complicated things than function | |
67 | calls, and so they’re visually distinct. The `!` also helps with parsing, | |
68 | making tooling easier to write, which is also important. | |
c34b1796 | 69 | |
9346a6ac AL |
70 | We used `mut` to make `x` mutable: bindings are immutable by default in Rust. |
71 | We’ll be mutating this vector later in the example. | |
c34b1796 | 72 | |
9346a6ac AL |
73 | It’s also worth noting that we didn’t need a type annotation here: while Rust |
74 | is statically typed, we didn’t need to explicitly annotate the type. Rust has | |
75 | type inference to balance out the power of static typing with the verbosity of | |
76 | annotating types. | |
77 | ||
78 | Rust prefers stack allocation to heap allocation: `x` is placed directly on the | |
79 | stack. However, the `Vec<T>` type allocates space for the elements of the | |
80 | vector on the heap. If you’re not familiar with this distinction, you can | |
81 | ignore it for now, or check out [‘The Stack and the Heap’][heap]. As a systems | |
82 | programming language, Rust gives you the ability to control how your memory is | |
83 | allocated, but when we’re getting started, it’s less of a big deal. | |
84 | ||
85 | [var]: variable-bindings.html | |
86 | [macro]: macros.html | |
87 | [heap]: the-stack-and-the-heap.html | |
88 | ||
89 | Earlier, we mentioned that ‘ownership’ is the key new concept in Rust. In Rust | |
90 | parlance, `x` is said to ‘own’ the vector. This means that when `x` goes out of | |
91 | scope, the vector’s memory will be de-allocated. This is done deterministically | |
92 | by the Rust compiler, rather than through a mechanism such as a garbage | |
93 | collector. In other words, in Rust, you don’t call functions like `malloc` and | |
94 | `free` yourself: the compiler statically determines when you need to allocate | |
95 | or deallocate memory, and inserts those calls itself. To err is to be human, | |
96 | but compilers never forget. | |
97 | ||
98 | Let’s add another line to our example: | |
99 | ||
100 | ```rust | |
101 | fn main() { | |
102 | let mut x = vec!["Hello", "world"]; | |
103 | ||
104 | let y = &x[0]; | |
105 | } | |
106 | ``` | |
107 | ||
108 | We’ve introduced another binding, `y`. In this case, `y` is a ‘reference’ to | |
109 | the first element of the vector. Rust’s references are similar to pointers in | |
110 | other languages, but with additional compile-time safety checks. References | |
111 | interact with the ownership system by [‘borrowing’][borrowing] what they point | |
112 | to, rather than owning it. The difference is, when the reference goes out of | |
113 | scope, it will not deallocate the underlying memory. If it did, we’d | |
114 | de-allocate twice, which is bad! | |
115 | ||
116 | [borrowing]: references-and-borrowing.html | |
117 | ||
118 | Let’s add a third line. It looks innocent enough, but causes a compiler error: | |
119 | ||
120 | ```rust,ignore | |
121 | fn main() { | |
122 | let mut x = vec!["Hello", "world"]; | |
123 | ||
124 | let y = &x[0]; | |
125 | ||
126 | x.push("foo"); | |
127 | } | |
128 | ``` | |
129 | ||
130 | `push` is a method on vectors that appends another element to the end of the | |
131 | vector. When we try to compile this program, we get an error: | |
132 | ||
133 | ```text | |
134 | error: cannot borrow `x` as mutable because it is also borrowed as immutable | |
bd371182 | 135 | x.push("foo"); |
9346a6ac AL |
136 | ^ |
137 | note: previous borrow of `x` occurs here; the immutable borrow prevents | |
138 | subsequent moves or mutable borrows of `x` until the borrow ends | |
139 | let y = &x[0]; | |
140 | ^ | |
141 | note: previous borrow ends here | |
142 | fn main() { | |
143 | ||
144 | } | |
145 | ^ | |
146 | ``` | |
147 | ||
148 | Whew! The Rust compiler gives quite detailed errors at times, and this is one | |
149 | of those times. As the error explains, while we made our binding mutable, we | |
150 | still cannot call `push`. This is because we already have a reference to an | |
151 | element of the vector, `y`. Mutating something while another reference exists | |
152 | is dangerous, because we may invalidate the reference. In this specific case, | |
62682a34 SL |
153 | when we create the vector, we may have only allocated space for two elements. |
154 | Adding a third would mean allocating a new chunk of memory for all those elements, | |
9346a6ac AL |
155 | copying the old values over, and updating the internal pointer to that memory. |
156 | That all works just fine. The problem is that `y` wouldn’t get updated, and so | |
157 | we’d have a ‘dangling pointer’. That’s bad. Any use of `y` would be an error in | |
158 | this case, and so the compiler has caught this for us. | |
159 | ||
160 | So how do we solve this problem? There are two approaches we can take. The first | |
161 | is making a copy rather than using a reference: | |
162 | ||
163 | ```rust | |
164 | fn main() { | |
165 | let mut x = vec!["Hello", "world"]; | |
166 | ||
167 | let y = x[0].clone(); | |
168 | ||
169 | x.push("foo"); | |
170 | } | |
171 | ``` | |
172 | ||
173 | Rust has [move semantics][move] by default, so if we want to make a copy of some | |
174 | data, we call the `clone()` method. In this example, `y` is no longer a reference | |
bd371182 | 175 | to the vector stored in `x`, but a copy of its first element, `"Hello"`. Now |
9346a6ac AL |
176 | that we don’t have a reference, our `push()` works just fine. |
177 | ||
d9579d0f | 178 | [move]: ownership.html#move-semantics |
9346a6ac AL |
179 | |
180 | If we truly want a reference, we need the other option: ensure that our reference | |
181 | goes out of scope before we try to do the mutation. That looks like this: | |
182 | ||
183 | ```rust | |
184 | fn main() { | |
185 | let mut x = vec!["Hello", "world"]; | |
186 | ||
187 | { | |
188 | let y = &x[0]; | |
189 | } | |
190 | ||
191 | x.push("foo"); | |
192 | } | |
193 | ``` | |
194 | ||
195 | We created an inner scope with an additional set of curly braces. `y` will go out of | |
196 | scope before we call `push()`, and so we’re all good. | |
197 | ||
bd371182 | 198 | This concept of ownership isn’t just good for preventing dangling pointers, but an |
9346a6ac | 199 | entire set of related problems, like iterator invalidation, concurrency, and more. |