| <!-- DO NOT EDIT THIS FILE. |
| |
| This file is periodically generated from the content in the `/src/` |
| directory, so all fixes need to be made in `/src/`. |
| --> |
| |
| [TOC] |
| |
| # Appendix |
| |
| The following sections contain reference material you may find useful in your |
| Rust journey. |
| |
| ## Appendix A: Keywords |
| |
| 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, as we discuss in the “Raw |
| Identifiers” section). *Identifiers* are names |
| of functions, variables, parameters, struct fields, modules, crates, constants, |
| macros, static values, attributes, types, traits, or lifetimes. |
| |
| ### Keywords Currently in Use |
| |
| The following is a list of keywords currently in use, with their functionality |
| described. |
| |
| * **`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. |
| * **`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. |
| * **`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. |
| * **`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. |
| |
| ### Keywords Reserved for Future Use |
| |
| The following keywords do not yet have any functionality but are reserved by |
| Rust for potential future use: |
| |
| * `abstract` |
| * `become` |
| * `box` |
| * `do` |
| * `final` |
| * `gen` |
| * `macro` |
| * `override` |
| * `priv` |
| * `try` |
| * `typeof` |
| * `unsized` |
| * `virtual` |
| * `yield` |
| |
| ### Raw Identifiers |
| |
| *Raw identifiers* are the syntax that lets you use keywords where they wouldn’t |
| normally be allowed. You use a raw identifier by prefixing a keyword with `r#`. |
| |
| For example, `match` is a keyword. If you try to compile the following function |
| that uses `match` as its name: |
| |
| Filename: 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 to use the raw |
| identifier syntax, like this: |
| |
| Filename: src/main.rs |
| |
| ``` |
| fn r#match(needle: &str, haystack: &str) -> bool { |
| haystack.contains(needle) |
| } |
| |
| fn main() { |
| assert!(r#match("foo", "foobar")); |
| } |
| ``` |
| |
| This code will compile without any errors. Note the `r#` prefix on the function |
| name in its definition as well as where the function is called in `main`. |
| |
| Raw identifiers allow you to use any word you choose as an identifier, even if |
| that word happens to be a reserved keyword. This gives us more freedom to choose |
| identifier names, as well as lets us integrate with programs written in a |
| language where these words aren’t keywords. In addition, raw identifiers allow |
| you to use libraries written in a different Rust edition than your crate uses. |
| For example, `try` isn’t a keyword in the 2015 edition but is in the 2018, 2021, |
| and 2024 editions. If you depend on a library that is written using the 2015 |
| edition and has a `try` function, you’ll need to use the raw identifier syntax, |
| `r#try` in this case, to call that function from your code on later editions. |
| See Appendix E for more information on editions. |
| |
| ## Appendix B: Operators and Symbols |
| |
| 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 B-1 contains the operators in Rust, an example of how the 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. |
| |
| Table B-1: Operators |
| |
| |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|| |
| |`*`|`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`| |
| |`-=`|`var -= expr`|Arithmetic subtraction and assignment|`SubAssign`| |
| |`->`|`fn(...) -> type`, <code>\|…\| -> type</code>|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|| |
| |`...`|`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`| |
| |`<<=`|`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`| |
| |`>>=`|`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`| |
| |<code>\|</code>|<code>pat \| pat</code>|Pattern alternatives|| |
| |<code>\|</code>|<code>expr \| expr</code>|Bitwise OR|`BitOr`| |
| |<code>\|=</code>|<code>var \|= expr</code>|Bitwise OR and assignment|`BitOrAssign`| |
| |<code>\|\|</code>|<code>expr \|\| expr</code>|Short-circuiting logical OR|| |
| |`?`|`expr?`|Error propagation|| |
| |
| ### Non-operator Symbols |
| |
| 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 B-2 shows symbols that appear on their own and are valid in a variety of |
| locations. |
| |
| Table B-2: Stand-alone Syntax |
| |
| |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| |
| |`'...'`|Character literal| |
| |`b'...'`|ASCII byte literal| |
| |<code>\|…\| expr</code>|Closure| |
| |`!`|Always-empty bottom type for diverging functions| |
| |`_`|“Ignored” pattern binding; also used to make integer literals readable| |
| |
| Table B-3 shows symbols that appear in the context of a path through the module |
| hierarchy to an item. |
| |
| Table B-3: Path-Related Syntax |
| |
| |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| |
| |
| Table B-4 shows symbols that appear in the context of using generic type |
| parameters. |
| |
| Table B-4: Generics |
| |
| |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>`)| |
| |
| Table B-5 shows symbols that appear in the context of constraining generic type |
| parameters with trait bounds. |
| |
| Table B-5: Trait Bound Constraints |
| |
| |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| |
| |
| Table B-6 shows symbols that appear in the context of calling or defining |
| macros and specifying attributes on an item. |
| |
| Table B-6: Macros and Attributes |
| |
| |Symbol|Explanation| |
| |------|-----------| |
| |`#[meta]`|Outer attribute| |
| |`#![meta]`|Inner attribute| |
| |`$ident`|Macro substitution| |
| |`$ident:kind`|Macro metavariable| |
| |`$(...)...`|Macro repetition| |
| |`ident!(...)`, `ident!{...}`, `ident![...]`|Macro invocation| |
| |
| Table B-7 shows symbols that create comments. |
| |
| Table B-7: Comments |
| |
| |Symbol|Explanation| |
| |------|-----------| |
| |`//`|Line comment| |
| |`//!`|Inner line doc comment| |
| |`///`|Outer line doc comment| |
| |`/*...*/`|Block comment| |
| |`/*!...*/`|Inner block doc comment| |
| |`/**...*/`|Outer block doc comment| |
| |
| Table B-8 shows the contexts in which parentheses are used. |
| |
| Table B-8: Parentheses |
| |
| |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 `struct`s and tuple `enum` variants| |
| |
| Table B-9 shows the contexts in which curly brackets are used. |
| |
| Table B-9: Curly Brackets |
| |
| |Context|Explanation| |
| |-------|-----------| |
| |`{...}`|Block expression| |
| |`Type {...}`|Struct literal| |
| |
| Table B-10 shows the contexts in which square brackets are used. |
| |
| Table B-10: Square Brackets |
| |
| |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”| |
| |
| ## Appendix C: Derivable Traits |
| |
| In various places in the book, we’ve discussed the `derive` attribute, which |
| you can apply to a struct or enum definition. The `derive` attribute generates |
| code that will implement a trait with its own default implementation on the |
| type you’ve annotated with the `derive` syntax. |
| |
| In this appendix, we provide 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 the `derive` attribute, |
| consult the standard library documentation |
| for each trait for details on how to manually implement them. |
| |
| The traits listed here are the only ones defined by the standard library that |
| can be implemented on your types using `derive`. Other traits defined in the |
| standard library 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. |
| |
| An example of a trait that can’t be derived is `Display`, which handles |
| formatting for end users. 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 provided 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. Implementing `derive` |
| involves using a procedural macro, which is covered in the “Custom `derive` |
| Macros” section in Chapter 20. |
| |
| ### Debug for Programmer Output |
| |
| The `Debug` trait enables debug formatting in format strings, which you |
| indicate by adding `:?` within `{}` placeholders. |
| |
| The `Debug` trait allows you to 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. |
| |
| The `Debug` trait is required, for example, in the use of the `assert_eq!` |
| macro. This macro prints the values of instances given as arguments if the |
| equality assertion fails so that programmers can see why the two instances |
| weren’t equal. |
| |
| ### PartialEq and Eq for Equality Comparisons |
| |
| The `PartialEq` trait allows you to compare instances of a type to check for |
| equality and enables use of the `==` and `!=` operators. |
| |
| Deriving `PartialEq` implements the `eq` method. When `PartialEq` is derived on |
| structs, two instances are equal only if *all* fields are equal, and the |
| instances are not equal if *any* fields are not equal. When derived on enums, |
| each variant is equal to itself and not equal to the other variants. |
| |
| The `PartialEq` trait is required, for example, with the use of the |
| `assert_eq!` macro, which needs to be able to compare two instances of a type |
| for equality. |
| |
| The `Eq` trait has no methods. Its purpose is to signal that for every value of |
| the annotated type, the value is equal to itself. The `Eq` trait can only be |
| applied to types that also implement `PartialEq`, although not all types that |
| implement `PartialEq` can implement `Eq`. One example of this is floating-point |
| number types: The implementation of floating-point numbers states that two |
| instances of the not-a-number (`NaN`) value are not equal to each other. |
| |
| An example of when `Eq` is required is for keys in a `HashMap<K, V>` so that |
| the `HashMap<K, V>` can tell whether two keys are the same. |
| |
| ### PartialOrd and Ord for Ordering Comparisons |
| |
| The `PartialOrd` trait allows you to compare instances of a type for sorting |
| purposes. A type that implements `PartialOrd` can be used with the `<`, `>`, |
| `<=`, and `>=` operators. You can only apply the `PartialOrd` trait to types |
| that also implement `PartialEq`. |
| |
| Deriving `PartialOrd` implements the `partial_cmp` method, which returns an |
| `Option<Ordering>` that will be `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 that type can be compared, is the `NaN` floating point value. |
| Calling `partial_cmp` with any floating-point number and the `NaN` |
| floating-point value will return `None`. |
| |
| When derived on structs, `PartialOrd` compares two instances by comparing the |
| value in each field in the order in which the fields appear in the struct |
| definition. When derived on enums, variants of the enum declared earlier in the |
| enum definition are considered less than the variants listed later. |
| |
| The `PartialOrd` trait is required, for example, for the `gen_range` method |
| from the `rand` crate that generates a random value in the range specified by a |
| range expression. |
| |
| The `Ord` trait allows you to know that for any two values of the annotated |
| type, a valid ordering will exist. The `Ord` trait implements the `cmp` method, |
| which returns an `Ordering` rather than an `Option<Ordering>` because a valid |
| ordering will always be possible. You can only apply the `Ord` trait 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 |
| implementation for `partial_cmp` does with `PartialOrd`. |
| |
| An example of when `Ord` is required is when storing values in a `BTreeSet<T>`, |
| a data structure that stores data based on the sort order of the values. |
| |
| ### Clone and Copy for Duplicating Values |
| |
| The `Clone` trait allows you to explicitly create a deep copy of a value, and |
| the duplication process might involve running arbitrary code and copying heap |
| data. See the “Variables and Data Interacting with |
| Clone” section in |
| Chapter 4 for more information on `Clone`. |
| |
| 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`. |
| |
| An example of when `Clone` is required is when 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` will need to own its instances, so `to_vec` calls |
| `clone` on each item. Thus, the type stored in the slice must implement `Clone`. |
| |
| The `Copy` trait allows you to duplicate a value by only copying bits stored on |
| the stack; no arbitrary code is necessary. See the “Stack-Only Data: |
| Copy” section in Chapter 4 for more |
| information on `Copy`. |
| |
| The `Copy` trait 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 type that implements |
| `Copy` has a trivial implementation of `Clone` that performs the same task as |
| `Copy`. |
| |
| The `Copy` trait is rarely required; types that implement `Copy` have |
| optimizations available, meaning you don’t have to call `clone`, which makes |
| the code more concise. |
| |
| Everything possible with `Copy` you can also accomplish with `Clone`, but the |
| code might be slower or have to use `clone` in places. |
| |
| ### Hash for Mapping a Value to a Value of Fixed Size |
| |
| The `Hash` trait allows you to 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 of the `hash` |
| method 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`. |
| |
| An example of when `Hash` is required is in storing keys in a `HashMap<K, V>` |
| to store data efficiently. |
| |
| ### Default for Default Values |
| |
| The `Default` trait allows you to create a default value for a type. Deriving |
| `Default` implements the `default` function. The derived implementation of the |
| `default` function calls the `default` function on each part of the type, |
| meaning all fields or values in the type must also implement `Default` to |
| derive `Default`. |
| |
| The `Default::default` function is commonly used in combination with the struct |
| update syntax discussed in the “Creating Instances from Other Instances with |
| Struct Update |
| Syntax” section in Chapter 5. You can customize a few fields of a struct and |
| then set and use a default value for the rest of the fields by using |
| `..Default::default()`. |
| |
| The `Default` trait is required when you use the method `unwrap_or_default` on |
| `Option<T>` instances, for example. If the `Option<T>` is `None`, the method |
| `unwrap_or_default` will return the result of `Default::default` for the type |
| `T` stored in the `Option<T>`. |
| |
| ## Appendix D: Useful Development Tools |
| |
| In this appendix, we talk about some useful development tools that the Rust |
| project provides. We’ll look at automatic formatting, quick ways to apply |
| warning fixes, a linter, and integrating with IDEs. |
| |
| ### Automatic Formatting with rustfmt |
| |
| 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` on your system. These two commands are |
| analogous to `rustc` and `cargo` in that `rustfmt` allows finer grained control |
| and `cargo-fmt` understands conventions of a project that uses Cargo. To format |
| any Cargo project, enter the following: |
| |
| ``` |
| $ cargo fmt |
| ``` |
| |
| Running this command reformats all the Rust code in the current crate. This |
| should only change the code style, not the code semantics. For more information |
| on `rustfmt`, see its documentation at *https://github.com/rust-lang/rustfmt*. |
| |
| ### Fix Your Code with rustfix |
| |
| 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. You’ve probably seen compiler warnings before. For |
| example, consider this code: |
| |
| Filename: src/main.rs |
| |
| ``` |
| fn main() { |
| let mut x = 42; |
| println!("{x}"); |
| } |
| ``` |
| |
| Here, we’re defining the variable `x` as mutable, but we never actually mutate |
| it. Rust warns us about that: |
| |
| ``` |
| $ 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 warning suggests that we remove the `mut` keyword. We can automatically |
| apply that suggestion using the `rustfix` tool by running the command `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 |
| ``` |
| |
| When we look at *src/main.rs* again, we’ll see that `cargo fix` has changed the |
| code: |
| |
| Filename: src/main.rs |
| |
| ``` |
| fn main() { |
| let x = 42; |
| println!("{x}"); |
| } |
| ``` |
| |
| The variable `x` is now immutable, and the warning no longer appears. |
| |
| You can also use the `cargo fix` command to transition your code between |
| different Rust editions. Editions are covered in Appendix E. |
| |
| ### More Lints with Clippy |
| |
| The Clippy tool is a collection of lints to analyze your code so that 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 the following: |
| |
| ``` |
| $ cargo clippy |
| ``` |
| |
| For example, say you write a program that uses an approximation of a |
| mathematical constant, such as pi, as this program does: |
| |
| src/main.rs |
| |
| ``` |
| fn main() { |
| let x = 3.1415; |
| let r = 8.0; |
| println!("the area of the circle is {}", x * r * r); |
| } |
| ``` |
| |
| |
| |
| 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 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); |
| } |
| ``` |
| |
| |
| |
| For more information on Clippy, see its documentation at *https://github.com/rust-lang/rust-clippy*. |
| |
| ### IDE Integration Using rust-analyzer |
| |
| To help with IDE integration, the Rust community recommends using |
| `rust-analyzer`. This tool is a set of |
| compiler-centric utilities that speak Language Server Protocol, which is a specification for IDEs and programming languages to |
| communicate with each other. Different clients can use `rust-analyzer`, such as |
| the Rust analyzer plug-in for Visual Studio Code at *https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer*. |
| |
| Visit the `rust-analyzer` project’s home page |
| for installation instructions, then install the language server support in your |
| particular IDE. Your IDE will gain capabilities such as autocompletion, jump to |
| definition, and inline errors. |
| |
| ## Appendix E: Editions |
| |
| In Chapter 1, you saw that `cargo new` adds a bit of metadata to your |
| *Cargo.toml* file about an edition. This appendix talks about what that means! |
| |
| The Rust language and compiler have a six-week release cycle, meaning 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!” |
| |
| Every three years or so, the Rust team produces a new Rust *edition*. Each |
| edition 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. |
| |
| 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, a new edition signals that some major advancements have |
| landed, which might make Rust worth another look. |
| * For those developing Rust, a new edition 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. This 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 including 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. |
| |
| 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. Therefore, 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, where 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. 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. |
| |
| For more details, see *The Rust Edition Guide* at *https://doc.rust-lang.org/stable/edition-guide*. This is a |
| complete book that enumerates the differences between editions and explains how |
| to automatically upgrade your code to a new edition via `cargo fix`. |
| |
| ## Appendix F: Translations of the Book |
| |
| For resources in languages other than English. Most are still in progress; see |
| the Translations label at *https://github.com/rust-lang/book/issues?q=is%3Aopen+is%3Aissue+label%3ATranslations* to help or let us know about a new translation! |
| |
| * Português at *https://github.com/rust-br/rust-book-pt-br* (BR) |
| * Português at *https://github.com/nunojesus/rust-book-pt-pt* (PT) |
| * 简体中文: KaiserY/trpl-zh-cn at *https://github.com/KaiserY/trpl-zh-cn*, gnu4cn/rust-lang-Zh_CN at *https://github.com/gnu4cn/rust-lang-Zh_CN* |
| * 正體中文 at *https://github.com/rust-tw/book-tw* |
| * Українська at *https://rust-lang-ua.github.io/rustbook_ukrainian* |
| * Español at *https://github.com/thecodix/book*, alternate at *https://github.com/ManRR/rust-book-es*, Español por RustLangES at *https://github.com/RustLangES/rust-book-es* |
| * Русский at *https://github.com/rust-lang-ru/book* |
| * 한국어 at *https://github.com/rust-kr/doc.rust-kr.org* |
| * 日本語 at *https://github.com/rust-lang-ja/book-ja* |
| * Français at *https://github.com/Jimskapt/rust-book-fr* |
| * Polski at *https://github.com/paytchoo/book-pl* |
| * Cebuano at *https://github.com/agentzero1/book* |
| * Tagalog at *https://github.com/josephace135/book* |
| * Esperanto at *https://github.com/psychoslave/Rust-libro* |
| * ελληνική at *https://github.com/TChatzigiannakis/rust-book-greek* |
| * Svenska at *https://github.com/sebras/book* |
| * Farsi at *https://github.com/RustFarsi/book*, Persian (FA) at *https://github.com/persian-rust/book* |
| * Deutsch at *https://github.com/rust-lang-de/rustbook-de* |
| * हिंदी at *https://github.com/venkatarun95/rust-book-hindi* |
| * ไทย at *https://github.com/rust-lang-th/book-th* |
| * Danske at *https://github.com/DanKHansen/book-dk* |
| * O’zbek at *https://github.com/rust-lang-uz/book* |
| * Tiếng Việt at *https://github.com/tuanemdev/rust-book-vn* |
| * Italiano at *https://nixxo.github.io/rust-lang-book-it/* |
| * বাংলা at *https://github.com/IsmailHosenIsmailJames/rust-book-bn* |
| |
| ## Appendix G - How Rust is Made and “Nightly Rust” |
| |
| This appendix is about how Rust is made and how that affects you as a Rust |
| developer. |
| |
| ### 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 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”, |
| and our guiding principle is this: 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. |
| |
| ### Choo, Choo! Release Channels and Riding the Trains |
| |
| Rust development operates on a *train schedule*. That is, all development is |
| done in the main 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 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 main |
| 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: |
| |
| ``` |
| nightly: * - - * - - * |
| ``` |
| |
| 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: * |
| ``` |
| |
| 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: |
| |
| ``` |
| nightly: * - - * - - * - - * - - * |
| | |
| beta: * |
| ``` |
| |
| 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 the main branch, so that nightly is fixed, and then the fix is backported to |
| the `beta` branch, and a new release of beta is produced: |
| |
| ``` |
| nightly: * - - * - - * - - * - - * - - * |
| | |
| beta: * - - - - - - - - * |
| ``` |
| |
| 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: * |
| ``` |
| |
| 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: |
| |
| ``` |
| nightly: * - - * - - * - - * - - * - - * - * - * |
| | | |
| beta: * - - - - - - - - * * |
| | |
| stable: * |
| ``` |
| |
| 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. |
| |
| 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 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. |
| |
| ### 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. If a new feature is under active development, it lands on the |
| main branch, 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. |
| |
| 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 get enabled in stable builds. You can find |
| documentation for nightly-only features online. |
| |
| ### 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 |
| ``` |
| |
| 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’ Windows computer: |
| |
| ``` |
| > rustup toolchain list |
| stable-x86_64-pc-windows-msvc (default) |
| beta-x86_64-pc-windows-msvc |
| 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. 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` 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 of |
| *~/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 |
| 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 topic subteams. There’s |
| a full list of the teams on Rust’s website at *https://www.rust-lang.org/governance*, 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 main branch behind a feature gate, as we discussed in |
| the “Unstable Features” section. |
| |
| 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. |