Skip to content

Commit 3252694

Browse files
committed
Rollup merge of #24239 - steveklabnik:editing_pass, r=steveklabnik
Now that the new TOC has landed, I've started doing an editing pass to get the old content into the right shape. I felt this introduction was significant enough to send as its own PR, though, as it's the introduction. It's possible that we may just want to replace 'the intro' with this directly, but this PR doesn't do that.
2 parents 858f3c8 + bf88539 commit 3252694

File tree

1 file changed

+178
-25
lines changed

1 file changed

+178
-25
lines changed

src/doc/trpl/README.md

Lines changed: 178 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,192 @@
11
% The Rust Programming Language
22

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.
715

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
1017

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:
1220

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.
1527

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
1834

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.
2040

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
2342

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.
2645

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:
2848

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+
```
3254

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.
3462

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.
3765

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(4);
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(4);
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(4);
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

Comments
 (0)