| <!-- 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 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’ll discuss in “Raw Identifiers” on page XX). |
| *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` |
| * `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 |
| and 2021 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 2021 edition code. 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`, `|…| -> type` | Function and closure return type | | |
| | `. | `expr.ident` | Member access | | |
| | `..` | `..`, `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` | |
| | `| | `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 | | |
| |
| ## 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 | |
| | `...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 | |
| | `|…| expr | 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 capture | |
| | `$(…)…` | 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 symbols that appear in the context of using tuples. |
| |
| Table B-8: Tuples |
| |
| | 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 | |
| | `expr.0`, `expr.1`, and so on | Tuple indexing | |
| |
| 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 “Macros” on page XX. |
| |
| ## 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 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 not-a-number (`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 “Variables and Data Interacting with Clone” on page XX 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 “Stack-Only Data: Copy” on page |
| XX 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 “Creating Instances from Other Instances with Struct |
| Update Syntax” on page XX. 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 |
| analagous 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 do_something() {} |
| |
| fn main() { |
| for i in 0..100 { |
| do_something(); |
| } |
| } |
| ``` |
| |
| Here, we’re calling the `do_something` function 100 times, but we never use the |
| variable `i` in the body of the `for` loop. Rust warns us about that: |
| |
| ``` |
| $ cargo build |
| Compiling myprogram v0.1.0 (file:///projects/myprogram) |
| warning: unused variable: `i` |
| --> src/main.rs:4:9 |
| | |
| 4 | for i in 0..100 { |
| | ^ help: consider using `_i` instead |
| | |
| = note: #[warn(unused_variables)] on by default |
| |
| Finished dev [unoptimized + debuginfo] target(s) in 0.50s |
| ``` |
| |
| The warning suggests that we use `_i` as a name instead: the underscore |
| indicates that we intend for this variable to be unused. 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 do_something() {} |
| |
| fn main() { |
| for _i in 0..100 { |
| do_something(); |
| } |
| } |
| ``` |
| |
| The `for` loop variable is now named `_i`, 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 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: |
| |
| Filename: 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: |
| |
| Filename: 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 at |
| *https://rust-analyzer.github.io* 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 two or three years, 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, three Rust editions are available: Rust 2015, Rust |
| 2018, and Rust 2021. This book is written using Rust 2021 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, *The* *Edition Guide* at |
| *https://doc.rust-lang.org/stable/edition-guide* is a complete book about |
| editions that enumerates the differences between editions and explains how to |
| automatically upgrade your code to a new edition via `cargo fix`. |
| |