mirror of
https://github.com/rust-lang/book.git
synced 2026-09-14 18:01:04 -04:00
Carol's revisions for consistency and clarity
Adding some listing numbers, rewording, rearranging a bit
This commit is contained in:
@@ -14,11 +14,11 @@ MORE STUFF GOES HERE LATER
|
||||
## Who This Book is For
|
||||
|
||||
This book assumes that you've written code in some other programming language,
|
||||
but doesn't make any assumptions about which ones. We've tried to make the
|
||||
but doesn't make any assumptions about which one. We've tried to make the
|
||||
material broadly accessible to those from a wide variety of programming
|
||||
backgrounds. We don't spend a lot of time talking about what programming *is*
|
||||
or how to think about it; someone new to programming entirely would be better
|
||||
served by reading a book specifically for those new to programming.
|
||||
served by reading a book specifically providing an introduction to programming.
|
||||
|
||||
## How to Use This Book
|
||||
|
||||
@@ -28,19 +28,20 @@ chapters may not dig into details on a topic, revisiting the topic in a later
|
||||
chapter.
|
||||
|
||||
There are two kinds of chapters in this book: concept chapters, and project
|
||||
chapters. In concept chapters, you'll learn something about some aspect of
|
||||
Rust. In the project chapters, we'll build small programs together, applying
|
||||
what we've learned so far. Chapters 2, 12, and 20 are project chapters, the
|
||||
rest are concept chapters.
|
||||
chapters. In concept chapters, you'll learn about an aspect of Rust. In the
|
||||
project chapters, we'll build small programs together, applying what we've
|
||||
learned so far. Chapters 2, 12, and 20 are project chapters; the rest are
|
||||
concept chapters.
|
||||
|
||||
Additionally, Chapter 2 is a hands-on introduction to Rust as a language. We'll
|
||||
cover concepts at a high level, and later chapters will go into them in detail.
|
||||
If you're the kind of person who likes to get their hands dirty right away,
|
||||
Chapter 2 is great for that. If you're *really* that kind of person, you may
|
||||
even wish to skip over chapter 3, which covers features that are very similar
|
||||
to other programming languages. By contrast, if you're a particularly
|
||||
meticulous learner who prefers to learn every detail before moving onto the
|
||||
next, you may want to skip chapter two and go straight to chapter 3.
|
||||
even wish to skip over Chapter 3, which covers features that are very similar
|
||||
to other programming languages, and go straight to Chapter 4 to learn about
|
||||
Rust's ownership system. By contrast, if you're a particularly meticulous
|
||||
learner who prefers to learn every detail before moving onto the next, you may
|
||||
want to skip Chapter 2 and go straight to Chapter 3.
|
||||
|
||||
In the end, there's no wrong way to read a book: if you want to skip ahead, go
|
||||
for it! You may have to jump back if you find things confusing. Do whatever
|
||||
|
||||
@@ -2,8 +2,20 @@
|
||||
|
||||
The first step to using Rust is to install it. You’ll need an internet
|
||||
connection to run the commands in this chapter, as we’ll be downloading Rust
|
||||
from the internet.
|
||||
from the internet. We'll actually be installing Rust using `rustup`, a
|
||||
command-line tool for managing Rust versions and associated tools.
|
||||
|
||||
The following steps will install the latest stable version of the Rust
|
||||
compiler. The examples and output shown in this book used stable Rust 1.21.0.
|
||||
Due to Rust's stability guarantees, which we'll discuss further in the "How
|
||||
Rust is Made" section later in this chapter, all of the examples that compile
|
||||
will continue to compile with newer versions of Rust. The output may differ
|
||||
slightly as error messages and warnings are often improved. In other words, the
|
||||
newer, stable version of Rust you will install with these steps should work as
|
||||
expected with the content of this book.
|
||||
|
||||
> #### Command Line Notation
|
||||
>
|
||||
> We’ll be showing off a number of commands using a terminal, and those lines
|
||||
> all start with `$`. You don’t need to type in the `$` character; they are
|
||||
> there to indicate the start of each command. You’ll see many tutorials and
|
||||
@@ -13,7 +25,7 @@ from the internet.
|
||||
> output of the previous command. Additionally, PowerShell specific examples
|
||||
> will use `>` rather than `$`.
|
||||
|
||||
### Installing on Linux or Mac
|
||||
### Installing Rustup on Linux or Mac
|
||||
|
||||
If you’re on Linux or a Mac, 99% of what you need to do is open a terminal and
|
||||
type this:
|
||||
@@ -22,8 +34,9 @@ type this:
|
||||
$ curl https://sh.rustup.rs -sSf | sh
|
||||
```
|
||||
|
||||
This will download a script and start the installation. You may be prompted for
|
||||
your password. If it all goes well, you’ll see this appear:
|
||||
This will download a script and start the installation of the `rustup` tool,
|
||||
which installs the latest stable version of Rust. You may be prompted for your
|
||||
password. If it all goes well, you’ll see this appear:
|
||||
|
||||
```text
|
||||
Rust is installed now. Great!
|
||||
@@ -46,12 +59,15 @@ Alternatively, add the following line to your `~/.bash_profile`:
|
||||
$ export PATH="$HOME/.cargo/bin:$PATH"
|
||||
```
|
||||
|
||||
Finally, you'll need a linker of some kind. You may have one installed. If not,
|
||||
check your platform's documentation for how to install a C compiler; they
|
||||
usually come with the correct linker as well, given that C needs one as well.
|
||||
You may want to do this regardless, as some packages depend on C code as well.
|
||||
Finally, you'll need a linker of some kind. You likely have one installed. If
|
||||
not, when you compile a Rust program, you'll get errors that a linker could not
|
||||
be executed. Check your platform's documentation for how to install a C
|
||||
compiler; they usually come with the correct linker as well, given that C needs
|
||||
one. You may want to install a C compiler regardless of your need for only a
|
||||
linker; some common Rust packages depend on C code and will need a C compiler
|
||||
too.
|
||||
|
||||
### Installing on Windows
|
||||
### Installing Rustup on Windows
|
||||
|
||||
On Windows, go to
|
||||
[https://www.rust-lang.org/en-US/install.html](https://www.rust-lang.org/en-US/i
|
||||
@@ -62,20 +78,20 @@ by installing [Microsoft Visual C++ Build Tools
|
||||
) which provides only the Visual C++ build tools. Alternately, you can
|
||||
[install](https://www.visualstudio.com/downloads/#build-tools-for-visual-studio-
|
||||
2017) Visual Studio 2017, Visual Studio 2015, or Visual Studio 2013 and during
|
||||
install select the "C++ tools".
|
||||
installation select the "C++ tools".
|
||||
|
||||
The rest of this book will use commands that work in both `cmd.exe` and
|
||||
PowerShell. If there are specific differences, we'll explain which to use.
|
||||
|
||||
### Custom Installations
|
||||
### Custom Installations Without Rustup
|
||||
|
||||
If you have reasons for preferring not to use rustup.rs, please see [the Rust
|
||||
If you have reasons for preferring not to use `rustup`, please see [the Rust
|
||||
installation page](https://www.rust-lang.org/install.html) for other options.
|
||||
|
||||
### Updating
|
||||
|
||||
Once you have Rust installed, updating to the latest version is easy. From your
|
||||
shell, run the update script:
|
||||
Once you have Rust installed via `rustup`, updating to the latest version is
|
||||
easy. From your shell, run the update script:
|
||||
|
||||
```text
|
||||
$ rustup update
|
||||
@@ -83,8 +99,8 @@ $ rustup update
|
||||
|
||||
### Uninstalling
|
||||
|
||||
Uninstalling Rust is as easy as installing it. From your shell, run the
|
||||
uninstall script:
|
||||
Uninstalling Rust and Rustup is as easy as installing them. From your shell,
|
||||
run the uninstall script:
|
||||
|
||||
```text
|
||||
$ rustup self uninstall
|
||||
@@ -92,7 +108,7 @@ $ rustup self uninstall
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
If you’ve got Rust installed, you can open up a shell, and type this:
|
||||
To check that you have Rust installed, you can open up a shell and type this:
|
||||
|
||||
```text
|
||||
$ rustc --version
|
||||
@@ -129,4 +145,5 @@ read it offline. Run `rustup doc` to open the local documentation in your
|
||||
browser.
|
||||
|
||||
Any time there’s a type or function provided by the standard library and you’re
|
||||
not sure what it does, use the API documentation to find out!
|
||||
not sure what it does or how to use it, use the API (Application Programming
|
||||
Interface) documentation to find out!
|
||||
|
||||
@@ -7,18 +7,19 @@ tradition.
|
||||
|
||||
> 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, feel free to use your
|
||||
> favorite IDE. Many IDEs now have some degree of Rust support; check the
|
||||
> documentation of yours to see what kind of things it supports. Enabling great
|
||||
> IDE support has been a recent focus of the Rust team, and so things have been
|
||||
> changing rapidly on that front!
|
||||
> lives, so if you prefer an IDE (Integrated Development Environment) to the
|
||||
> command line, feel free to use your favorite IDE. Many IDEs now have some
|
||||
> degree of Rust support; check the IDE's documentation for details. Enabling
|
||||
> great IDE support has been a recent focus of the Rust team, and progress
|
||||
> has been made rapidly on that front!
|
||||
|
||||
### Creating a Project Directory
|
||||
|
||||
First, make a directory to put your Rust code in. Rust doesn’t care where your
|
||||
code lives, but for this book, we’d 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:
|
||||
enter the following commands to make a *projects* directory and a directory
|
||||
inside that for the “Hello, world!” project:
|
||||
|
||||
Linux and Mac:
|
||||
|
||||
@@ -54,7 +55,8 @@ the *.rs* extension. If you’re using more than one word in your filename, use
|
||||
an underscore to separate them. For example, you’d use *hello_world.rs* rather
|
||||
than *helloworld.rs*.
|
||||
|
||||
Now open the *main.rs* file you just created, and type the following code:
|
||||
Now open the *main.rs* file you just created, and enter the code shown in
|
||||
Listing 1-1:
|
||||
|
||||
<span class="filename">Filename: main.rs</span>
|
||||
|
||||
@@ -64,10 +66,12 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
<span class="caption">Listing 1-1: A program that prints “Hello, world!”</span>
|
||||
|
||||
Save the file, and go back to your terminal window. On Linux or OSX, enter the
|
||||
following commands:
|
||||
|
||||
```bash
|
||||
```text
|
||||
$ rustc main.rs
|
||||
$ ./main
|
||||
Hello, world!
|
||||
@@ -97,10 +101,9 @@ fn main() {
|
||||
```
|
||||
|
||||
These lines define a *function* in Rust. The `main` function is special: it’s
|
||||
the first thing that is run for every executable Rust program. The first line
|
||||
says, “I’m declaring a function named `main` that has no parameters and returns
|
||||
nothing.” If there were parameters, their names would go inside the
|
||||
parentheses, `(` and `)`.
|
||||
the first code that is run for every executable Rust program. The first line
|
||||
declares a function named `main` that has no parameters and returns nothing. If
|
||||
there were parameters, their names would go inside the parentheses, `(` and `)`.
|
||||
|
||||
Also note that the function body is wrapped in curly brackets, `{` and `}`.
|
||||
Rust requires these around all function bodies. It’s considered good style to
|
||||
@@ -109,12 +112,12 @@ with one space in between.
|
||||
|
||||
> At the time of writing, an automatic formatter, `rustfmt`, is under
|
||||
> development. If you'd like to stick to a standard style across Rust projects,
|
||||
> `rustfmt` is the way to go. The plan is to eventually include it with the
|
||||
> standard Rust distribution, like `rustc`, so depending on when you
|
||||
> read this book, you may have it already installed! Check the online
|
||||
> documentation for more details.
|
||||
> `rustfmt` is a tool that will format your code in a particular style. The
|
||||
> plan is to eventually include it with the standard Rust distribution, like
|
||||
> `rustc`, so depending on when you read this book, you may have it already
|
||||
> installed! Check the online documentation for more details.
|
||||
|
||||
Inside the `main` function:
|
||||
Inside the `main` function, we have this code:
|
||||
|
||||
```rust
|
||||
println!("Hello, world!");
|
||||
@@ -130,18 +133,22 @@ it would look like this: `println` (without the `!`). We’ll discuss Rust macro
|
||||
in more detail in Appendix D, but for now you just need to know that when you
|
||||
see a `!` that means that you’re calling a macro instead of a normal function.
|
||||
|
||||
> Why is println! a macro? There's multiple reasons, and we haven't really
|
||||
> explained Rust yet, so it's not exactly obvious. Here's the reasons:
|
||||
> ### Why `println!` is a Macro
|
||||
>
|
||||
> There are multiple reasons why `println!` is a macro rather than a function,
|
||||
> and we haven't really explained Rust yet, so it's not exactly obvious. Here
|
||||
> are the reasons:
|
||||
>
|
||||
> * The string passed to `println!` can have formatting specifiers in it,
|
||||
> and those are checked at compile-time.
|
||||
> * Rust functions can only have a static number of arguments, but `println!`
|
||||
> (and macros generally) can take a variable number of them.
|
||||
> * The formatters can take named arguments, which Rust functions cannot.
|
||||
> * Rust functions can only have a fixed number of arguments, but `println!`
|
||||
> (and macros generally) can take a variable number.
|
||||
> * The formatting specifiers can have named arguments, which Rust functions
|
||||
> cannot.
|
||||
> * It implicitly takes its arguments by reference even when they're passed
|
||||
> by value.
|
||||
>
|
||||
> If none of this makes sense, don't worry about it. We'll cover this stuff
|
||||
> If none of this makes sense, don't worry about it. We'll cover these concepts
|
||||
> in more detail later.
|
||||
|
||||
Next is `"Hello, world!"` which is a *string*. We pass this string as an
|
||||
@@ -165,13 +172,13 @@ $ 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
|
||||
`gcc` or `clang`. After compiling successfully, Rust outputs a binary
|
||||
executable.
|
||||
|
||||
On Linux, Mac, and PowerShell on Windows, you can see the executable by
|
||||
entering the `ls` command in your shell as follows:
|
||||
|
||||
```bash
|
||||
```text
|
||||
$ ls
|
||||
main main.rs
|
||||
```
|
||||
@@ -199,8 +206,8 @@ 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 having Rust
|
||||
installed. If you give someone a `.rb`, `.py`, or `.js` file, on the other
|
||||
give the executable to someone else, and they can run it even without having
|
||||
Rust installed. If you give someone a `.rb`, `.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.
|
||||
@@ -227,8 +234,8 @@ easier to do.
|
||||
|
||||
As the vast, vast majority of Rust projects use Cargo, we will assume that
|
||||
you’re using it for the rest of the book. Cargo comes installed with Rust
|
||||
itself, if you used the official installers as covered in the Installation
|
||||
chapter. If you installed Rust through some other means, you can check if you
|
||||
itself, if you used the official installers as covered in the "Installation"
|
||||
section. If you installed Rust through some other means, you can check if you
|
||||
have Cargo installed by typing the following into your terminal:
|
||||
|
||||
```text
|
||||
@@ -274,11 +281,12 @@ If we list the files in the *hello_cargo* directory, we can see that Cargo has
|
||||
generated two files and one directory for us: a *Cargo.toml* and a *src*
|
||||
directory with a *main.rs* file inside. It has also initialized a new git
|
||||
repository in the *hello_cargo* directory for us, along with a *.gitignore*
|
||||
file; you can change this to use a different version control system, or no
|
||||
version control system, by using the `--vcs` flag.
|
||||
file. Git is a common version control system. You can change `cargo new` to use
|
||||
a different version control system, or no version control system, by using the
|
||||
`--vcs` flag. Run `cargo new --help` to see the available options.
|
||||
|
||||
Open up *Cargo.toml* in your text editor of choice. It should look something
|
||||
like this:
|
||||
Open up *Cargo.toml* in your text editor of choice. It should look similar to
|
||||
the code in Listing 1-2:
|
||||
|
||||
<span class="filename">Filename: Cargo.toml</span>
|
||||
|
||||
@@ -291,9 +299,11 @@ authors = ["Your Name <you@example.com>"]
|
||||
[dependencies]
|
||||
```
|
||||
|
||||
<span class="caption">Listing 1-2: Contents of *Cargo.toml* generated by `cargo
|
||||
new`</span>
|
||||
|
||||
This file is in the [*TOML*][toml]<!-- ignore --> (Tom’s Obvious, Minimal
|
||||
Language) format. TOML is similar to INI but has some extra goodies and is used
|
||||
as Cargo’s configuration format.
|
||||
Language) format. TOML is used as Cargo’s configuration format.
|
||||
|
||||
[toml]: https://github.com/toml-lang/toml
|
||||
|
||||
@@ -311,7 +321,7 @@ The last line, `[dependencies]`, is the start of a section for you to list any
|
||||
*crates* (which is what we call packages of Rust code) that your project will
|
||||
depend on so that Cargo knows to download and compile those too. We won’t need
|
||||
any other crates for this project, but we will in the guessing game tutorial in
|
||||
the next chapter.
|
||||
Chapter 2.
|
||||
|
||||
Now let’s look at *src/main.rs*:
|
||||
|
||||
@@ -323,9 +333,9 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
Cargo has generated a “Hello World!” for you, just like the one we wrote
|
||||
earlier! So that part is the same. The differences between our previous project
|
||||
and the project generated by Cargo that we’ve seen so far are:
|
||||
Cargo has generated a “Hello World!” for you, just like the one we wrote in
|
||||
Listing 1-1! So that part is the same. The differences between our previous
|
||||
project and the project generated by Cargo that we’ve seen so far are:
|
||||
|
||||
- Our code goes in the *src* directory
|
||||
- The top level contains a *Cargo.toml* configuration file
|
||||
@@ -352,7 +362,7 @@ $ cargo build
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 2.85 secs
|
||||
```
|
||||
|
||||
This should have created an executable file in *target/debug/hello_cargo* (or
|
||||
This creates an executable file in *target/debug/hello_cargo* (or
|
||||
*target\\debug\\hello_cargo.exe* on Windows), which you can run with this
|
||||
command:
|
||||
|
||||
@@ -364,7 +374,7 @@ Hello, world!
|
||||
Bam! If all goes well, `Hello, world!` should print to the terminal once more.
|
||||
|
||||
Running `cargo build` for the first time also causes Cargo to create a new file
|
||||
at the top level called *Cargo.lock*, which looks like this:
|
||||
at the top level called *Cargo.lock*, which looks like Listing 1-3:
|
||||
|
||||
<span class="filename">Filename: Cargo.lock</span>
|
||||
|
||||
@@ -374,10 +384,13 @@ name = "hello_cargo"
|
||||
version = "0.1.0"
|
||||
```
|
||||
|
||||
Cargo uses the *Cargo.lock* to keep track of dependencies in your application.
|
||||
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.
|
||||
<span class="caption">Listing 1-3: Contents of *Cargo.lock* after running
|
||||
`cargo build`</span>
|
||||
|
||||
Cargo uses *Cargo.lock* to keep track of the exact versions of dependencies
|
||||
used to build your project. This project doesn’t have dependencies, so the file
|
||||
is a bit sparse. You won’t ever need to touch this file yourself; Cargo will
|
||||
manage its contents for you.
|
||||
|
||||
We just built a project with `cargo build` and ran it with
|
||||
`./target/debug/hello_cargo`, but we can also use `cargo run` to compile and
|
||||
@@ -393,7 +406,7 @@ Hello, world!
|
||||
Notice that this time, we didn’t see the output telling us that Cargo was
|
||||
compiling `hello_cargo`. Cargo figured out that the files haven’t changed, so
|
||||
it just ran the binary. If you had modified your source code, Cargo would have
|
||||
rebuilt the project before running it, and you would have seen something like
|
||||
rebuilt the project before running it, and you would have seen output like
|
||||
this:
|
||||
|
||||
```text
|
||||
@@ -404,8 +417,8 @@ $ cargo run
|
||||
Hello, world!
|
||||
```
|
||||
|
||||
Finally, there's `cargo check`. This will check out your code to make sure that
|
||||
it compiles, but not bother producing an executable:
|
||||
Finally, there's `cargo check`. This will quickly check your code to make sure
|
||||
that it compiles, but not bother producing an executable:
|
||||
|
||||
```text
|
||||
$ cargo check
|
||||
@@ -414,11 +427,11 @@ $ cargo check
|
||||
```
|
||||
|
||||
Why would you not want an executable? `cargo check` is often much faster than
|
||||
`cargo build`, since we can skip that entire step. If we're checking our work,
|
||||
rather than producing a build to run, this will speed things up! As such, many
|
||||
Rustaceans run `cargo check` as they write their program to make sure that it
|
||||
compiles, and then run `cargo build` once they're ready to give it a spin
|
||||
themselves.
|
||||
`cargo build`, because Cargo can skip the entire step of producing the
|
||||
executable. If we're checking our work throughouth the process of writing the
|
||||
code, this will speed things up! As such, many Rustaceans run `cargo check` as
|
||||
they write their program to make sure that it compiles, and then run `cargo
|
||||
build` once they're ready to give it a spin themselves.
|
||||
|
||||
So a few more differences we’ve now seen:
|
||||
|
||||
@@ -450,10 +463,13 @@ With simple projects, Cargo doesn’t provide a whole lot of value over just
|
||||
using `rustc`, but it will prove its worth as you continue. With complex
|
||||
projects composed of multiple crates, it’s much easier to let Cargo coordinate
|
||||
the build. With Cargo, you can just run `cargo build`, and it should work the
|
||||
right way. Even though this project is simple, it now uses much of the real
|
||||
right way.
|
||||
|
||||
Even though the `hello_cargo` project is simple, it now uses much of the real
|
||||
tooling you’ll use for the rest of your Rust career. In fact, you can get
|
||||
started with virtually all Rust projects you want to work on with the following
|
||||
commands:
|
||||
commands to check out the code using Git, change into the project directory,
|
||||
and build:
|
||||
|
||||
```text
|
||||
$ git clone someurl.com/someproject
|
||||
@@ -461,7 +477,7 @@ $ cd someproject
|
||||
$ cargo build
|
||||
```
|
||||
|
||||
> Note: If you want to look at Cargo in more detail, check out [its
|
||||
> documentation], which covers all of its features.
|
||||
If you want to look at Cargo in more detail, check out [its documentation],
|
||||
which covers all of its features.
|
||||
|
||||
[its documentation]: http://doc.crates.io/
|
||||
[its documentation]: https://doc.rust-lang.org/cargo/
|
||||
|
||||
@@ -2,51 +2,49 @@
|
||||
|
||||
Before we dive into the language itself, we'd like to finish up the
|
||||
introductory chapter by talking about how Rust is made, and how that affects
|
||||
you as a Rust developer. The output in this book was generated by stable Rust
|
||||
1.21.0. Any examples that compile should continue to compile in any stable
|
||||
version of Rust greater than that, but you may see some improvements in the
|
||||
output or error messages. Part of this chapter is to explain how we ensure that
|
||||
this is true!
|
||||
|
||||
Feel free to skip this section and come back to it after you've learned the
|
||||
language if you'd like!
|
||||
you as a Rust developer. We mentioned in the "Installation" section that the
|
||||
output in this book was generated by stable Rust 1.21.0, but any examples that
|
||||
compile should continue to compile in any stable version of Rust greater than
|
||||
that. This section is to explain how we ensure this is true!
|
||||
|
||||
### Stability Without Stagnation
|
||||
|
||||
As a language, Rust cares a *lot* about the stability of your code. We want
|
||||
Rust to be a rock-solid foundation that you can build on, and if things were
|
||||
constantly changing, that would be impossible. At the same time, if we cannot
|
||||
Rust to be a rock-solid foundation you can build on, and if things were
|
||||
constantly changing, that would be impossible. At the same time, if we can't
|
||||
experiment with new features, we may not find out important flaws until after
|
||||
their release, when we can no longer change things.
|
||||
|
||||
Our solution to this problem is what we call "stability without stagnation";
|
||||
that is, the way we can change and improve Rust while making sure that for our
|
||||
users, things stay nice, stable, and boring.
|
||||
Our solution to this problem is what we call "stability without stagnation" and
|
||||
is the way we can change and improve Rust while making sure that using Rust
|
||||
stays nice, stable, and boring.
|
||||
|
||||
Our guiding principle for Rust releases is this: you should never have to fear
|
||||
upgrading to a new version of stable Rust. Each upgrade should be painless. At
|
||||
the same time, the upgrade should bring you new features, less bugs, and faster
|
||||
compile times.
|
||||
the same time, the upgrade should bring you new features, fewer bugs, and
|
||||
faster compile times.
|
||||
|
||||
### Choo, Choo! Release Channels and Riding the Trains
|
||||
|
||||
Rust development operates on a *train schedule*. That is, all development is
|
||||
done on the `master` branch of the Rust repository, and releases follow "the
|
||||
train model." There are three *release channels* for Rust:
|
||||
done on the `master` branch of the Rust repository. Releases follow a software
|
||||
release train model, which has been used by Cisco IOS and other software
|
||||
projects. There are three *release channels* for Rust:
|
||||
|
||||
* Nightly
|
||||
* Beta
|
||||
* Stable
|
||||
|
||||
Most Rust developers primarily use Rust Stable, but those who want to try out
|
||||
experimental new features may use nightly or beta. Here's an example of how
|
||||
this works: let's assume that the Rust team is working on the release of Rust
|
||||
1.5. That release happened in December of 2015, but it will provide us with
|
||||
realistic version numbers. A new feature is added to Rust: a new commit lands
|
||||
on the `master` branch. Each night, a new nightly version of Rust is produced.
|
||||
Every day is a release day, and these releases are created by our release
|
||||
infrastructure automatically. So as time passes, our releases look like this,
|
||||
once a night:
|
||||
Most Rust developers primarily use the stable channel, but those who want to
|
||||
try out experimental new features may use nightly or beta.
|
||||
|
||||
Here's an example of how the development and release process works: let's
|
||||
assume that the Rust team is working on the release of Rust 1.5. That release
|
||||
happened in December of 2015, but it will provide us with realistic version
|
||||
numbers. A new feature is added to Rust: a new commit lands on the `master`
|
||||
branch. Each night, a new nightly version of Rust is produced. Every day is a
|
||||
release day, and these releases are created by our release infrastructure
|
||||
automatically. So as time passes, our releases look like this, once a night:
|
||||
|
||||
```text
|
||||
nightly: * - - * - - *
|
||||
@@ -62,9 +60,9 @@ nightly: * - - * - - *
|
||||
beta: *
|
||||
```
|
||||
|
||||
Most Rust users do not use beta actively, but test against beta in their CI
|
||||
system to help test against regressions. In the meantime, there's still a
|
||||
nightly release every night:
|
||||
Most Rust users do not use beta releases actively, but test against beta in
|
||||
their CI system to help Rust discover possible regressions. In the meantime,
|
||||
there's still a nightly release every night:
|
||||
|
||||
```text
|
||||
nightly: * - - * - - * - - * - - *
|
||||
@@ -72,10 +70,10 @@ nightly: * - - * - - * - - * - - *
|
||||
beta: *
|
||||
```
|
||||
|
||||
Let's say a regression is found. Good thing we had some time on beta before it
|
||||
snuck into a release! The fix is applied to `master`, so that nightly is fixed,
|
||||
and then the fix is backported to the beta branch, and a new release of beta is
|
||||
produced:
|
||||
Let's say a regression is found. Good thing we had some time to test the beta
|
||||
release before the regression snuck into a stable release! The fix is applied
|
||||
to `master`, so that nightly is fixed, and then the fix is backported to the
|
||||
`beta` branch, and a new release of beta is produced:
|
||||
|
||||
```text
|
||||
nightly: * - - * - - * - - * - - * - - *
|
||||
@@ -94,7 +92,7 @@ beta: * - - - - - - - - *
|
||||
stable: *
|
||||
```
|
||||
|
||||
Hooray! Rust 1.5 is done! However, we've forgotten one thing: since the six
|
||||
Hooray! Rust 1.5 is done! However, we've forgotten one thing: because the six
|
||||
weeks have gone by, we also need a new beta of the *next* version of Rust, 1.6.
|
||||
So after `stable` branches off of `beta`, the next version of `beta` branches
|
||||
off of `nightly` again:
|
||||
@@ -107,41 +105,42 @@ beta: * - - - - - - - - * *
|
||||
stable: *
|
||||
```
|
||||
|
||||
This is called the "train model" because every six weeks, the release "leaves
|
||||
the station", but still has to take a journey before it arrives. Another nice
|
||||
thing is that the next train is coming soon. If a feature happens to miss a
|
||||
particular release, there's no need to worry: another one is coming like
|
||||
clockwork! This helps reduce pressure to sneak things in close to the release
|
||||
deadline.
|
||||
This is called the "train model" because every six weeks, a release "leaves the
|
||||
station", but still has to take a journey through the beta channel before it
|
||||
arrives as a stable release.
|
||||
|
||||
This also means that Rust releases every six weeks, like clockwork. If you know
|
||||
the date of one Rust release, you can know the date of the next one: it's six
|
||||
weeks later.
|
||||
Rust releases every six weeks, like clockwork. If you know the date of one Rust
|
||||
release, you can know the date of the next one: it's six weeks later. A nice
|
||||
aspect of having releases scheduled every six weeks is that the next train is
|
||||
coming soon. If a feature happens to miss a particular release, there's no need
|
||||
to worry: another one is happening in a short time! This helps reduce pressure
|
||||
to sneak possibly unpolished features in close to the release deadline.
|
||||
|
||||
Thanks to this process, you can always check out the next build of Rust and
|
||||
verify for yourself that it's easy to upgrade to: if something breaks, you can
|
||||
report it to the team and get it fixed before the next release happens! This is
|
||||
relatively rare, but `rustc` is still a piece of software, and bugs do exist.
|
||||
verify for yourself that it's easy to upgrade to: if a beta release doesn't
|
||||
work as expected, you can report it to the team and get it fixed before the
|
||||
next stable release happens! Breakage in a beta release is relatively rare, but
|
||||
`rustc` is still a piece of software, and bugs do exist.
|
||||
|
||||
### Unstable Features
|
||||
|
||||
There's one more catch with this release model: unstable features. Rust uses a
|
||||
technique called "feature flags" to determine what features are enabled in a
|
||||
given release. If a new feature is under active development, it lands on
|
||||
`master`, and therefore, in nightly, but behind a *feature flag*. If you as a
|
||||
user wish to try out the work-in-progress feature, you can, but you must
|
||||
annotate your source code with the appropriate flag to opt in.
|
||||
`master`, and therefore, in nightly, but behind a *feature flag*. If you, as a
|
||||
user, wish to try out the work-in-progress feature, you can, but you must be
|
||||
using a nightly release of Rust and annotate your source code with the
|
||||
appropriate flag to opt in.
|
||||
|
||||
There's one more piece to this puzzle: if you're using a beta or stable release
|
||||
of Rust, you cannot use any feature flags. This is the key that allows us to
|
||||
get practical use with new features before we declare them stable forever.
|
||||
Those who wish to opt into the bleeding edge can do so, and those who want a
|
||||
rock-solid experience can stick with stable and know that their code won't
|
||||
break. Stability without stagnation.
|
||||
If you're using a beta or stable release of Rust, you can't use any feature
|
||||
flags. This is the key that allows us to get practical use with new features
|
||||
before we declare them stable forever. Those who wish to opt into the bleeding
|
||||
edge can do so, and those who want a rock-solid experience can stick with
|
||||
stable and know that their code won't break. Stability without stagnation.
|
||||
|
||||
This book only contains information about stable features, as in-progress
|
||||
features are still changing, and surely they'll be different between when this
|
||||
book was written and when they were enabled in stable builds. You can find
|
||||
book was written and when they get enabled in stable builds. You can find
|
||||
documentation for nightly-only features online.
|
||||
|
||||
### Rustup and the Role of Rust Nightly
|
||||
@@ -150,12 +149,13 @@ Rustup makes it easy to change between different release channels of Rust, on a
|
||||
global or per-project basis. By default, you'll have stable Rust installed. To
|
||||
install nightly, for example:
|
||||
|
||||
```bash
|
||||
```text
|
||||
$ rustup install nightly
|
||||
```
|
||||
|
||||
You can see all of the toolchains you have installed with `rustup` as well.
|
||||
Here's an example on one of your authors' computers:
|
||||
You can see all of the *toolchains* (releases of Rust and associated
|
||||
components) you have installed with `rustup` as well. Here's an example on one
|
||||
of your authors' computers:
|
||||
|
||||
```powershell
|
||||
> rustup toolchain list
|
||||
@@ -165,44 +165,47 @@ nightly-x86_64-pc-windows-msvc
|
||||
```
|
||||
|
||||
As you can see, the stable toolchain is the default. Most Rust users use stable
|
||||
most of the time. But maybe you want to use stable most of the time, but use
|
||||
most of the time. You might want to use stable most of the time, but use
|
||||
nightly on a specific project, because you care about a cutting-edge feature.
|
||||
To do so, you can use `rustup override`:
|
||||
To do so, you can use `rustup override` in that project's directory to set the
|
||||
nightly toolchain as the one `rustup` should use when you're in that directory:
|
||||
|
||||
```bash
|
||||
```text
|
||||
$ cd ~/projects/needs-nightly
|
||||
$ rustup override add nightly
|
||||
```
|
||||
|
||||
Now, every time you call `rustc` or `cargo` inside of
|
||||
`~/projects/needs-nightly`, `rustup` will make sure that you are using nightly
|
||||
Rust, rather than the default of stable. This comes in handy when you have a
|
||||
lot of Rust projects!
|
||||
*~/projects/needs-nightly*, `rustup` will make sure that you are using nightly
|
||||
Rust, rather than your default of stable Rust. This comes in handy when you
|
||||
have a lot of Rust projects!
|
||||
|
||||
### The RFC Process and Teams
|
||||
|
||||
So how do you learn about these new features? Rust's development model follows
|
||||
*the RFC process*. If you'd like an improvement in Rust, you can write up a
|
||||
proposal, called an RFC. This stands for "request for comments", and when you
|
||||
submit one, you'll get many.
|
||||
a *Request For Comments (RFC) process*. If you'd like an improvement in Rust,
|
||||
you can write up a proposal, called an RFC.
|
||||
|
||||
Anyone can write RFCs to improve Rust, and the proposals are reviewed and
|
||||
discussed by the Rust team, which is comprised of many individual teams.
|
||||
There's a full list on Rust's website, but there are teams for each area of the
|
||||
project: language design, compiler implementation, infrastructure,
|
||||
documentation, and more. The appropriate team reads the comments, writes some
|
||||
of their own, and eventually, there's consensus to accept or reject the feature.
|
||||
discussed by the Rust team, which is comprised of many topic subteams. There's
|
||||
a full list of the teams [on Rust's
|
||||
website](https://www.rust-lang.org/en-US/team.html), which includes teams for
|
||||
each area of the project: language design, compiler implementation,
|
||||
infrastructure, documentation, and more. The appropriate team reads the
|
||||
proposal and the comments, writes some comments of their own, and eventually,
|
||||
there's consensus to accept or reject the feature.
|
||||
|
||||
If the feature is accepted, an issue is opened on the Rust repository, and
|
||||
someone can implement it. The person who implements it very well may not be the
|
||||
person who proposed the feature in the first place! When the implementation is
|
||||
ready, it lands on the `master` branch behind a feature gate, as we discussed
|
||||
above.
|
||||
in the "Unstable Features" section.
|
||||
|
||||
After some time, once nightly developers have been able to actually try out the
|
||||
new feature, team members will discuss the feature, how it's worked out on
|
||||
nightly, and decide if it should make it into stable Rust or not. If the
|
||||
decision is to move forward, the feature gate is removed, and the feature is
|
||||
now considered stable! It rides the trains into a new stable release of Rust.
|
||||
After some time, once Rust developers who use nightly releases have been able
|
||||
to try out the new feature, team members will discuss the feature, how it's
|
||||
worked out on nightly, and decide if it should make it into stable Rust or not.
|
||||
If the decision is to move forward, the feature gate is removed, and the
|
||||
feature is now considered stable! It rides the trains into a new stable release
|
||||
of Rust.
|
||||
|
||||
## Summary
|
||||
|
||||
Reference in New Issue
Block a user