Appendix
Appendices A–G
The following sections contain reference material you may find useful in your Rust journey: the keyword and symbol tables, the traits you can derive, the tools that ship with Rust, how editions work, translations of the book, and how Rust itself is made.
- A Keywords
- B Operators and Symbols
- C Derivable Traits
- D Useful Development Tools
- E Editions
- F Translations of the Book
- G How Rust is Made and “Nightly Rust”
The Rust Programming Language · Appendix
1
Appendix · A Keywords
Keywords are reserved words
The following lists contain keywords that are reserved for current or future use by the Rust language. As such, they cannot be used as identifiers — except as raw identifiers, discussed in “Raw Identifiers” at the end of this appendix.
Definition A.1 (Identifier). A name of a function, variable, parameter, struct field, module, crate, constant, macro, static value, attribute, type, trait, or lifetime.
Appendix A has three parts:
- Keywords currently in use — each listed with its functionality (Table A.1, four slides).
- Keywords reserved for future use — no functionality yet (Table A.2).
- Raw identifiers — the r# syntax that lets you use a keyword as an identifier.
The Rust Programming Language · Appendix
2
Appendix · A Keywords
Keywords currently in use (1 of 4): as – enum
Table A.1: Keywords currently in use, with their functionality
| Keyword | Functionality |
|---|---|
| as | Perform primitive casting, disambiguate the specific trait containing an item, or rename items in use statements |
| async | Return a Future instead of blocking the current thread |
| await | Suspend execution until the result of a Future is ready |
| break | Exit a loop immediately |
| const | Define constant items or constant raw pointers |
| continue | Continue to the next loop iteration |
| crate | In a module path, refers to the crate root |
| dyn | Dynamic dispatch to a trait object |
| else | Fallback for if and if let control flow constructs |
| enum | Define an enumeration |
The Rust Programming Language · Appendix
3
Appendix · A Keywords
Keywords currently in use (2 of 4): extern – match
Table A.1 (continued): Keywords currently in use, with their functionality
| Keyword | Functionality |
|---|---|
| extern | Link an external function or variable |
| false | Boolean false literal |
| fn | Define a function or the function pointer type |
| for | Loop over items from an iterator, implement a trait, or specify a higher ranked lifetime |
| if | Branch based on the result of a conditional expression |
| impl | Implement inherent or trait functionality |
| in | Part of for loop syntax |
| let | Bind a variable |
| loop | Loop unconditionally |
| match | Match a value to patterns |
The Rust Programming Language · Appendix
4
Appendix · A Keywords
Keywords currently in use (3 of 4): mod – struct
Table A.1 (continued): Keywords currently in use, with their functionality
| Keyword | Functionality |
|---|---|
| mod | Define a module |
| move | Make a closure take ownership of all its captures |
| mut | Denote mutability in references, raw pointers, or pattern bindings |
| pub | Denote public visibility in struct fields, impl blocks, or modules |
| ref | Bind by reference |
| return | Return from function |
| Self | A type alias for the type we are defining or implementing |
| self | Method subject or current module |
| static | Global variable or lifetime lasting the entire program execution |
| struct | Define a structure |
The Rust Programming Language · Appendix
5
Appendix · A Keywords
Keywords currently in use (4 of 4): super – while
Table A.1 (continued): Keywords currently in use, with their functionality
| Keyword | Functionality |
|---|---|
| super | Parent module of the current module |
| trait | Define a trait |
| true | Boolean true literal |
| type | Define a type alias or associated type |
| union | Define a union; is a keyword only when used in a union declaration |
| unsafe | Denote unsafe code, functions, traits, or implementations |
| use | Bring symbols into scope |
| where | Denote clauses that constrain a type |
| while | Loop conditionally based on the result of an expression |
Remark. union is a contextual keyword: outside a union declaration it can still be used as an ordinary identifier. See the Rust Reference, “Unions”.
The Rust Programming Language · Appendix
6
Appendix · A Keywords
Keywords reserved for future use
The following keywords do not yet have any functionality but are reserved by Rust for potential future use. Like the keywords in use, they cannot be ordinary identifiers.
Table A.2: Keywords reserved for future use (14 keywords)
| Reserved keyword | Reserved keyword |
|---|---|
| abstract | override |
| become | priv |
| box | try |
| do | typeof |
| final | unsized |
| gen | virtual |
| macro | yield |
The Rust Programming Language · Appendix
7
Appendix · A Keywords
Raw identifiers: the problem
Definition A.2 (Raw identifier). The syntax that lets you use keywords where they wouldn’t normally be allowed: you prefix a keyword with r#.
For example, match is a keyword. Try to compile a function that uses match as its name:
src/main.rs
fn match(needle: &str, haystack: &str) -> bool {
haystack.contains(needle)
}
You’ll get this error:
error: expected identifier, found keyword `match`
--> src/main.rs:4:4
|
4 | fn match(needle: &str, haystack: &str) -> bool {
| ^^^^^ expected identifier, found keyword
The error shows that you can’t use the keyword match as the function identifier. To use match as a function name, you need the raw identifier syntax.
The Rust Programming Language · Appendix
8
Appendix · A Keywords
Raw identifiers: the fix, and why they exist
src/main.rs
fn r#match(needle: &str, haystack: &str) -> bool {
haystack.contains(needle)
}
fn main() {
assert!(r#match("foo", "foobar"));
}
This code compiles without any errors. Note the r# prefix on the function name both in its definition and where the function is called in main.
Raw identifiers let you use any word you choose as an identifier, even a reserved keyword. That gives more freedom in naming and lets Rust integrate with programs written in a language where these words aren’t keywords.
Example A.3. Raw identifiers also let you use libraries written in a different Rust edition than your crate. try isn’t a keyword in the 2015 edition but is in the 2018, 2021, and 2024 editions. If you depend on a 2015-edition library that has a try function, you call it as r#try from your code on later editions. (Editions: Appendix E.)
The Rust Programming Language · Appendix
9
Appendix · B Operators and Symbols
A glossary of Rust’s syntax
This appendix contains a glossary of Rust’s syntax, including operators and other symbols that appear by themselves or in the context of paths, generics, trait bounds, macros, attributes, comments, tuples, and brackets.
Operators
Table A.3 (the book’s Table B-1, next six slides) lists the operators in Rust, an example of how each operator would appear in context, a short explanation, and whether that operator is overloadable. If an operator is overloadable, the relevant trait to use to overload that operator is listed.
Example A.4. The row for + in expr + expr names the trait Add: implement std::ops::Add for your type and a + b works on it. Rows with an empty last cell (such as &&) cannot be overloaded.
The non-operator symbols follow in Tables A.4–A.12 (the book’s Tables B-2 to B-10).
The Rust Programming Language · Appendix
10
Appendix · B Operators and Symbols
Operators (1 of 6): ! to &&
Table A.3: Operators (book Table B-1) — “—” means not overloadable
| Operator | Example | Explanation | Overloadable? |
|---|---|---|---|
| ! | ident!(...), ident!{...}, ident![...] | Macro expansion | — |
| ! | !expr | Bitwise or logical complement | Not |
| != | expr != expr | Nonequality comparison | PartialEq |
| % | expr % expr | Arithmetic remainder | Rem |
| %= | var %= expr | Arithmetic remainder and assignment | RemAssign |
| & | &expr, &mut expr | Borrow | — |
| & | &type, &mut type, &'a type, &'a mut type | Borrowed pointer type | — |
| & | expr & expr | Bitwise AND | BitAnd |
| &= | var &= expr | Bitwise AND and assignment | BitAndAssign |
| && | expr && expr | Short-circuiting logical AND | — |
The Rust Programming Language · Appendix
11
Appendix · B Operators and Symbols
Operators (2 of 6): * to -
Table A.3 (continued): Operators (book Table B-1)
| Operator | Example | Explanation | Overloadable? |
|---|---|---|---|
| * | expr * expr | Arithmetic multiplication | Mul |
| *= | var *= expr | Arithmetic multiplication and assignment | MulAssign |
| * | *expr | Dereference | Deref |
| * | *const type, *mut type | Raw pointer | — |
| + | trait + trait, 'a + trait | Compound type constraint | — |
| + | expr + expr | Arithmetic addition | Add |
| += | var += expr | Arithmetic addition and assignment | AddAssign |
| , | expr, expr | Argument and element separator | — |
| - | - expr | Arithmetic negation | Neg |
| - | expr - expr | Arithmetic subtraction | Sub |
The Rust Programming Language · Appendix
12
Appendix · B Operators and Symbols
Operators (3 of 6): -= to ..
Table A.3 (continued): Operators (book Table B-1)
| Operator | Example | Explanation | Overloadable? |
|---|---|---|---|
| -= | var -= expr | Arithmetic subtraction and assignment | SubAssign |
| -> | fn(...) -> type, |…| -> type | Function and closure return type | — |
| . | expr.ident | Field access | — |
| . | expr.ident(expr, ...) | Method call | — |
| . | expr.0, expr.1, and so on | Tuple indexing | — |
| .. | .., expr.., ..expr, expr..expr | Right-exclusive range literal | PartialOrd |
| ..= | ..=expr, expr..=expr | Right-inclusive range literal | PartialOrd |
| .. | ..expr | Struct literal update syntax | — |
| .. | variant(x, ..), struct_type { x, .. } | “And the rest” pattern binding | — |
The Rust Programming Language · Appendix
13
Appendix · B Operators and Symbols
Operators (4 of 6): ... to <<
Table A.3 (continued): Operators (book Table B-1)
| Operator | Example | Explanation | Overloadable? |
|---|---|---|---|
| ... | expr...expr | (Deprecated, use ..= instead) In a pattern: inclusive range pattern | — |
| / | expr / expr | Arithmetic division | Div |
| /= | var /= expr | Arithmetic division and assignment | DivAssign |
| : | pat: type, ident: type | Constraints | — |
| : | ident: expr | Struct field initializer | — |
| : | 'a: loop {...} | Loop label | — |
| ; | expr; | Statement and item terminator | — |
| ; | [...; len] | Part of fixed-size array syntax | — |
| << | expr << expr | Left-shift | Shl |
The Rust Programming Language · Appendix
14
Appendix · B Operators and Symbols
Operators (5 of 6): <<= to >>
Table A.3 (continued): Operators (book Table B-1)
| Operator | Example | Explanation | Overloadable? |
|---|---|---|---|
| <<= | var <<= expr | Left-shift and assignment | ShlAssign |
| < | expr < expr | Less than comparison | PartialOrd |
| <= | expr <= expr | Less than or equal to comparison | PartialOrd |
| = | var = expr, ident = type | Assignment/equivalence | — |
| == | expr == expr | Equality comparison | PartialEq |
| => | pat => expr | Part of match arm syntax | — |
| > | expr > expr | Greater than comparison | PartialOrd |
| >= | expr >= expr | Greater than or equal to comparison | PartialOrd |
| >> | expr >> expr | Right-shift | Shr |
The Rust Programming Language · Appendix
15
Appendix · B Operators and Symbols
Operators (6 of 6): >>= to ?
Table A.3 (continued): Operators (book Table B-1)
| Operator | Example | Explanation | Overloadable? |
|---|---|---|---|
| >>= | var >>= expr | Right-shift and assignment | ShrAssign |
| @ | ident @ pat | Pattern binding | — |
| ^ | expr ^ expr | Bitwise exclusive OR | BitXor |
| ^= | var ^= expr | Bitwise exclusive OR and assignment | BitXorAssign |
| | | pat | pat | Pattern alternatives | — |
| | | expr | expr | Bitwise OR | BitOr |
| |= | var |= expr | Bitwise OR and assignment | BitOrAssign |
| || | expr || expr | Short-circuiting logical OR | — |
| ? | expr? | Error propagation | — |
The Rust Programming Language · Appendix
16
Appendix · B Operators and Symbols
Non-operator symbols: stand-alone syntax (1 of 2)
The following tables contain all symbols that don’t function as operators; that is, they don’t behave like a function or method call. Table A.4 shows symbols that appear on their own and are valid in a variety of locations.
Table A.4: Stand-alone syntax (book Table B-2)
| Symbol | Explanation |
|---|---|
| 'ident | Named lifetime or loop label |
| Digits immediately followed by u8, i32, f64, usize, and so on | Numeric literal of specific type |
| "..." | String literal |
| r"...", r#"..."#, r##"..."##, and so on | Raw string literal; escape characters not processed |
| b"..." | Byte string literal; constructs an array of bytes instead of a string |
| br"...", br#"..."#, br##"..."##, and so on | Raw byte string literal; combination of raw and byte string literal |
The Rust Programming Language · Appendix
17
Appendix · B Operators and Symbols
Non-operator symbols: stand-alone syntax (2 of 2)
Table A.4 (continued): Stand-alone syntax (book Table B-2)
| Symbol | Explanation |
|---|---|
| '...' | Character literal |
| b'...' | ASCII byte literal |
| |…| expr | Closure |
| ! | Always-empty bottom type for diverging functions |
| _ | “Ignored” pattern binding; also used to make integer literals readable |
Example A.5. A few stand-alone symbols in use: a typed numeric literal made readable with _, a raw string, a byte string, and a closure.
let big = 1_000_000u32;
let path = r"C:\no\escapes";
let bytes = b"abc";
let double = |x: i32| x * 2;
The Rust Programming Language · Appendix
18
Appendix · B Operators and Symbols
Path-related syntax
Table A.5: Path-related syntax (book Table B-3) — symbols that appear in the context of a path through the module hierarchy to an item
| Symbol | Explanation |
|---|---|
| ident::ident | Namespace path |
| ::path | Path relative to the crate root (that is, an explicitly absolute path) |
| self::path | Path relative to the current module (that is, an explicitly relative path) |
| super::path | Path relative to the parent of the current module |
| type::ident, <type as trait>::ident | Associated constants, functions, and types |
| <type>::... | Associated item for a type that cannot be directly named (for example, <&T>::..., <[T]>::..., and so on) |
| trait::method(...) | Disambiguating a method call by naming the trait that defines it |
| type::method(...) | Disambiguating a method call by naming the type for which it’s defined |
| <type as trait>::method(...) | Disambiguating a method call by naming the trait and type |
The Rust Programming Language · Appendix
19
Appendix · B Operators and Symbols
Generics syntax
Table A.6: Generics (book Table B-4) — symbols that appear in the context of using generic type parameters
| Symbol | Explanation |
|---|---|
| path<...> | Specifies parameters to a generic type in a type (for example, Vec<u8>) |
| path::<...>, method::<...> | Specifies parameters to a generic type, function, or method in an expression; often referred to as turbofish (for example, "42".parse::<i32>()) |
| fn ident<...> ... | Define generic function |
| struct ident<...> ... | Define generic structure |
| enum ident<...> ... | Define generic enumeration |
| impl<...> ... | Define generic implementation |
| for<...> type | Higher ranked lifetime bounds |
| type<ident=type> | A generic type where one or more associated types have specific assignments (for example, Iterator<Item=T>) |
The Rust Programming Language · Appendix
20
Appendix · B Operators and Symbols
Trait bound constraints
Table A.7 shows symbols that appear in the context of constraining generic type parameters with trait bounds.
Table A.7: Trait bound constraints (book Table B-5)
| Symbol | Explanation |
|---|---|
| T: U | Generic parameter T constrained to types that implement U |
| T: 'a | Generic type T must outlive lifetime 'a (meaning the type cannot transitively contain any references with lifetimes shorter than 'a) |
| T: 'static | Generic type T contains no borrowed references other than 'static ones |
| 'b: 'a | Generic lifetime 'b must outlive lifetime 'a |
| T: ?Sized | Allow generic type parameter to be a dynamically sized type |
| 'a + trait, trait + trait | Compound type constraint |
The Rust Programming Language · Appendix
21
Appendix · B Operators and Symbols
Macros, attributes and comments
Symbols that appear in the context of calling or defining macros and specifying attributes on an item:
Table A.8: Macros and attributes (book Table B-6)
| Symbol | Explanation |
|---|---|
| #[meta] | Outer attribute |
| #![meta] | Inner attribute |
| $ident | Macro substitution |
| $ident:kind | Macro metavariable |
| $(...)... | Macro repetition |
| ident!(...), ident!{...}, ident![...] | Macro invocation |
Symbols that create comments:
Table A.9: Comments (book Table B-7)
| Symbol | Explanation |
|---|---|
| // | Line comment |
| //! | Inner line doc comment |
| /// | Outer line doc comment |
| /*...*/ | Block comment |
| /*!...*/ | Inner block doc comment |
| /**...*/ | Outer block doc comment |
The Rust Programming Language · Appendix
22
Appendix · B Operators and Symbols
Parentheses and curly brackets
Table A.10: Parentheses (book Table B-8) — the contexts in which parentheses are used
| Symbol | Explanation |
|---|---|
| () | Empty tuple (aka unit), both literal and type |
| (expr) | Parenthesized expression |
| (expr,) | Single-element tuple expression |
| (type,) | Single-element tuple type |
| (expr, ...) | Tuple expression |
| (type, ...) | Tuple type |
| expr(expr, ...) | Function call expression; also used to initialize tuple structs and tuple enum variants |
Table A.11: Curly brackets (book Table B-9) — the contexts in which curly brackets are used
| Context | Explanation |
|---|---|
| {...} | Block expression |
| Type {...} | Struct literal |
The Rust Programming Language · Appendix
23
Appendix · B Operators and Symbols
Square brackets
Table A.12: Square brackets (book Table B-10) — the contexts in which square brackets are used
| Context | Explanation |
|---|---|
| [...] | Array literal |
| [expr; len] | Array literal containing len copies of expr |
| [type; len] | Array type containing len instances of type |
| expr[expr] | Collection indexing; overloadable (Index, IndexMut) |
| expr[..], expr[a..], expr[..b], expr[a..b] | Collection indexing pretending to be collection slicing, using Range, RangeFrom, RangeTo, or RangeFull as the “index” |
The Rust Programming Language · Appendix
24
Appendix · C Derivable Traits
The derive attribute
Definition A.6 (derive attribute). An attribute you apply to a struct or enum definition; it generates code that implements a trait, with its own default implementation, on the type you’ve annotated with the derive syntax.
This appendix is a reference of all the traits in the standard library that you can use with derive. Each section covers:
- What operators and methods deriving this trait will enable
- What the implementation of the trait provided by derive does
- What implementing the trait signifies about the type
- The conditions in which you’re allowed or not allowed to implement the trait
- Examples of operations that require the trait
If you want different behavior from that provided by derive, consult the standard library documentation for each trait for details on how to implement it manually.
The Rust Programming Language · Appendix
25
Appendix · C Derivable Traits
Which traits can be derived — and which cannot
The traits listed here are the only ones defined by the standard library that can be implemented on your types using derive. Other standard library traits don’t have sensible default behavior, so it’s up to you to implement them in the way that makes sense for what you’re trying to accomplish.
Example A.7. Display, which handles formatting for end users, can’t be derived. You should always consider the appropriate way to display a type to an end user. What parts of the type should an end user be allowed to see? What parts would they find relevant? What format of the data would be most relevant to them? The Rust compiler doesn’t have this insight, so it can’t provide appropriate default behavior for you.
The list of derivable traits in this appendix is not comprehensive: libraries can implement derive for their own traits, making the list of traits you can use derive with truly open ended.
Remark. Implementing derive involves using a procedural macro, covered in the “Custom derive Macros” section in Chapter 20.
The Rust Programming Language · Appendix
26
Appendix · C Derivable Traits
Debug for programmer output
The Debug trait enables debug formatting in format strings, which you indicate by adding :? within {} placeholders.
Debug lets you print instances of a type for debugging purposes, so you and other programmers using your type can inspect an instance at a particular point in a program’s execution.
Required by: for example, the assert_eq! macro. It prints the values of the instances given as arguments if the equality assertion fails, so programmers can see why the two instances weren’t equal.
Example A.8. Deriving Debug and PartialEq (next slide) makes a struct printable and usable in assert_eq!.
#[derive(Debug, PartialEq)]
struct Point { x: i32, y: i32 }
let p = Point { x: 1, y: 2 };
println!("{p:?}"); // Point { x: 1, y: 2 }
assert_eq!(p, Point { x: 1, y: 2 });
The Rust Programming Language · Appendix
27
Appendix · C Derivable Traits
PartialEq and Eq for equality comparisons
PartialEq
Lets you compare instances of a type for equality and enables the == and != operators. Deriving it implements the eq method.
- On structs: two instances are equal only if all fields are equal, and not equal if any field is not equal.
- On enums: each variant is equal to itself and not equal to the other variants.
Required by: for example, assert_eq!, which must compare two instances for equality.
Eq
Has no methods. It signals that for every value of the annotated type, the value is equal to itself. Eq can only be applied to types that also implement PartialEq — but not all such types can implement Eq.
Floating-point types are one example: two instances of the not-a-number (NaN) value are not equal to each other.
Required by: keys in a HashMap<K, V>, so it can tell whether two keys are the same.
The Rust Programming Language · Appendix
28
Appendix · C Derivable Traits
PartialOrd for ordering comparisons
The PartialOrd trait lets you compare instances of a type for sorting purposes. A type that implements PartialOrd can be used with the <, >, <=, and >= operators. You can only apply PartialOrd to types that also implement PartialEq.
Deriving PartialOrd implements the partial_cmp method, which returns an Option<Ordering> that is None when the values given don’t produce an ordering. An example of a value that doesn’t produce an ordering, even though most values of its type can be compared, is the NaN floating-point value: calling partial_cmp with any floating-point number and NaN returns None.
- On structs: compares two instances by comparing the value in each field, in the order the fields appear in the struct definition.
- On enums: variants declared earlier in the enum definition are considered less than the variants listed later.
Required by: for example, the gen_range method from the rand crate, which generates a random value in the range specified by a range expression.
The Rust Programming Language · Appendix
29
Appendix · C Derivable Traits
Ord for total ordering
The Ord trait lets you know that for any two values of the annotated type, a valid ordering will exist. It implements the cmp method, which returns an Ordering rather than an Option<Ordering>, because a valid ordering is always possible.
You can only apply Ord to types that also implement PartialOrd and Eq (and Eq requires PartialEq). When derived on structs and enums, cmp behaves the same way as the derived partial_cmp does with PartialOrd.
Required by: storing values in a BTreeSet<T>, a data structure that stores data based on the sort order of the values.
Example A.9. A derived ordering on an enum follows declaration order, so the whole chain of traits is derived together:
#[derive(PartialEq, Eq, PartialOrd, Ord)]
enum Size { Small, Medium, Large }
assert!(Size::Small < Size::Large); // declared earlier => less
The Rust Programming Language · Appendix
30
Appendix · C Derivable Traits
Clone for duplicating values
The Clone trait lets you explicitly create a deep copy of a value; the duplication process might involve running arbitrary code and copying heap data. (More on Clone: “Variables and Data Interacting with Clone”, Chapter 4.)
Deriving Clone implements the clone method, which, when implemented for the whole type, calls clone on each of the parts of the type. This means all the fields or values in the type must also implement Clone to derive Clone.
Required by: calling the to_vec method on a slice. The slice doesn’t own the type instances it contains, but the vector returned from to_vec needs to own its instances, so to_vec calls clone on each item. Thus, the type stored in the slice must implement Clone.
The Rust Programming Language · Appendix
31
Appendix · C Derivable Traits
Copy for duplicating values cheaply
The Copy trait lets you duplicate a value by only copying bits stored on the stack; no arbitrary code is necessary. (More on Copy: “Stack-Only Data: Copy”, Chapter 4.)
Copy doesn’t define any methods, to prevent programmers from overloading those methods and violating the assumption that no arbitrary code is being run. That way, all programmers can assume that copying a value will be very fast.
You can derive Copy on any type whose parts all implement Copy. A type that implements Copy must also implement Clone, because a Copy type has a trivial implementation of Clone that performs the same task as Copy.
Rarely required: types that implement Copy have optimizations available, meaning you don’t have to call clone, which makes the code more concise.
Remark. Everything possible with Copy you can also accomplish with Clone, but the code might be slower or have to use clone in places.
The Rust Programming Language · Appendix
32
Appendix · C Derivable Traits
Hash for mapping a value to a value of fixed size
The Hash trait lets you take an instance of a type of arbitrary size and map that instance to a value of fixed size using a hash function.
Deriving Hash implements the hash method. The derived implementation combines the result of calling hash on each of the parts of the type, meaning all fields or values must also implement Hash to derive Hash.
Required by: storing keys in a HashMap<K, V> to store data efficiently.
Example A.10. A type used as a HashMap key needs Hash plus Eq (and so PartialEq):
#[derive(PartialEq, Eq, Hash)]
struct UserId(u32);
let mut names: HashMap<UserId, String> = HashMap::new();
names.insert(UserId(7), String::from("Ferris"));
The Rust Programming Language · Appendix
33
Appendix · C Derivable Traits
Default for default values
The Default trait lets you create a default value for a type. Deriving Default implements the default function, whose derived implementation calls default on each part of the type — so all fields or values in the type must also implement Default to derive Default.
Default::default is commonly combined with the struct update syntax (“Creating Instances from Other Instances with Struct Update Syntax”, Chapter 5): customize a few fields of a struct, then set and use a default value for the rest with ..Default::default().
Required by: for example, the method unwrap_or_default on Option<T>. If the Option<T> is None, unwrap_or_default returns the result of Default::default for the type T stored in the Option<T>.
Example A.11. Struct update syntax with derived defaults:
#[derive(Default)]
struct Config { verbose: bool, retries: u32, name: String }
let c = Config { retries: 3, ..Default::default() }; // verbose: false, name: ""
The Rust Programming Language · Appendix
34
Appendix · D Useful Development Tools
Automatic formatting with rustfmt
This appendix covers useful development tools that the Rust project provides: automatic formatting, quick ways to apply warning fixes, a linter, and integration with IDEs.
The rustfmt tool reformats your code according to the community code style. Many collaborative projects use rustfmt to prevent arguments about which style to use when writing Rust: everyone formats their code using the tool.
Rust installations include rustfmt by default, so you should already have the programs rustfmt and cargo-fmt. They are analogous to rustc and cargo: rustfmt allows finer-grained control, and cargo-fmt understands the conventions of a project that uses Cargo. To format any Cargo project:
$ cargo fmt
This reformats all the Rust code in the current crate. It should only change the code style, not the code semantics. More: the rustfmt documentation (github.com/rust-lang/rustfmt).
The Rust Programming Language · Appendix
35
Appendix · D Useful Development Tools
Fix your code with rustfix: a warning
The rustfix tool is included with Rust installations and can automatically fix compiler warnings that have a clear way to correct the problem that’s likely what you want. Consider this code:
src/main.rs
fn main() {
let mut x = 42;
println!("{x}");
}
We define x as mutable but never actually mutate it. Rust warns us about that (right).
$ cargo build
Compiling myprogram v0.1.0 (file:///projects/myprogram)
warning: variable does not need to be mutable
--> src/main.rs:2:9
|
2 | let mut x = 0;
| ----^
| |
| help: remove this `mut`
|
= note: `#[warn(unused_mut)]` on by default
The Rust Programming Language · Appendix
36
Appendix · D Useful Development Tools
Fix your code with rustfix: cargo fix
The warning suggests removing the mut keyword. We can apply that suggestion automatically with the rustfix tool by running cargo fix:
Running cargo fix:
$ cargo fix
Checking myprogram v0.1.0 (file:///projects/myprogram)
Fixing src/main.rs (1 fix)
Finished dev [unoptimized + debuginfo] target(s) in 0.59s
src/main.rs afterwards — changed by cargo fix:
fn main() {
let x = 42;
println!("{x}");
}
The variable x is now immutable, and the warning no longer appears. You can also use cargo fix to transition your code between different Rust editions (Appendix E).
The Rust Programming Language · Appendix
37
Appendix · D Useful Development Tools
More lints with Clippy
Definition A.12 (Clippy). A collection of lints that analyze your code so you can catch common mistakes and improve your Rust code. Clippy is included with standard Rust installations.
To run Clippy’s lints on any Cargo project, enter:
$ cargo clippy
For example, say you write a program that uses an approximation of a mathematical constant, such as pi:
src/main.rs
fn main() {
let x = 3.1415;
let r = 8.0;
println!("the area of the circle is {}", x * r * r);
}
The Rust Programming Language · Appendix
38
Appendix · D Useful Development Tools
Clippy’s approx_constant error
Running cargo clippy on this project results in this error:
error: approximate value of `f{32, 64}::consts::PI` found
--> src/main.rs:2:13
|
2 | let x = 3.1415;
| ^^^^^^
|
= note: `#[deny(clippy::approx_constant)]` on by default
= help: consider using the constant directly
= help: for further information visit
https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant
This error lets you know that Rust already has a more precise PI constant defined, and that your program would be more correct if you used the constant instead. You would then change your code to use the PI constant.
The Rust Programming Language · Appendix
39
Appendix · D Useful Development Tools
Clippy: the fixed program
The following code doesn’t result in any errors or warnings from Clippy:
src/main.rs
fn main() {
let x = std::f64::consts::PI;
let r = 8.0;
println!("the area of the circle is {}", x * r * r);
}
Remark. For more information on Clippy, see its documentation (github.com/rust-lang/rust-clippy).
The Rust Programming Language · Appendix
40
Appendix · D Useful Development Tools
IDE integration using rust-analyzer
To help with IDE integration, the Rust community recommends using rust-analyzer (rust-analyzer.github.io). This tool is a set of compiler-centric utilities that speak the Language Server Protocol.
Definition A.13 (Language Server Protocol). A specification for IDEs and programming languages to communicate with each other (langserver.org).
Different clients can use rust-analyzer, such as the Rust analyzer plug-in for Visual Studio Code.
- Visit the rust-analyzer project’s home page (rust-analyzer.github.io) for installation instructions.
- Install the language server support in your particular IDE.
Your IDE then gains capabilities such as autocompletion, jump to definition, and inline errors.
The Rust Programming Language · Appendix
41
Appendix · E Editions
Why Rust has editions
In Chapter 1, cargo new added a bit of metadata about an edition to your Cargo.toml file. This appendix explains what that means.
The Rust language and compiler have a six-week release cycle, so users get a constant stream of new features. Other programming languages release larger changes less often; Rust releases smaller updates more frequently. After a while, all of these tiny changes add up — but from release to release, it can be difficult to look back and say, “Wow, between Rust 1.10 and Rust 1.31, Rust has changed a lot!”
Definition A.14 (Edition). A package, produced by the Rust team every three years or so, that brings together the features that have landed into a clear package with fully updated documentation and tooling. New editions ship as part of the usual six-week release process.
The Rust Programming Language · Appendix
42
Appendix · E Editions
Choosing an edition
Editions serve different purposes for different people:
- For active Rust users, a new edition brings together incremental changes into an easy-to-understand package.
- For non-users, it signals that some major advancements have landed, which might make Rust worth another look.
- For those developing Rust, it provides a rallying point for the project as a whole.
At the time of this writing, four Rust editions are available: Rust 2015, Rust 2018, Rust 2021, and Rust 2024. The book is written using Rust 2024 edition idioms.
The edition key in Cargo.toml indicates which edition the compiler should use for your code. If the key doesn’t exist, Rust uses 2015 as the edition value, for backward compatibility reasons.
Each project can opt in to an edition other than the default 2015 edition. Editions can contain incompatible changes, such as a new keyword that conflicts with identifiers in code. However, unless you opt in to those changes, your code will continue to compile even as you upgrade the Rust compiler version you use.
The Rust Programming Language · Appendix
43
Appendix · E Editions
Editions interoperate
All Rust compiler versions support any edition that existed prior to that compiler’s release, and they can link crates of any supported editions together. Edition changes only affect the way the compiler initially parses code.
Example A.15. If you’re using Rust 2015 and one of your dependencies uses Rust 2018, your project will compile and be able to use that dependency. The opposite situation — your project uses Rust 2018 and a dependency uses Rust 2015 — works as well.
To be clear: most features will be available on all editions, and developers using any Rust edition will continue to see improvements as new stable releases are made. However, in some cases, mainly when new keywords are added, some new features might only be available in later editions. You will need to switch editions if you want to take advantage of such features.
Remark. For more details, see The Rust Edition Guide (doc.rust-lang.org/stable/edition-guide), a complete book that enumerates the differences between editions and explains how to automatically upgrade your code to a new edition via cargo fix.
The Rust Programming Language · Appendix
44
Appendix · F Translations
Translations of the book (1 of 3)
Resources in languages other than English. Most are still in progress; see the Translations label on the book’s GitHub issues to help, or to let the maintainers know about a new translation.
Table A.13: Translations (repositories on github.com unless a full host is given)
| Language | Repository |
|---|---|
| Portuguese (Brazil) | rust-br/rust-book-pt-br |
| Portuguese (Portugal) | nunojesus/rust-book-pt-pt |
| Simplified Chinese | KaiserY/trpl-zh-cn; gnu4cn/rust-lang-Zh_CN |
| Traditional Chinese | rust-tw/book-tw |
| Ukrainian | rust-lang-ua.github.io/rustbook_ukrainian |
| Spanish | thecodix/book; alternate: ManRR/rust-book-es; RustLangES/rust-book-es |
| Russian | rust-lang-ru/book |
| Korean | rust-kr/doc.rust-kr.org |
The Rust Programming Language · Appendix
45
Appendix · F Translations
Translations of the book (2 of 3)
Table A.13 (continued): Translations (repositories on github.com unless a full host is given)
| Language | Repository |
|---|---|
| Japanese | rust-lang-ja/book-ja |
| French | Jimskapt/rust-book-fr |
| Polish | paytchoo/book-pl |
| Cebuano | agentzero1/book |
| Tagalog | josephace135/book |
| Esperanto | psychoslave/Rust-libro |
| Greek | TChatzigiannakis/rust-book-greek |
| Swedish | sebras/book |
| Farsi; Persian (FA) | RustFarsi/book; persian-rust/book |
The Rust Programming Language · Appendix
46
Appendix · F Translations
Translations of the book (3 of 3)
Table A.13 (continued): Translations (repositories on github.com unless a full host is given)
| Language | Repository |
|---|---|
| German | rust-lang-de/rustbook-de |
| Hindi | venkatarun95/rust-book-hindi |
| Thai | rust-lang-th/book-th |
| Danish | DanKHansen/book-dk |
| Uzbek | rust-lang-uz/book |
| Vietnamese | tuanemdev/rust-book-vn |
| Italian | nixxo.github.io/rust-lang-book-it |
| Bengali | IsmailHosenIsmailJames/rust-book-bn |
Remark. The book lists each language under its own name (for example Deutsch, Español, Français); this deck gives English names. The list is open: new translations are announced through the Translations label on github.com/rust-lang/book issues.
The Rust Programming Language · Appendix
47
Appendix · G How Rust is Made and Nightly Rust
Stability without stagnation
This appendix is about how Rust is made and how that affects you as a Rust developer.
As a language, Rust cares a lot about the stability of your code. Rust should be a rock-solid foundation you can build on, and if things were constantly changing, that would be impossible.
At the same time, if the Rust team can’t experiment with new features, they may not find out important flaws until after their release, when things can no longer be changed.
Definition A.16 (Stability without stagnation). Rust’s solution to this tension. Its guiding principle: you should never have to fear upgrading to a new version of stable Rust. Each upgrade should be painless, but should also bring you new features, fewer bugs, and faster compile times.
The Rust Programming Language · Appendix
48
Appendix · G How Rust is Made and Nightly Rust
Choo, choo! Release channels and riding the trains
Rust development operates on a train schedule: all development is done in the main branch of the Rust repository, and releases follow a software release train model, which has been used by Cisco IOS and other software projects.
Definition A.17 (Release channel). One of the three streams in which Rust is released: Nightly, Beta, and Stable. Most Rust developers primarily use the stable channel, but those who want to try out experimental new features may use nightly or beta.
An example of how development and release work: assume the Rust team is working on the release of Rust 1.5. (That release happened in December 2015, but it gives realistic version numbers.) A new feature is added to Rust: a new commit lands on the main branch. Each night, a new nightly version of Rust is produced. Every day is a release day, and these releases are created automatically by the release infrastructure. So as time passes, the releases look like this, once a night:
nightly: * - - * - - *
The Rust Programming Language · Appendix
49
Appendix · G How Rust is Made and Nightly Rust
The trains: beta branches off, regressions get fixed
1. Every six weeks, it’s time to prepare a new release! The beta branch of the Rust repository branches off from the main branch used by nightly. Now there are two releases:
nightly: * - - * - - *
|
beta: *
2. Most Rust users do not use beta releases actively, but test against beta in their CI system to help Rust discover possible regressions. Meanwhile, there’s still a nightly release every night:
nightly: * - - * - - * - - * - - *
|
beta: *
3. Say a regression is found. Good thing there was time to test the beta release before the regression snuck into a stable release! The fix is applied to the main branch, so nightly is fixed; then the fix is backported to the beta branch, and a new beta release is produced:
nightly: * - - * - - * - - * - - * - - *
|
beta: * - - - - - - - - *
The Rust Programming Language · Appendix
50
Appendix · G How Rust is Made and Nightly Rust
The trains: stable ships, the next beta departs
4. Six weeks after the first beta was created, it’s time for a stable release! The stable branch is produced from the beta branch:
nightly: * - - * - - * - - * - - * - - * - * - *
|
beta: * - - - - - - - - *
|
stable: *
5. Hooray! Rust 1.5 is done! But because the six weeks have gone by, a new beta of the next version of Rust, 1.6, is needed too. So after stable branches off of beta, the next version of beta branches off of nightly again:
nightly: * - - * - - * - - * - - * - - * - * - *
| |
beta: * - - - - - - - - * *
|
stable: *
The Rust Programming Language · Appendix
51
Appendix · G How Rust is Made and Nightly Rust
Why the train model works
Definition A.18 (Train model). The release model in which 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.
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 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 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.
The Rust Programming Language · Appendix
52
Appendix · G How Rust is Made and Nightly Rust
Maintenance time and unstable features
Maintenance time
The Rust project supports the most recent stable version. When a new stable version is released, the old version reaches its end of life (EOL). This means each version is supported for six weeks.
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.
Definition A.19 (Feature flag). A flag behind which a feature under active development lands on the main branch — and therefore in nightly. To try out the work-in-progress feature, you must be using a nightly release of Rust and annotate your source code with the appropriate flag to opt in.
The Rust Programming Language · Appendix
53
Appendix · G How Rust is Made and Nightly Rust
Unstable features stay on nightly
If you’re using a beta or stable release of Rust, you can’t use any feature flags. This is the key that allows practical use of new features before they are declared 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.
Example A.20. Opting in to an unstable feature is a crate-level attribute naming the flag; it compiles only on a nightly toolchain, and beta or stable reject it.
#![feature(never_type)] // at the top of src/main.rs or src/lib.rs
The book only contains information about stable features, as in-progress features are still changing, and surely they’ll be different between when the book was written and when they get enabled in stable builds. You can find documentation for nightly-only features online.
The Rust Programming Language · Appendix
54
Appendix · G How Rust is Made and Nightly Rust
Rustup and the role of Rust nightly
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:
$ rustup toolchain install nightly
Definition A.21 (Toolchain). A release of Rust together with its associated components, as installed and managed by rustup.
You can see all of the toolchains you have installed with rustup as well. Here’s an example on one of the authors’ Windows computers:
> rustup toolchain list
stable-x86_64-pc-windows-msvc (default)
beta-x86_64-pc-windows-msvc
nightly-x86_64-pc-windows-msvc
The Rust Programming Language · Appendix
55
Appendix · G How Rust is Made and Nightly Rust
Using nightly for one project: rustup override
As the list shows, the stable toolchain is the default. Most Rust users use stable 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, 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:
$ cd ~/projects/needs-nightly
$ rustup override set nightly
Now, every time you call rustc or cargo inside ~/projects/needs-nightly, rustup makes 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 Rust Programming Language · Appendix
56
Appendix · G How Rust is Made and Nightly Rust
The RFC process and teams
So how do you learn about these new features? Rust’s development model follows a Request For Comments (RFC) process.
Definition A.22 (RFC). A written proposal for an improvement in Rust. Anyone can write RFCs to improve Rust.
The proposals are reviewed and discussed by the Rust team, which is comprised of many topic subteams. There’s a full list of the teams on Rust’s website (rust-lang.org/governance), including 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.
The Rust Programming Language · Appendix
57
Appendix · G How Rust is Made and Nightly Rust
From accepted RFC to stable feature
Once a team reaches consensus to accept a feature, it travels the rest of the way like this:
- 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 main branch behind a feature gate, as discussed in “Unstable features”.
- After some time, once Rust developers who use nightly releases have been able to try out the new feature, team members discuss the feature and how it’s worked out on nightly, and decide whether it should make it into stable Rust.
- 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.
The Rust Programming Language · Appendix
58
Appendix · Summary
Appendix summary
The appendices are reference material to come back to:
- A — keywords in use and reserved; r# raw identifiers let you use any keyword as a name.
- B — every operator (with its overloading trait) and every non-operator symbol.
- C — the derivable traits: Debug, PartialEq/Eq, PartialOrd/Ord, Clone/Copy, Hash, Default.
- D — cargo fmt, cargo fix, cargo clippy, and rust-analyzer for IDEs.
- E — editions (2015, 2018, 2021, 2024) are opt-in via Cargo.toml and interoperate freely.
- F — community translations of the book in many languages.
- G — nightly, beta and stable ride six-week trains; unstable features stay behind feature flags on nightly; RFCs drive new features.
Remark. This is the end of the book. From here, keep the standard library documentation (rustup doc) and The Rust Edition Guide close at hand, and follow new features as they ride the trains to stable.
The Rust Programming Language · Appendix
59