From 324190ec85503decde4f3fd5ddd996d0da7a9849 Mon Sep 17 00:00:00 2001 From: Michael Frank <55284511+frank-at-adacore@users.noreply.github.com> Date: Thu, 13 Feb 2025 12:10:58 -0500 Subject: [PATCH 1/4] Convert all inline literals to the "rust" role --- .../020_hello_world/01_what_is_rust.rst | 2 +- .../020_hello_world/02_benefits.rst | 2 +- .../020_hello_world/03_playground.rst | 2 +- .../030_types_and_values/01_hello_world.rst | 8 +-- .../030_types_and_values/02_variables.rst | 14 ++--- .../030_types_and_values/03_values.rst | 32 +++++------ .../030_types_and_values/04_arithmetic.rst | 8 +-- .../030_types_and_values/05_inference.rst | 8 +-- .../030_types_and_values/06_exercise.rst | 6 +-- .../040_control_flow_basics/01_if.rst | 26 ++++----- .../040_control_flow_basics/02_match.rst | 38 ++++++------- .../040_control_flow_basics/03_loops.rst | 8 +-- .../04_break_continue.rst | 14 ++--- .../05_blocks_and_scopes.rst | 10 ++-- .../040_control_flow_basics/06_functions.rst | 12 ++--- .../040_control_flow_basics/07_macros.rst | 14 ++--- .../040_control_flow_basics/08_exercise.rst | 4 +- .../050_tuples_and_arrays/01_arrays.rst | 16 +++--- .../050_tuples_and_arrays/02_tuples.rst | 8 +-- .../050_tuples_and_arrays/03_iteration.rst | 12 ++--- .../04_destructuring.rst | 8 +-- .../050_tuples_and_arrays/05_exercise.rst | 4 +- .../060_references/01_shared.rst | 18 +++---- .../060_references/02_exclusive.rst | 12 ++--- .../060_references/03_slices.rst | 20 +++---- .../060_references/04_strings.rst | 48 ++++++++--------- .../060_references/05_dangling.rst | 8 +-- .../060_references/06_exercise.rst | 4 +- .../01_named_structs.rst | 6 +-- .../02_tuple_structs.rst | 10 ++-- .../070_user_defined_types/03_enums.rst | 24 ++++----- .../070_user_defined_types/04_aliases.rst | 6 +-- .../070_user_defined_types/05_const.rst | 14 ++--- .../070_user_defined_types/06_static.rst | 24 ++++----- .../070_user_defined_types/07_exercise.rst | 8 +-- .../080_pattern_matching/01_match.rst | 36 ++++++------- .../02_destructuring_structs.rst | 10 ++-- .../03_destructuring_enums.rst | 14 ++--- .../04_let_control_flow.rst | 46 ++++++++-------- .../080_pattern_matching/05_exercise.rst | 18 +++---- .../090_methods_and_traits/01_methods.rst | 34 ++++++------ .../090_methods_and_traits/02_traits.rst | 2 +- .../090_methods_and_traits/03_deriving.rst | 6 +-- .../090_methods_and_traits/04_exercise.rst | 12 ++--- .../100_generics/01_generic_functions.rst | 12 ++--- .../100_generics/02_generic_data.rst | 16 +++--- .../100_generics/03_generic_traits.rst | 8 +-- .../100_generics/04_trait_bounds.rst | 18 +++---- .../100_generics/05_impl_trait.rst | 24 ++++----- .../100_generics/06_dyn_trait.rst | 32 +++++------ .../100_generics/07_exercise.rst | 8 +-- .../110_std_types/01_std.rst | 18 +++---- .../110_std_types/02_docs.rst | 10 ++-- .../110_std_types/03_option.rst | 26 ++++----- .../110_std_types/04_result.rst | 16 +++--- .../110_std_types/05_string.rst | 42 +++++++-------- .../110_std_types/06_vec.rst | 30 +++++------ .../110_std_types/07_hashmap.rst | 20 +++---- .../110_std_types/08_exercise.rst | 10 ++-- .../120_std_traits/01_comparisons.rst | 28 +++++----- .../120_std_traits/02_operators.rst | 22 ++++---- .../120_std_traits/03_from_and_into.rst | 20 +++---- .../120_std_traits/04_casting.rst | 22 ++++---- .../120_std_traits/05_read_and_write.rst | 12 ++--- .../120_std_traits/06_default.rst | 18 +++---- .../120_std_traits/07_closures.rst | 36 ++++++------- .../120_std_traits/08_exercise.rst | 4 +- .../130_memory_management/01_review.rst | 10 ++-- .../130_memory_management/02_approaches.rst | 6 +-- .../130_memory_management/03_ownership.rst | 2 +- .../130_memory_management/04_move.rst | 54 +++++++++---------- .../130_memory_management/05_clone.rst | 14 ++--- .../130_memory_management/06_copy_types.rst | 26 ++++----- .../130_memory_management/07_drop.rst | 28 +++++----- .../130_memory_management/08_exercise.rst | 2 +- .../140_smart_pointers/01_box.rst | 36 ++++++------- .../140_smart_pointers/02_rc.rst | 22 ++++---- .../140_smart_pointers/03_trait_objects.rst | 24 ++++----- .../140_smart_pointers/04_exercise.rst | 2 +- .../150_borrowing/01_shared.rst | 10 ++-- .../150_borrowing/02_borrowck.rst | 16 +++--- .../150_borrowing/03_examples.rst | 4 +- .../160_lifetimes/01_lifetime_annotations.rst | 22 ++++---- .../160_lifetimes/02_lifetime_elision.rst | 10 ++-- .../160_lifetimes/03_struct_lifetimes.rst | 12 ++--- .../160_lifetimes/04_exercise.rst | 34 ++++++------ .../170_iterators/01_motivation.rst | 14 ++--- .../170_iterators/02_iterator.rst | 22 ++++---- .../170_iterators/03_helpers.rst | 16 +++--- .../170_iterators/04_collect.rst | 34 ++++++------ .../170_iterators/05_intoiterator.rst | 44 +++++++-------- .../170_iterators/06_exercise.rst | 2 +- .../180_modules/01_modules.rst | 8 +-- .../180_modules/02_filesystem.rst | 28 +++++----- .../180_modules/03_visibility.rst | 12 ++--- .../180_modules/04_encapsulation.rst | 14 ++--- .../180_modules/05_paths.rst | 26 ++++----- .../180_modules/06_exercise.rst | 10 ++-- .../190_testing/01_unit_tests.rst | 10 ++-- .../190_testing/02_other.rst | 14 ++--- .../190_testing/03_lints.rst | 8 +-- .../190_testing/04_exercise.rst | 8 +-- .../200_error_handling/01_panics.rst | 16 +++--- .../200_error_handling/02_result.rst | 20 +++---- .../200_error_handling/03_try.rst | 26 ++++----- .../200_error_handling/04_try_conversions.rst | 38 ++++++------- .../200_error_handling/05_error.rst | 12 ++--- .../200_error_handling/06_thiserror.rst | 18 +++---- .../200_error_handling/07_anyhow.rst | 28 +++++----- .../200_error_handling/08_exercise.rst | 8 +-- .../210_unsafe_rust/01_unsafe.rst | 6 +-- .../210_unsafe_rust/02_dereferencing.rst | 10 ++-- .../210_unsafe_rust/03_mutable_static.rst | 8 +-- .../210_unsafe_rust/04_unions.rst | 2 +- .../210_unsafe_rust/05_unsafe_functions.rst | 20 +++---- .../210_unsafe_rust/06_unsafe_traits.rst | 12 ++--- .../210_unsafe_rust/07_exercise.rst | 22 ++++---- 117 files changed, 969 insertions(+), 969 deletions(-) diff --git a/courses/comprehensive_rust_training/020_hello_world/01_what_is_rust.rst b/courses/comprehensive_rust_training/020_hello_world/01_what_is_rust.rst index 152c69241..58845362a 100644 --- a/courses/comprehensive_rust_training/020_hello_world/01_what_is_rust.rst +++ b/courses/comprehensive_rust_training/020_hello_world/01_what_is_rust.rst @@ -11,7 +11,7 @@ Rust is a new programming language which had its `1.0 release in - Rust is a statically compiled language in a similar role as C++ - - ``rustc`` uses LLVM as its backend. + - :rust:`rustc` uses LLVM as its backend. - Rust supports many `platforms and architectures `__: diff --git a/courses/comprehensive_rust_training/020_hello_world/02_benefits.rst b/courses/comprehensive_rust_training/020_hello_world/02_benefits.rst index aa7f15f39..3cacd4c2a 100644 --- a/courses/comprehensive_rust_training/020_hello_world/02_benefits.rst +++ b/courses/comprehensive_rust_training/020_hello_world/02_benefits.rst @@ -14,7 +14,7 @@ Some unique selling points of Rust: - No uninitialized variables. - No double-frees. - No use-after-free. - - No ``NULL`` pointers. + - No :rust:`NULL` pointers. - No forgotten locked mutexes. - No data races between threads. - No iterator invalidation. diff --git a/courses/comprehensive_rust_training/020_hello_world/03_playground.rst b/courses/comprehensive_rust_training/020_hello_world/03_playground.rst index 7bde35bba..b4f685b1e 100644 --- a/courses/comprehensive_rust_training/020_hello_world/03_playground.rst +++ b/courses/comprehensive_rust_training/020_hello_world/03_playground.rst @@ -11,7 +11,7 @@ way to run short Rust programs, and is the basis for the examples and exercises in this course. Try running the "hello-world" program it starts with. It comes with a few handy features: -- Under "Tools", use the ``rustfmt`` option to format your code in the +- Under "Tools", use the :rust:`rustfmt` option to format your code in the "standard" way. - Rust has two main "profiles" for generating code: Debug (extra diff --git a/courses/comprehensive_rust_training/030_types_and_values/01_hello_world.rst b/courses/comprehensive_rust_training/030_types_and_values/01_hello_world.rst index 3f6f41c2f..a374a2653 100644 --- a/courses/comprehensive_rust_training/030_types_and_values/01_hello_world.rst +++ b/courses/comprehensive_rust_training/030_types_and_values/01_hello_world.rst @@ -9,7 +9,7 @@ Hello, World Let us jump into the simplest possible Rust program, a classic Hello World program: -.. code:: rust,editable +.. code:: rust fn main() { println!("Hello World!"); @@ -17,10 +17,10 @@ World program: What you see: -- Functions are introduced with ``fn``. +- Functions are introduced with :rust:`fn`. - Blocks are delimited by curly braces like in C and C++. -- The ``main`` function is the entry point of the program. -- Rust has hygienic macros, ``println!`` is an example of this. +- The :rust:`main` function is the entry point of the program. +- Rust has hygienic macros, :rust:`println!` is an example of this. - Rust strings are UTF-8 encoded and can contain any Unicode character. .. raw:: html diff --git a/courses/comprehensive_rust_training/030_types_and_values/02_variables.rst b/courses/comprehensive_rust_training/030_types_and_values/02_variables.rst index d61956bc4..c2be512fc 100644 --- a/courses/comprehensive_rust_training/030_types_and_values/02_variables.rst +++ b/courses/comprehensive_rust_training/030_types_and_values/02_variables.rst @@ -7,9 +7,9 @@ Variables ----------- Rust provides type safety via static typing. Variable bindings are made -with ``let``: +with :rust:`let`: -.. code:: rust,editable,warnunused +.. code:: rust fn main() { let x: i32 = 10; @@ -24,15 +24,15 @@ with ``let``: Details --------- -- Uncomment the ``x = 20`` to demonstrate that variables are immutable - by default. Add the ``mut`` keyword to allow changes. +- Uncomment the :rust:`x = 20` to demonstrate that variables are immutable + by default. Add the :rust:`mut` keyword to allow changes. - Warnings are enabled for this slide, such as for unused variables or - unnecessary ``mut``. These are omitted in most slides to avoid + unnecessary :rust:`mut`. These are omitted in most slides to avoid distracting warnings. Try removing the mutation but leaving the - ``mut`` keyword in place. + :rust:`mut` keyword in place. -- The ``i32`` here is the type of the variable. This must be known at +- The :rust:`i32` here is the type of the variable. This must be known at compile time, but type inference (covered later) allows the programmer to omit it in many cases. diff --git a/courses/comprehensive_rust_training/030_types_and_values/03_values.rst b/courses/comprehensive_rust_training/030_types_and_values/03_values.rst index 3104ff30f..0a4298578 100644 --- a/courses/comprehensive_rust_training/030_types_and_values/03_values.rst +++ b/courses/comprehensive_rust_training/030_types_and_values/03_values.rst @@ -12,30 +12,30 @@ each type. +---------------+-------------------------------+---------------------+ | | Types | Literals | +===============+===============================+=====================+ -| Signed | ``i8``, ``i16``, ``i32``, | ``-10``, ``0``, | -| integers | ``i64``, ``i128``, ``isize`` | ``1_000``, | -| | | ``123_i64`` | +| Signed | :rust:`i8`, :rust:`i16`, :rust:`i32`, | :rust:`-10`, :rust:`0`, | +| integers | :rust:`i64`, :rust:`i128`, :rust:`isize` | :rust:`1_000`, | +| | | :rust:`123_i64` | +---------------+-------------------------------+---------------------+ -| Unsigned | ``u8``, ``u16``, ``u32``, | ``0``, ``123``, | -| integers | ``u64``, ``u128``, ``usize`` | ``10_u16`` | +| Unsigned | :rust:`u8`, :rust:`u16`, :rust:`u32`, | :rust:`0`, :rust:`123`, | +| integers | :rust:`u64`, :rust:`u128`, :rust:`usize` | :rust:`10_u16` | +---------------+-------------------------------+---------------------+ -| Floating | ``f32``, ``f64`` | ``3.14``, | -| point numbers | | ``-10.0e20``, | -| | | ``2_f32`` | +| Floating | :rust:`f32`, :rust:`f64` | :rust:`3.14`, | +| point numbers | | :rust:`-10.0e20`, | +| | | :rust:`2_f32` | +---------------+-------------------------------+---------------------+ -| Unicode | ``char`` | ``'a'``, | +| Unicode | :rust:`char` | :rust:`'a'`, | | scalar values | | ':math:`\alpha`', | | | | ':math:`\infty`' | +---------------+-------------------------------+---------------------+ -| Booleans | ``bool`` | ``true``, ``false`` | +| Booleans | :rust:`bool` | :rust:`true`, :rust:`false` | +---------------+-------------------------------+---------------------+ The types have widths as follows: -- ``iN``, ``uN``, and ``fN`` are *N* bits wide, -- ``isize`` and ``usize`` are the width of a pointer, -- ``char`` is 32 bits wide, -- ``bool`` is 8 bits wide. +- :rust:`iN`, :rust:`uN`, and :rust:`fN` are *N* bits wide, +- :rust:`isize` and :rust:`usize` are the width of a pointer, +- :rust:`char` is 32 bits wide, +- :rust:`bool` is 8 bits wide. .. raw:: html @@ -46,8 +46,8 @@ Details There are a few syntaxes which are not shown above: - All underscores in numbers can be left out, they are for legibility - only. So ``1_000`` can be written as ``1000`` (or ``10_00``), and - ``123_i64`` can be written as ``123i64``. + only. So :rust:`1_000` can be written as :rust:`1000` (or :rust:`10_00`), and + :rust:`123_i64` can be written as :rust:`123i64`. .. raw:: html diff --git a/courses/comprehensive_rust_training/030_types_and_values/04_arithmetic.rst b/courses/comprehensive_rust_training/030_types_and_values/04_arithmetic.rst index 0aaea06f0..7ae7a0ca5 100644 --- a/courses/comprehensive_rust_training/030_types_and_values/04_arithmetic.rst +++ b/courses/comprehensive_rust_training/030_types_and_values/04_arithmetic.rst @@ -6,7 +6,7 @@ Arithmetic Arithmetic ------------ -.. code:: rust,editable +.. code:: rust fn interproduct(a: i32, b: i32, c: i32) -> i32 { return a * b + b * c + c * a; @@ -22,7 +22,7 @@ Arithmetic Details --------- -This is the first time we've seen a function other than ``main``, but +This is the first time we've seen a function other than :rust:`main`, but the meaning should be clear: it takes three integers, and returns an integer. Functions will be covered in more detail later. @@ -32,11 +32,11 @@ What about integer overflow? In C and C++ overflow of *signed* integers is actually undefined, and might do unknown things at runtime. In Rust, it's defined. -Change the ``i32``\ 's to ``i16`` to see an integer overflow, which +Change the :rust:`i32`\ 's to :rust:`i16` to see an integer overflow, which panics (checked) in a debug build and wraps in a release build. There are other options, such as overflowing, saturating, and carrying. These are accessed with method syntax, e.g., -``(a * b).saturating_add(b * c).saturating_add(c * a)``. +:rust:`(a * b).saturating_add(b * c).saturating_add(c * a)`. In fact, the compiler will detect overflow of constant expressions, which is why the example requires a separate function. diff --git a/courses/comprehensive_rust_training/030_types_and_values/05_inference.rst b/courses/comprehensive_rust_training/030_types_and_values/05_inference.rst index 01d20908c..47a1a5f5c 100644 --- a/courses/comprehensive_rust_training/030_types_and_values/05_inference.rst +++ b/courses/comprehensive_rust_training/030_types_and_values/05_inference.rst @@ -12,7 +12,7 @@ Rust will look at how the variable is *used* to determine the type: -.. code:: rust,editable +.. code:: rust fn takes_u32(x: u32) { println!("u32: {x}"); @@ -47,10 +47,10 @@ declaration of a type. The compiler does the job for us and helps us write more concise code. When nothing constrains the type of an integer literal, Rust defaults to -``i32``. This sometimes appears as ``{integer}`` in error messages. -Similarly, floating-point literals default to ``f64``. +:rust:`i32`. This sometimes appears as :rust:`{integer}` in error messages. +Similarly, floating-point literals default to :rust:`f64`. -.. code:: rust,compile_fail +.. code:: rust fn main() { let x = 3.14; diff --git a/courses/comprehensive_rust_training/030_types_and_values/06_exercise.rst b/courses/comprehensive_rust_training/030_types_and_values/06_exercise.rst index de6527d43..64669332e 100644 --- a/courses/comprehensive_rust_training/030_types_and_values/06_exercise.rst +++ b/courses/comprehensive_rust_training/030_types_and_values/06_exercise.rst @@ -6,14 +6,14 @@ Exercise: Fibonacci Exercise: Fibonacci --------------------- -The Fibonacci sequence begins with ``[0,1]``. For n>1, the n'th +The Fibonacci sequence begins with :rust:`[0,1]`. For n>1, the n'th Fibonacci number is calculated recursively as the sum of the n-1'th and n-2'th Fibonacci numbers. -Write a function ``fib(n)`` that calculates the n'th Fibonacci number. +Write a function :rust:`fib(n)` that calculates the n'th Fibonacci number. When will this function panic? -.. code:: rust,editable,should_panic +.. code:: rust {{#include exercise.rs:fib}} if n < 2 { diff --git a/courses/comprehensive_rust_training/040_control_flow_basics/01_if.rst b/courses/comprehensive_rust_training/040_control_flow_basics/01_if.rst index e9bcf6e6b..772529051 100644 --- a/courses/comprehensive_rust_training/040_control_flow_basics/01_if.rst +++ b/courses/comprehensive_rust_training/040_control_flow_basics/01_if.rst @@ -1,16 +1,16 @@ ==================== -``if`` expressions +:rust:`if` expressions ==================== -------------------- -``if`` expressions +:rust:`if` expressions -------------------- You use :url:`if expressions ` -exactly like ``if`` statements in other languages: +exactly like :rust:`if` statements in other languages: -.. code:: rust,editable +.. code:: rust fn main() { let x = 10; @@ -23,10 +23,10 @@ exactly like ``if`` statements in other languages: } } -In addition, you can use ``if`` as an expression. The last expression of -each block becomes the value of the ``if`` expression: +In addition, you can use :rust:`if` as an expression. The last expression of +each block becomes the value of the :rust:`if` expression: -.. code:: rust,editable +.. code:: rust fn main() { let x = 10; @@ -40,14 +40,14 @@ each block becomes the value of the ``if`` expression: Details --------- -Because ``if`` is an expression and must have a particular type, both of +Because :rust:`if` is an expression and must have a particular type, both of its branch blocks must have the same type. Show what happens if you add -``;`` after ``"small"`` in the second example. +:rust:`;` after :rust:`"small"` in the second example. -An ``if`` expression should be used in the same way as the other -expressions. For example, when it is used in a ``let`` statement, the -statement must be terminated with a ``;`` as well. Remove the ``;`` -before ``println!`` to see the compiler error. +An :rust:`if` expression should be used in the same way as the other +expressions. For example, when it is used in a :rust:`let` statement, the +statement must be terminated with a :rust:`;` as well. Remove the :rust:`;` +before :rust:`println!` to see the compiler error. .. raw:: html diff --git a/courses/comprehensive_rust_training/040_control_flow_basics/02_match.rst b/courses/comprehensive_rust_training/040_control_flow_basics/02_match.rst index d6834e96c..f44938dd1 100644 --- a/courses/comprehensive_rust_training/040_control_flow_basics/02_match.rst +++ b/courses/comprehensive_rust_training/040_control_flow_basics/02_match.rst @@ -1,14 +1,14 @@ ======================= -``match`` Expressions +:rust:`match` Expressions ======================= ----------------------- -``match`` Expressions +:rust:`match` Expressions ----------------------- -``match`` can be used to check a value against one or more options: +:rust:`match` can be used to check a value against one or more options: -.. code:: rust,editable +.. code:: rust fn main() { let val = 1; @@ -22,9 +22,9 @@ } } -Like ``if`` expressions, ``match`` can also return a value; +Like :rust:`if` expressions, :rust:`match` can also return a value; -.. code:: rust,editable +.. code:: rust fn main() { let flag = true; @@ -41,24 +41,24 @@ Like ``if`` expressions, ``match`` can also return a value; Details --------- -- ``match`` arms are evaluated from top to bottom, and the first one +- :rust:`match` arms are evaluated from top to bottom, and the first one that matches has its corresponding body executed. -- There is no fall-through between cases the way that ``switch`` works +- There is no fall-through between cases the way that :rust:`switch` works in other languages. -- The body of a ``match`` arm can be a single expression or a block. +- The body of a :rust:`match` arm can be a single expression or a block. Technically this is the same thing, since blocks are also expressions, but students may not fully understand that symmetry at this point. -- ``match`` expressions need to be exhaustive, meaning they either need +- :rust:`match` expressions need to be exhaustive, meaning they either need to cover all possible values or they need to have a default case such - as ``_``. Exhaustiveness is easiest to demonstrate with enums, but + as :rust:`_`. Exhaustiveness is easiest to demonstrate with enums, but enums haven't been introduced yet. Instead we demonstrate matching on - a ``bool``, which is the simplest primitive type. + a :rust:`bool`, which is the simplest primitive type. -- This slide introduces ``match`` without talking about pattern +- This slide introduces :rust:`match` without talking about pattern matching, giving students a chance to get familiar with the syntax without front-loading too much information. We'll be talking about pattern matching in more detail tomorrow, so try not to go into too @@ -68,14 +68,14 @@ Details More to Explore ----------------- -- To further motivate the usage of ``match``, you can compare the - examples to their equivalents written with ``if``. In the second case - matching on a ``bool`` an ``if {} else {}`` block is pretty similar. - But in the first example that checks multiple cases, a ``match`` +- To further motivate the usage of :rust:`match`, you can compare the + examples to their equivalents written with :rust:`if`. In the second case + matching on a :rust:`bool` an :rust:`if {} else {}` block is pretty similar. + But in the first example that checks multiple cases, a :rust:`match` expression can be more concise than - ``if {} else if {} else if {} else``. + :rust:`if {} else if {} else if {} else`. -- ``match`` also supports match guards, which allow you to add an +- :rust:`match` also supports match guards, which allow you to add an arbitrary logical condition that will get evaluated to determine if the match arm should be taken. However talking about match guards requires explaining about pattern matching, which we're trying to diff --git a/courses/comprehensive_rust_training/040_control_flow_basics/03_loops.rst b/courses/comprehensive_rust_training/040_control_flow_basics/03_loops.rst index a5f475c36..b1090b2e9 100644 --- a/courses/comprehensive_rust_training/040_control_flow_basics/03_loops.rst +++ b/courses/comprehensive_rust_training/040_control_flow_basics/03_loops.rst @@ -6,11 +6,11 @@ Loops Loops ------- -There are three looping keywords in Rust: ``while``, ``loop``, and -``for``: +There are three looping keywords in Rust: :rust:`while`, :rust:`loop`, and +:rust:`for`: ----------- -``while`` +:rust:`while` ----------- The @@ -18,7 +18,7 @@ The works much like in other languages, executing the loop body as long as the condition is true. -.. code:: rust,editable +.. code:: rust fn main() { let mut x = 200; diff --git a/courses/comprehensive_rust_training/040_control_flow_basics/04_break_continue.rst b/courses/comprehensive_rust_training/040_control_flow_basics/04_break_continue.rst index db807310a..9966172f2 100644 --- a/courses/comprehensive_rust_training/040_control_flow_basics/04_break_continue.rst +++ b/courses/comprehensive_rust_training/040_control_flow_basics/04_break_continue.rst @@ -1,9 +1,9 @@ ============================ -``break`` and ``continue`` +:rust:`break` and :rust:`continue` ============================ ---------------------------- -``break`` and ``continue`` +:rust:`break` and :rust:`continue` ---------------------------- If you want to immediately start the next iteration use @@ -11,10 +11,10 @@ If you want to immediately start the next iteration use If you want to exit any kind of loop early, use :url:`break `. -With ``loop``, this can take an optional expression that becomes the -value of the ``loop`` expression. +With :rust:`loop`, this can take an optional expression that becomes the +value of the :rust:`loop` expression. -.. code:: rust,editable +.. code:: rust fn main() { let mut i = 0; @@ -36,9 +36,9 @@ value of the ``loop`` expression. Details --------- -Note that ``loop`` is the only looping construct which can return a +Note that :rust:`loop` is the only looping construct which can return a non-trivial value. This is because it's guaranteed to only return at a -``break`` statement (unlike ``while`` and ``for`` loops, which can also +:rust:`break` statement (unlike :rust:`while` and :rust:`for` loops, which can also return when the condition fails). .. raw:: html diff --git a/courses/comprehensive_rust_training/040_control_flow_basics/05_blocks_and_scopes.rst b/courses/comprehensive_rust_training/040_control_flow_basics/05_blocks_and_scopes.rst index 9fbc8024a..d9ef46472 100644 --- a/courses/comprehensive_rust_training/040_control_flow_basics/05_blocks_and_scopes.rst +++ b/courses/comprehensive_rust_training/040_control_flow_basics/05_blocks_and_scopes.rst @@ -11,10 +11,10 @@ Blocks -------- A block in Rust contains a sequence of expressions, enclosed by braces -``{}``. Each block has a value and a type, which are those of the last +:rust:`{}`. Each block has a value and a type, which are those of the last expression of the block: -.. code:: rust,editable +.. code:: rust fn main() { let z = 13; @@ -26,8 +26,8 @@ expression of the block: println!("x: {x}"); } -If the last expression ends with ``;``, then the resulting value and -type is ``()``. +If the last expression ends with :rust:`;`, then the resulting value and +type is :rust:`()`. .. raw:: html @@ -37,7 +37,7 @@ Details - You can show how the value of the block changes by changing the last line in the block. For instance, adding/removing a semicolon or using - a ``return``. + a :rust:`return`. .. raw:: html diff --git a/courses/comprehensive_rust_training/040_control_flow_basics/06_functions.rst b/courses/comprehensive_rust_training/040_control_flow_basics/06_functions.rst index 46976fac8..b723d6c0a 100644 --- a/courses/comprehensive_rust_training/040_control_flow_basics/06_functions.rst +++ b/courses/comprehensive_rust_training/040_control_flow_basics/06_functions.rst @@ -10,7 +10,7 @@ Functions -.. code:: rust,editable +.. code:: rust fn gcd(a: u32, b: u32) -> u32 { if b > 0 { @@ -33,12 +33,12 @@ Details - Declaration parameters are followed by a type (the reverse of some programming languages), then a return type. - The last expression in a function body (or any block) becomes the - return value. Simply omit the ``;`` at the end of the expression. The - ``return`` keyword can be used for early return, but the "bare value" - form is idiomatic at the end of a function (refactor ``gcd`` to use a - ``return``). + return value. Simply omit the :rust:`;` at the end of the expression. The + :rust:`return` keyword can be used for early return, but the "bare value" + form is idiomatic at the end of a function (refactor :rust:`gcd` to use a + :rust:`return`). - Some functions have no return value, and return the 'unit type', - ``()``. The compiler will infer this if the return type is omitted. + :rust:`()`. The compiler will infer this if the return type is omitted. - Overloading is not supported - each function has a single implementation. diff --git a/courses/comprehensive_rust_training/040_control_flow_basics/07_macros.rst b/courses/comprehensive_rust_training/040_control_flow_basics/07_macros.rst index 91d6de2bd..942521a50 100644 --- a/courses/comprehensive_rust_training/040_control_flow_basics/07_macros.rst +++ b/courses/comprehensive_rust_training/040_control_flow_basics/07_macros.rst @@ -7,21 +7,21 @@ Macros -------- Macros are expanded into Rust code during compilation, and can take a -variable number of arguments. They are distinguished by a ``!`` at the +variable number of arguments. They are distinguished by a :rust:`!` at the end. The Rust standard library includes an assortment of useful macros. -- ``println!(format, ..)`` prints a line to standard output, applying +- :rust:`println!(format, ..)` prints a line to standard output, applying formatting described in :url:`std::fmt `. -- ``format!(format, ..)`` works just like ``println!`` but returns the +- :rust:`format!(format, ..)` works just like :rust:`println!` but returns the result as a string. -- ``dbg!(expression)`` logs the value of the expression and returns it. -- ``todo!()`` marks a bit of code as not-yet-implemented. If executed, +- :rust:`dbg!(expression)` logs the value of the expression and returns it. +- :rust:`todo!()` marks a bit of code as not-yet-implemented. If executed, it will panic. -- ``unreachable!()`` marks a bit of code as unreachable. If executed, +- :rust:`unreachable!()` marks a bit of code as unreachable. If executed, it will panic. -.. code:: rust,editable +.. code:: rust fn factorial(n: u32) -> u32 { let mut product = 1; diff --git a/courses/comprehensive_rust_training/040_control_flow_basics/08_exercise.rst b/courses/comprehensive_rust_training/040_control_flow_basics/08_exercise.rst index 6583dcfa2..1861a08d7 100644 --- a/courses/comprehensive_rust_training/040_control_flow_basics/08_exercise.rst +++ b/courses/comprehensive_rust_training/040_control_flow_basics/08_exercise.rst @@ -26,9 +26,9 @@ For example, beginning with *n1* = 3: - the sequence terminates. Write a function to calculate the length of the collatz sequence for a -given initial ``n``. +given initial :rust:`n`. -.. code:: rust,editable,should_panic +.. code:: rust {{#include exercise.rs:collatz_length}} todo!("Implement this") diff --git a/courses/comprehensive_rust_training/050_tuples_and_arrays/01_arrays.rst b/courses/comprehensive_rust_training/050_tuples_and_arrays/01_arrays.rst index 4230596ef..0ee9d10eb 100644 --- a/courses/comprehensive_rust_training/050_tuples_and_arrays/01_arrays.rst +++ b/courses/comprehensive_rust_training/050_tuples_and_arrays/01_arrays.rst @@ -10,7 +10,7 @@ Arrays -.. code:: rust,editable +.. code:: rust fn main() { let mut a: [i8; 10] = [42; 10]; @@ -24,10 +24,10 @@ Arrays Details --------- -- A value of the array type ``[T; N]`` holds ``N`` (a compile-time - constant) elements of the same type ``T``. Note that the length of - the array is *part of its type*, which means that ``[u8; 3]`` and - ``[u8; 4]`` are considered two different types. Slices, which have a +- A value of the array type :rust:`[T; N]` holds :rust:`N` (a compile-time + constant) elements of the same type :rust:`T`. Note that the length of + the array is *part of its type*, which means that :rust:`[u8; 3]` and + :rust:`[u8; 4]` are considered two different types. Slices, which have a size determined at runtime, are covered later. - Try accessing an out-of-bounds array element. Array accesses are @@ -36,13 +36,13 @@ Details - We can use literals to assign values to arrays. -- The ``println!`` macro asks for the debug implementation with the - ``?`` format parameter: ``{}`` gives the default output, ``{:?}`` +- The :rust:`println!` macro asks for the debug implementation with the + :rust:`?` format parameter: :rust:`{}` gives the default output, :rust:`{:?}` gives the debug output. Types such as integers and strings implement the default output, but arrays only implement the debug output. This means that we must use debug output here. -- Adding ``#``, eg ``{a:#?}``, invokes a "pretty printing" format, +- Adding :rust:`#`, eg :rust:`{a:#?}`, invokes a "pretty printing" format, which can be easier to read. .. raw:: html diff --git a/courses/comprehensive_rust_training/050_tuples_and_arrays/02_tuples.rst b/courses/comprehensive_rust_training/050_tuples_and_arrays/02_tuples.rst index e998ccc99..24d1e90f4 100644 --- a/courses/comprehensive_rust_training/050_tuples_and_arrays/02_tuples.rst +++ b/courses/comprehensive_rust_training/050_tuples_and_arrays/02_tuples.rst @@ -10,7 +10,7 @@ Tuples -.. code:: rust,editable +.. code:: rust fn main() { let t: (i8, bool) = (7, true); @@ -29,10 +29,10 @@ Details - Tuples group together values of different types into a compound type. - Fields of a tuple can be accessed by the period and the index of the - value, e.g. ``t.0``, ``t.1``. + value, e.g. :rust:`t.0`, :rust:`t.1`. -- The empty tuple ``()`` is referred to as the "unit type" and - signifies absence of a return value, akin to ``void`` in other +- The empty tuple :rust:`()` is referred to as the "unit type" and + signifies absence of a return value, akin to :rust:`void` in other languages. .. raw:: html diff --git a/courses/comprehensive_rust_training/050_tuples_and_arrays/03_iteration.rst b/courses/comprehensive_rust_training/050_tuples_and_arrays/03_iteration.rst index 761da0eb5..fb73398b5 100644 --- a/courses/comprehensive_rust_training/050_tuples_and_arrays/03_iteration.rst +++ b/courses/comprehensive_rust_training/050_tuples_and_arrays/03_iteration.rst @@ -6,9 +6,9 @@ Array Iteration Array Iteration ----------------- -The ``for`` statement supports iterating over arrays (but not tuples). +The :rust:`for` statement supports iterating over arrays (but not tuples). -.. code:: rust,editable +.. code:: rust fn main() { let primes = [2, 3, 5, 7, 11, 13, 17, 19]; @@ -25,12 +25,12 @@ The ``for`` statement supports iterating over arrays (but not tuples). Details --------- -This functionality uses the ``IntoIterator`` trait, but we haven't +This functionality uses the :rust:`IntoIterator` trait, but we haven't covered that yet. -The ``assert_ne!`` macro is new here. There are also ``assert_eq!`` and -``assert!`` macros. These are always checked, while debug-only variants -like ``debug_assert!`` compile to nothing in release builds. +The :rust:`assert_ne!` macro is new here. There are also :rust:`assert_eq!` and +:rust:`assert!` macros. These are always checked, while debug-only variants +like :rust:`debug_assert!` compile to nothing in release builds. .. raw:: html diff --git a/courses/comprehensive_rust_training/050_tuples_and_arrays/04_destructuring.rst b/courses/comprehensive_rust_training/050_tuples_and_arrays/04_destructuring.rst index a670c7525..5958b45f4 100644 --- a/courses/comprehensive_rust_training/050_tuples_and_arrays/04_destructuring.rst +++ b/courses/comprehensive_rust_training/050_tuples_and_arrays/04_destructuring.rst @@ -10,7 +10,7 @@ When working with tuples and other structured values it's common to want to extract the inner values into local variables. This can be done manually by directly accessing the inner values: -.. code:: rust,editable +.. code:: rust fn print_tuple(tuple: (i32, i32)) { let left = tuple.0; @@ -21,7 +21,7 @@ manually by directly accessing the inner values: However, Rust also supports using pattern matching to destructure a larger value into its constituent parts: -.. code:: rust,editable +.. code:: rust fn print_tuple(tuple: (i32, i32)) { let (left, right) = tuple; @@ -35,10 +35,10 @@ Details --------- - The patterns used here are "irrefutable", meaning that the compiler - can statically verify that the value on the right of ``=`` has the + can statically verify that the value on the right of :rust:`=` has the same structure as the pattern. - A variable name is an irrefutable pattern that always matches any - value, hence why we can also use ``let`` to declare a single + value, hence why we can also use :rust:`let` to declare a single variable. - Rust also supports using patterns in conditionals, allowing for equality comparison and destructuring to happen at the same time. diff --git a/courses/comprehensive_rust_training/050_tuples_and_arrays/05_exercise.rst b/courses/comprehensive_rust_training/050_tuples_and_arrays/05_exercise.rst index c7fff5376..8db643227 100644 --- a/courses/comprehensive_rust_training/050_tuples_and_arrays/05_exercise.rst +++ b/courses/comprehensive_rust_training/050_tuples_and_arrays/05_exercise.rst @@ -14,7 +14,7 @@ Arrays can contain other arrays: What is the type of this variable? -Use an array such as the above to write a function ``transpose`` which +Use an array such as the above to write a function :rust:`transpose` which will transpose a matrix (turn rows into columns): Transpose @@ -40,7 +40,7 @@ into Copy the code below to https://play.rust-lang.org/ and implement the function. This function only operates on 3x3 matrices. -.. code:: rust,should_panic +.. code:: rust // TODO: remove this when you're done with your implementation. #![allow(unused_variables, dead_code)] diff --git a/courses/comprehensive_rust_training/060_references/01_shared.rst b/courses/comprehensive_rust_training/060_references/01_shared.rst index a6274aa2c..331122c88 100644 --- a/courses/comprehensive_rust_training/060_references/01_shared.rst +++ b/courses/comprehensive_rust_training/060_references/01_shared.rst @@ -14,7 +14,7 @@ references are read-only, and the referenced data cannot change. -.. code:: rust,editable +.. code:: rust fn main() { let a = 'A'; @@ -25,8 +25,8 @@ references are read-only, and the referenced data cannot change. println!("r: {}", *r); } -A shared reference to a type ``T`` has type ``&T``. A reference value is -made with the ``&`` operator. The ``*`` operator "dereferences" a +A shared reference to a type :rust:`T` has type :rust:`&T`. A reference value is +made with the :rust:`&` operator. The :rust:`*` operator "dereferences" a reference, yielding its value. .. raw:: html @@ -49,24 +49,24 @@ Details parts of the course will cover how Rust prevents the memory-safety bugs that come from using raw pointers. -- Rust does not automatically create references for you - the ``&`` is +- Rust does not automatically create references for you - the :rust:`&` is always required. - Rust will auto-dereference in some cases, in particular when invoking - methods (try ``r.is_ascii()``). There is no need for an ``->`` + methods (try :rust:`r.is_ascii()`). There is no need for an :rust:`->` operator like in C++. -- In this example, ``r`` is mutable so that it can be reassigned - (``r = &b``). Note that this re-binds ``r``, so that it refers to +- In this example, :rust:`r` is mutable so that it can be reassigned + (:rust:`r = &b`). Note that this re-binds :rust:`r`, so that it refers to something else. This is different from C++, where assignment to a reference changes the referenced value. - A shared reference does not allow modifying the value it refers to, - even if that value was mutable. Try ``*r = 'X'``. + even if that value was mutable. Try :rust:`*r = 'X'`. - Rust is tracking the lifetimes of all references to ensure they live long enough. Dangling references cannot occur in safe Rust. - ``x_axis`` would return a reference to ``point``, but ``point`` will + :rust:`x_axis` would return a reference to :rust:`point`, but :rust:`point` will be deallocated when the function returns, so this will not compile. - We will talk more about borrowing when we get to ownership. diff --git a/courses/comprehensive_rust_training/060_references/02_exclusive.rst b/courses/comprehensive_rust_training/060_references/02_exclusive.rst index b9ec44233..264ab6c52 100644 --- a/courses/comprehensive_rust_training/060_references/02_exclusive.rst +++ b/courses/comprehensive_rust_training/060_references/02_exclusive.rst @@ -7,13 +7,13 @@ Exclusive References ---------------------- Exclusive references, also known as mutable references, allow changing -the value they refer to. They have type ``&mut T``. +the value they refer to. They have type :rust:`&mut T`. .. raw:: html -.. code:: rust,editable +.. code:: rust fn main() { let mut point = (1, 2); @@ -33,11 +33,11 @@ Key points: - "Exclusive" means that only this reference can be used to access the value. No other references (shared or exclusive) can exist at the same time, and the referenced value cannot be accessed while the - exclusive reference exists. Try making an ``&point.0`` or changing - ``point.0`` while ``x_coord`` is alive. + exclusive reference exists. Try making an :rust:`&point.0` or changing + :rust:`point.0` while :rust:`x_coord` is alive. -- Be sure to note the difference between ``let mut x_coord: &i32`` and - ``let x_coord: &mut i32``. The first one represents a shared +- Be sure to note the difference between :rust:`let mut x_coord: &i32` and + :rust:`let x_coord: &mut i32`. The first one represents a shared reference which can be bound to different values, while the second represents an exclusive reference to a mutable value. diff --git a/courses/comprehensive_rust_training/060_references/03_slices.rst b/courses/comprehensive_rust_training/060_references/03_slices.rst index 046fe9e54..8af661dd7 100644 --- a/courses/comprehensive_rust_training/060_references/03_slices.rst +++ b/courses/comprehensive_rust_training/060_references/03_slices.rst @@ -12,7 +12,7 @@ A slice gives you a view into a larger collection: -.. code:: rust,editable +.. code:: rust fn main() { let a: [i32; 6] = [10, 20, 30, 40, 50, 60]; @@ -31,24 +31,24 @@ A slice gives you a view into a larger collection: Details --------- -- We create a slice by borrowing ``a`` and specifying the starting and +- We create a slice by borrowing :rust:`a` and specifying the starting and ending indexes in brackets. - If the slice starts at index 0, Rust's range syntax allows us to drop - the starting index, meaning that ``&a[0..a.len()]`` and - ``&a[..a.len()]`` are identical. + the starting index, meaning that :rust:`&a[0..a.len()]` and + :rust:`&a[..a.len()]` are identical. -- The same is true for the last index, so ``&a[2..a.len()]`` and - ``&a[2..]`` are identical. +- The same is true for the last index, so :rust:`&a[2..a.len()]` and + :rust:`&a[2..]` are identical. - To easily create a slice of the full array, we can therefore use - ``&a[..]``. + :rust:`&a[..]`. -- ``s`` is a reference to a slice of ``i32``\ s. Notice that the type - of ``s`` (``&[i32]``) no longer mentions the array length. This +- :rust:`s` is a reference to a slice of :rust:`i32`\ s. Notice that the type + of :rust:`s` (:rust:`&[i32]`) no longer mentions the array length. This allows us to perform computation on slices of different sizes. -- Slices always borrow from another object. In this example, ``a`` has +- Slices always borrow from another object. In this example, :rust:`a` has to remain 'alive' (in scope) for at least as long as our slice. .. raw:: html diff --git a/courses/comprehensive_rust_training/060_references/04_strings.rst b/courses/comprehensive_rust_training/060_references/04_strings.rst index fa2a77c28..2b2944926 100644 --- a/courses/comprehensive_rust_training/060_references/04_strings.rst +++ b/courses/comprehensive_rust_training/060_references/04_strings.rst @@ -14,16 +14,16 @@ Strings We can now understand the two string types in Rust: -- ``&str`` is a slice of UTF-8 encoded bytes, similar to ``&[u8]``. -- ``String`` is an owned buffer of UTF-8 encoded bytes, similar to - ``Vec``. +- :rust:`&str` is a slice of UTF-8 encoded bytes, similar to :rust:`&[u8]`. +- :rust:`String` is an owned buffer of UTF-8 encoded bytes, similar to + :rust:`Vec`. .. raw:: html -.. code:: rust,editable +.. code:: rust fn main() { let s1: &str = "World"; @@ -44,56 +44,56 @@ We can now understand the two string types in Rust: Details --------- -- ``&str`` introduces a string slice, which is an immutable reference +- :rust:`&str` introduces a string slice, which is an immutable reference to UTF-8 encoded string data stored in a block of memory. String - literals (``"Hello"``), are stored in the program's binary. + literals (:rust:`"Hello"`), are stored in the program's binary. -- Rust's ``String`` type is a wrapper around a vector of bytes. As with - a ``Vec``, it is owned. +- Rust's :rust:`String` type is a wrapper around a vector of bytes. As with + a :rust:`Vec`, it is owned. -- As with many other types ``String::from()`` creates a string from a - string literal; ``String::new()`` creates a new empty string, to - which string data can be added using the ``push()`` and - ``push_str()`` methods. +- As with many other types :rust:`String::from()` creates a string from a + string literal; :rust:`String::new()` creates a new empty string, to + which string data can be added using the :rust:`push()` and + :rust:`push_str()` methods. -- The ``format!()`` macro is a convenient way to generate an owned +- The :rust:`format!()` macro is a convenient way to generate an owned string from dynamic values. It accepts the same format specification - as ``println!()``. + as :rust:`println!()`. -- You can borrow ``&str`` slices from ``String`` via ``&`` and +- You can borrow :rust:`&str` slices from :rust:`String` via :rust:`&` and optionally range selection. If you select a byte range that is not aligned to character boundaries, the expression will panic. The - ``chars`` iterator iterates over characters and is preferred over + :rust:`chars` iterator iterates over characters and is preferred over trying to get character boundaries right. -- For C++ programmers: think of ``&str`` as ``std::string_view`` from +- For C++ programmers: think of :rust:`&str` as :rust:`std::string_view` from C++, but the one that always points to a valid string in memory. Rust - ``String`` is a rough equivalent of ``std::string`` from C++ (main + :rust:`String` is a rough equivalent of :rust:`std::string` from C++ (main difference: it can only contain UTF-8 encoded bytes and will never use a small-string optimization). -- Byte strings literals allow you to create a ``&[u8]`` value directly: +- Byte strings literals allow you to create a :rust:`&[u8]` value directly: .. raw:: html - .. code:: rust,editable + .. code:: rust fn main() { println!("{:?}", b"abc"); println!("{:?}", &[97, 98, 99]); } -- Raw strings allow you to create a ``&str`` value with escapes - disabled: ``r"\n" == "\\n"``. You can embed double-quotes by using an - equal amount of ``#`` on either side of the quotes: +- Raw strings allow you to create a :rust:`&str` value with escapes + disabled: :rust:`r"\n" == "\\n"`. You can embed double-quotes by using an + equal amount of :rust:`#` on either side of the quotes: .. raw:: html - .. code:: rust,editable + .. code:: rust fn main() { println!(r#"link"#); diff --git a/courses/comprehensive_rust_training/060_references/05_dangling.rst b/courses/comprehensive_rust_training/060_references/05_dangling.rst index 1e32cc8fa..27185641a 100644 --- a/courses/comprehensive_rust_training/060_references/05_dangling.rst +++ b/courses/comprehensive_rust_training/060_references/05_dangling.rst @@ -7,15 +7,15 @@ Reference Validity -------------------- Rust enforces a number of rules for references that make them always -safe to use. One rule is that references can never be ``null``, making -them safe to use without ``null`` checks. The other rule we'll look at +safe to use. One rule is that references can never be :rust:`null`, making +them safe to use without :rust:`null` checks. The other rule we'll look at for now is that references can't *outlive* the data they point to. .. raw:: html -.. code:: rust,editable,compile_fail +.. code:: rust fn main() { let x_ref = { @@ -42,7 +42,7 @@ Details More to Explore ----------------- -- Rust's equivalent of nullability is the ``Option`` type, which can be +- Rust's equivalent of nullability is the :rust:`Option` type, which can be used to make any type "nullable" (not just references/pointers). We haven't yet introduced enums or pattern matching, though, so try not to go into too much detail about this here. diff --git a/courses/comprehensive_rust_training/060_references/06_exercise.rst b/courses/comprehensive_rust_training/060_references/06_exercise.rst index 927816f8d..faf9f1b5c 100644 --- a/courses/comprehensive_rust_training/060_references/06_exercise.rst +++ b/courses/comprehensive_rust_training/060_references/06_exercise.rst @@ -7,10 +7,10 @@ Exercise: Geometry -------------------- We will create a few utility functions for 3-dimensional geometry, -representing a point as ``[f64;3]``. It is up to you to determine the +representing a point as :rust:`[f64;3]`. It is up to you to determine the function signatures. -.. code:: rust,compile_fail +.. code:: rust // Calculate the magnitude of a vector by summing the squares of its coordinates // and taking the square root. Use the `sqrt()` method to calculate the square diff --git a/courses/comprehensive_rust_training/070_user_defined_types/01_named_structs.rst b/courses/comprehensive_rust_training/070_user_defined_types/01_named_structs.rst index 9c9ea7464..6ffa1749d 100644 --- a/courses/comprehensive_rust_training/070_user_defined_types/01_named_structs.rst +++ b/courses/comprehensive_rust_training/070_user_defined_types/01_named_structs.rst @@ -8,7 +8,7 @@ Named Structs Like C and C++, Rust has support for custom structs: -.. code:: rust,editable +.. code:: rust struct Person { name: String, @@ -52,7 +52,7 @@ Key Points: - This may be a good time to let people know there are different types of structs. - - Zero-sized structs (e.g. ``struct Foo;``) might be used when + - Zero-sized structs (e.g. :rust:`struct Foo;`) might be used when implementing a trait on some type but don't have any data that you want to store in the value itself. - The next slide will introduce Tuple structs, used when the field @@ -60,7 +60,7 @@ Key Points: - If you already have variables with the right names, then you can create the struct using a shorthand. -- The syntax ``..avery`` allows us to copy the majority of the fields +- The syntax :rust:`..avery` allows us to copy the majority of the fields from the old struct without having to explicitly type it all out. It must always be the last element. diff --git a/courses/comprehensive_rust_training/070_user_defined_types/02_tuple_structs.rst b/courses/comprehensive_rust_training/070_user_defined_types/02_tuple_structs.rst index b5792b3ee..ca83c1bde 100644 --- a/courses/comprehensive_rust_training/070_user_defined_types/02_tuple_structs.rst +++ b/courses/comprehensive_rust_training/070_user_defined_types/02_tuple_structs.rst @@ -14,7 +14,7 @@ Tuple Structs If the field names are unimportant, you can use a tuple struct: -.. code:: rust,editable +.. code:: rust struct Point(i32, i32); @@ -25,7 +25,7 @@ If the field names are unimportant, you can use a tuple struct: This is often used for single-field wrappers (called newtypes): -.. code:: rust,editable,compile_fail +.. code:: rust struct PoundsOfForce(f64); struct Newtons(f64); @@ -52,13 +52,13 @@ Details - Newtypes are a great way to encode additional information about the value in a primitive type, for example: - - The number is measured in some units: ``Newtons`` in the example + - The number is measured in some units: :rust:`Newtons` in the example above. - The value passed some validation when it was created, so you no longer have to validate it again at every use: - ``PhoneNumber(String)`` or ``OddNumber(u32)``. + :rust:`PhoneNumber(String)` or :rust:`OddNumber(u32)`. -- Demonstrate how to add a ``f64`` value to a ``Newtons`` type by +- Demonstrate how to add a :rust:`f64` value to a :rust:`Newtons` type by accessing the single field in the newtype. - Rust generally doesn't like inexplicit things, like automatic diff --git a/courses/comprehensive_rust_training/070_user_defined_types/03_enums.rst b/courses/comprehensive_rust_training/070_user_defined_types/03_enums.rst index 3eb244d25..7ea5aaf18 100644 --- a/courses/comprehensive_rust_training/070_user_defined_types/03_enums.rst +++ b/courses/comprehensive_rust_training/070_user_defined_types/03_enums.rst @@ -6,10 +6,10 @@ Enums Enums ------- -The ``enum`` keyword allows the creation of a type which has a few +The :rust:`enum` keyword allows the creation of a type which has a few different variants: -.. code:: rust,editable +.. code:: rust #[derive(Debug)] enum Direction { @@ -38,11 +38,11 @@ Details Key Points: - Enumerations allow you to collect a set of values under one type. -- ``Direction`` is a type with variants. There are two values of - ``Direction``: ``Direction::Left`` and ``Direction::Right``. -- ``PlayerMove`` is a type with three variants. In addition to the +- :rust:`Direction` is a type with variants. There are two values of + :rust:`Direction`: :rust:`Direction::Left` and :rust:`Direction::Right`. +- :rust:`PlayerMove` is a type with three variants. In addition to the payloads, Rust will store a discriminant so that it knows at runtime - which variant is in a ``PlayerMove`` value. + which variant is in a :rust:`PlayerMove` value. - This might be a good time to compare structs and enums: - In both, you can have a simple version without fields (unit @@ -57,8 +57,8 @@ Key Points: - If the allowed variant values do not cover all bit patterns, it will use invalid bit patterns to encode the discriminant (the - "niche optimization"). For example, ``Option<&u8>`` stores either - a pointer to an integer or ``NULL`` for the ``None`` variant. + "niche optimization"). For example, :rust:`Option<&u8>` stores either + a pointer to an integer or :rust:`NULL` for the :rust:`None` variant. - You can control the discriminant if needed (e.g., for compatibility with C): @@ -67,7 +67,7 @@ Key Points: - .. code:: rust,editable + .. code:: rust #[repr(u32)] enum Bar { @@ -82,7 +82,7 @@ Key Points: println!("C: {}", Bar::C as u32); } - Without ``repr``, the discriminant type takes 2 bytes, because + Without :rust:`repr`, the discriminant type takes 2 bytes, because 10001 fits 2 bytes. ----------------- @@ -94,7 +94,7 @@ space. - Null pointer optimization: For :url:`some types `, Rust - guarantees that ``size_of::()`` equals ``size_of::>()``. + guarantees that :rust:`size_of::()` equals :rust:`size_of::>()`. Example code if you want to show how the bitwise representation *may* look like in practice. It's important to note that the compiler @@ -105,7 +105,7 @@ space. - .. code:: rust,editable + .. code:: rust use std::mem::transmute; diff --git a/courses/comprehensive_rust_training/070_user_defined_types/04_aliases.rst b/courses/comprehensive_rust_training/070_user_defined_types/04_aliases.rst index cb6b191ba..004604b47 100644 --- a/courses/comprehensive_rust_training/070_user_defined_types/04_aliases.rst +++ b/courses/comprehensive_rust_training/070_user_defined_types/04_aliases.rst @@ -9,7 +9,7 @@ Type Aliases A type alias creates a name for another type. The two types can be used interchangeably. -.. code:: rust,editable +.. code:: rust enum CarryableConcreteItem { Left, @@ -31,9 +31,9 @@ Details - A :url:`newtype ` is often a better alternative since it creates a distinct type. Prefer - ``struct InventoryCount(usize)`` to ``type InventoryCount = usize``. + :rust:`struct InventoryCount(usize)` to :rust:`type InventoryCount = usize`. -- C programmers will recognize this as similar to a ``typedef``. +- C programmers will recognize this as similar to a :rust:`typedef`. .. raw:: html diff --git a/courses/comprehensive_rust_training/070_user_defined_types/05_const.rst b/courses/comprehensive_rust_training/070_user_defined_types/05_const.rst index 73b78ca61..419a4cba7 100644 --- a/courses/comprehensive_rust_training/070_user_defined_types/05_const.rst +++ b/courses/comprehensive_rust_training/070_user_defined_types/05_const.rst @@ -1,9 +1,9 @@ =========== -``const`` +:rust:`const` =========== ----------- -``const`` +:rust:`const` ----------- Constants are evaluated at compile time and their values are inlined @@ -13,7 +13,7 @@ wherever they are used: -.. code:: rust,editable +.. code:: rust const DIGEST_SIZE: usize = 3; const FILL_VALUE: u8 = calculate_fill_value(); @@ -43,8 +43,8 @@ According to the :url:`Rust RFC Book ` these are inlined upon use. -Only functions marked ``const`` can be called at compile time to -generate ``const`` values. ``const`` functions can however be called at +Only functions marked :rust:`const` can be called at compile time to +generate :rust:`const` values. :rust:`const` functions can however be called at runtime. .. raw:: html @@ -53,8 +53,8 @@ runtime. Details --------- -- Mention that ``const`` behaves semantically similar to C++'s - ``constexpr`` +- Mention that :rust:`const` behaves semantically similar to C++'s + :rust:`constexpr` .. raw:: html diff --git a/courses/comprehensive_rust_training/070_user_defined_types/06_static.rst b/courses/comprehensive_rust_training/070_user_defined_types/06_static.rst index e8e09acfc..4f75a5fab 100644 --- a/courses/comprehensive_rust_training/070_user_defined_types/06_static.rst +++ b/courses/comprehensive_rust_training/070_user_defined_types/06_static.rst @@ -1,15 +1,15 @@ ============ -``static`` +:rust:`static` ============ ------------ -``static`` +:rust:`static` ------------ Static variables will live during the whole execution of the program, and therefore will not move: -.. code:: rust,editable +.. code:: rust static BANNER: &str = "Welcome to RustOS 3.14"; @@ -23,7 +23,7 @@ these are not inlined upon use and have an actual associated memory location. This is useful for unsafe and embedded code, and the variable lives through the entirety of the program execution. When a globally-scoped value does not have a reason to need object identity, -``const`` is generally preferred. +:rust:`const` is generally preferred. .. raw:: html @@ -31,9 +31,9 @@ globally-scoped value does not have a reason to need object identity, Details --------- -- ``static`` is similar to mutable global variables in C++. -- ``static`` provides object identity: an address in memory and state - as required by types with interior mutability such as ``Mutex``. +- :rust:`static` is similar to mutable global variables in C++. +- :rust:`static` provides object identity: an address in memory and state + as required by types with interior mutability such as :rust:`Mutex`. ================= More to Explore @@ -43,16 +43,16 @@ More to Explore More to Explore ----------------- -Because ``static`` variables are accessible from any thread, they must -be ``Sync``. Interior mutability is possible through a +Because :rust:`static` variables are accessible from any thread, they must +be :rust:`Sync`. Interior mutability is possible through a :url:`Mutex `, atomic or similar. -It is common to use ``OnceLock`` in a static as a way to support -initialization on first use. ``OnceCell`` is not ``Sync`` and thus +It is common to use :rust:`OnceLock` in a static as a way to support +initialization on first use. :rust:`OnceCell` is not :rust:`Sync` and thus cannot be used in this context. -Thread-local data can be created with the macro ``std::thread_local``. +Thread-local data can be created with the macro :rust:`std::thread_local`. .. raw:: html diff --git a/courses/comprehensive_rust_training/070_user_defined_types/07_exercise.rst b/courses/comprehensive_rust_training/070_user_defined_types/07_exercise.rst index d89c8d97e..bbb5c104e 100644 --- a/courses/comprehensive_rust_training/070_user_defined_types/07_exercise.rst +++ b/courses/comprehensive_rust_training/070_user_defined_types/07_exercise.rst @@ -8,14 +8,14 @@ Exercise: Elevator Events We will create a data structure to represent an event in an elevator control system. It is up to you to define the types and functions to -construct various events. Use ``#[derive(Debug)]`` to allow the types to -be formatted with ``{:?}``. +construct various events. Use :rust:`#[derive(Debug)]` to allow the types to +be formatted with :rust:`{:?}`. This exercise only requires creating and populating data structures so -that ``main`` runs without errors. The next part of the course will +that :rust:`main` runs without errors. The next part of the course will cover getting data out of these structures. -.. code:: rust,editable,should_panic +.. code:: rust {{#include exercise.rs:event}} // TODO: add required variants diff --git a/courses/comprehensive_rust_training/080_pattern_matching/01_match.rst b/courses/comprehensive_rust_training/080_pattern_matching/01_match.rst index a15013aeb..eafa897cf 100644 --- a/courses/comprehensive_rust_training/080_pattern_matching/01_match.rst +++ b/courses/comprehensive_rust_training/080_pattern_matching/01_match.rst @@ -6,12 +6,12 @@ Matching Values Matching Values ----------------- -The ``match`` keyword lets you match a value against one or more -*patterns*. The patterns can be simple values, similarly to ``switch`` +The :rust:`match` keyword lets you match a value against one or more +*patterns*. The patterns can be simple values, similarly to :rust:`switch` in C and C++, but they can also be used to express more complex conditions: -.. code:: rust,editable +.. code:: rust #[rustfmt::skip] fn main() { @@ -25,7 +25,7 @@ conditions: } } -A variable in the pattern (``key`` in this example) will create a +A variable in the pattern (:rust:`key` in this example) will create a binding that can be used within the match arm. We will learn more about this on the next slide. @@ -43,21 +43,21 @@ Key Points: - You might point out how some specific characters are being used when in a pattern - - ``|`` as an ``or`` - - ``..`` can expand as much as it needs to be - - ``1..=5`` represents an inclusive range - - ``_`` is a wild card + - :rust:`|` as an :rust:`or` + - :rust:`..` can expand as much as it needs to be + - :rust:`1..=5` represents an inclusive range + - :rust:`_` is a wild card - Match guards as a separate syntax feature are important and necessary when we wish to concisely express more complex ideas than patterns alone would allow. -- They are not the same as separate ``if`` expression inside of the - match arm. An ``if`` expression inside of the branch block (after - ``=>``) happens after the match arm is selected. Failing the ``if`` +- They are not the same as separate :rust:`if` expression inside of the + match arm. An :rust:`if` expression inside of the branch block (after + :rust:`=>`) happens after the match arm is selected. Failing the :rust:`if` condition inside of that block won't result in other arms of the - original ``match`` expression being considered. + original :rust:`match` expression being considered. - The condition defined in the guard applies to every expression in a - pattern with an ``|``. + pattern with an :rust:`|`. ================= More To Explore @@ -67,7 +67,7 @@ More To Explore More To Explore ----------------- -- Another piece of pattern syntax you can show students is the ``@`` +- Another piece of pattern syntax you can show students is the :rust:`@` syntax which binds a part of a pattern to a variable. For example: .. code:: rust @@ -80,10 +80,10 @@ More To Explore None => {} } - In this example ``inner`` has the value 123 which it pulled from the - ``Option`` via destructuring, ``outer`` captures the entire - ``Some(inner)`` expression, so it contains the full - ``Option::Some(123)``. This is rarely used but can be useful in more + In this example :rust:`inner` has the value 123 which it pulled from the + :rust:`Option` via destructuring, :rust:`outer` captures the entire + :rust:`Some(inner)` expression, so it contains the full + :rust:`Option::Some(123)`. This is rarely used but can be useful in more complex patterns. .. raw:: html diff --git a/courses/comprehensive_rust_training/080_pattern_matching/02_destructuring_structs.rst b/courses/comprehensive_rust_training/080_pattern_matching/02_destructuring_structs.rst index f6f3f7e2c..3342d8ea2 100644 --- a/courses/comprehensive_rust_training/080_pattern_matching/02_destructuring_structs.rst +++ b/courses/comprehensive_rust_training/080_pattern_matching/02_destructuring_structs.rst @@ -8,7 +8,7 @@ Structs Like tuples, Struct can also be destructured by matching: -.. code:: rust,editable +.. code:: rust {{#include ../../third_party/rust-by-example/destructuring-structs.rs}} @@ -18,12 +18,12 @@ Like tuples, Struct can also be destructured by matching: Details --------- -- Change the literal values in ``foo`` to match with the other +- Change the literal values in :rust:`foo` to match with the other patterns. -- Add a new field to ``Foo`` and make changes to the pattern as needed. +- Add a new field to :rust:`Foo` and make changes to the pattern as needed. - The distinction between a capture and a constant expression can be - hard to spot. Try changing the ``2`` in the second arm to a variable, - and see that it subtly doesn't work. Change it to a ``const`` and see + hard to spot. Try changing the :rust:`2` in the second arm to a variable, + and see that it subtly doesn't work. Change it to a :rust:`const` and see it working again. .. raw:: html diff --git a/courses/comprehensive_rust_training/080_pattern_matching/03_destructuring_enums.rst b/courses/comprehensive_rust_training/080_pattern_matching/03_destructuring_enums.rst index cc974fec6..326252068 100644 --- a/courses/comprehensive_rust_training/080_pattern_matching/03_destructuring_enums.rst +++ b/courses/comprehensive_rust_training/080_pattern_matching/03_destructuring_enums.rst @@ -10,9 +10,9 @@ Like tuples, enums can also be destructured by matching: Patterns can also be used to bind variables to parts of your values. This is how you inspect the structure of your types. Let us start with a -simple ``enum`` type: +simple :rust:`enum` type: -.. code:: rust,editable +.. code:: rust enum Result { Ok(i32), @@ -35,9 +35,9 @@ simple ``enum`` type: } } -Here we have used the arms to *destructure* the ``Result`` value. In the -first arm, ``half`` is bound to the value inside the ``Ok`` variant. In -the second arm, ``msg`` is bound to the error message. +Here we have used the arms to *destructure* the :rust:`Result` value. In the +first arm, :rust:`half` is bound to the value inside the :rust:`Ok` variant. In +the second arm, :rust:`msg` is bound to the error message. .. raw:: html @@ -45,8 +45,8 @@ the second arm, ``msg`` is bound to the error message. Details --------- -- The ``if``/``else`` expression is returning an enum that is later - unpacked with a ``match``. +- The :rust:`if`/:rust:`else` expression is returning an enum that is later + unpacked with a :rust:`match`. - You can try adding a third variant to the enum definition and displaying the errors when running the code. Point out the places where your code is now inexhaustive and how the compiler tries to diff --git a/courses/comprehensive_rust_training/080_pattern_matching/04_let_control_flow.rst b/courses/comprehensive_rust_training/080_pattern_matching/04_let_control_flow.rst index 2907e47a1..20464b901 100644 --- a/courses/comprehensive_rust_training/080_pattern_matching/04_let_control_flow.rst +++ b/courses/comprehensive_rust_training/080_pattern_matching/04_let_control_flow.rst @@ -9,16 +9,16 @@ Let Control Flow Rust has a few control flow constructs which differ from other languages. They are used for pattern matching: -- ``if let`` expressions -- ``let else`` expressions -- ``while let`` expressions +- :rust:`if let` expressions +- :rust:`let else` expressions +- :rust:`while let` expressions ======================== -``if let`` expressions +:rust:`if let` expressions ======================== ------------------------ -``if let`` expressions +:rust:`if let` expressions ------------------------ The @@ -26,7 +26,7 @@ The lets you execute different code depending on whether a value matches a pattern: -.. code:: rust,editable +.. code:: rust use std::time::Duration; @@ -43,20 +43,20 @@ pattern: } ========================== -``let else`` expressions +:rust:`let else` expressions ========================== -------------------------- -``let else`` expressions +:rust:`let else` expressions -------------------------- For the common case of matching a pattern and returning from the function, use :url:`let else `. -The "else" case must diverge (``return``, ``break``, or panic - anything +The "else" case must diverge (:rust:`return`, :rust:`break`, or panic - anything but falling off the end of the block). -.. code:: rust,editable +.. code:: rust fn hex_or_die_trying(maybe_string: Option) -> Result { // TODO: The structure of this code is difficult to follow -- rewrite it with let-else! @@ -79,7 +79,7 @@ but falling off the end of the block). println!("result: {:?}", hex_or_die_trying(Some(String::from("foo")))); } -Like with ``if let``, there is a +Like with :rust:`if let`, there is a :url:`while let ` variant which repeatedly tests a value against a pattern: @@ -87,7 +87,7 @@ variant which repeatedly tests a value against a pattern: -.. code:: rust,editable +.. code:: rust fn main() { let mut name = String::from("Comprehensive Rust"); @@ -99,8 +99,8 @@ variant which repeatedly tests a value against a pattern: Here :url:`String::pop ` -returns ``Some(c)`` until the string is empty, after which it will -return ``None``. The ``while let`` lets us keep iterating through all +returns :rust:`Some(c)` until the string is empty, after which it will +return :rust:`None`. The :rust:`while let` lets us keep iterating through all items. .. raw:: html @@ -113,18 +113,18 @@ Details if-let -------- -- Unlike ``match``, ``if let`` does not have to cover all branches. - This can make it more concise than ``match``. -- A common usage is handling ``Some`` values when working with - ``Option``. -- Unlike ``match``, ``if let`` does not support guard clauses for +- Unlike :rust:`match`, :rust:`if let` does not have to cover all branches. + This can make it more concise than :rust:`match`. +- A common usage is handling :rust:`Some` values when working with + :rust:`Option`. +- Unlike :rust:`match`, :rust:`if let` does not support guard clauses for pattern matching. ---------- let-else ---------- -``if-let``\ s can pile up, as shown. The ``let-else`` construct supports +:rust:`if-let`\ s can pile up, as shown. The :rust:`let-else` construct supports flattening this nested code. Rewrite the awkward version for students, so they can see the transformation. @@ -156,11 +156,11 @@ while-let while-let ----------- -- Point out that the ``while let`` loop will keep going as long as the +- Point out that the :rust:`while let` loop will keep going as long as the value matches the pattern. -- You could rewrite the ``while let`` loop as an infinite loop with an +- You could rewrite the :rust:`while let` loop as an infinite loop with an if statement that breaks when there is no value to unwrap for - ``name.pop()``. The ``while let`` provides syntactic sugar for the + :rust:`name.pop()`. The :rust:`while let` provides syntactic sugar for the above scenario. .. raw:: html diff --git a/courses/comprehensive_rust_training/080_pattern_matching/05_exercise.rst b/courses/comprehensive_rust_training/080_pattern_matching/05_exercise.rst index c27dc8729..7585e9f7e 100644 --- a/courses/comprehensive_rust_training/080_pattern_matching/05_exercise.rst +++ b/courses/comprehensive_rust_training/080_pattern_matching/05_exercise.rst @@ -8,8 +8,8 @@ Exercise: Expression Evaluation Let's write a simple recursive evaluator for arithmetic expressions. -An example of a small arithmetic expression could be ``10 + 20``, which -evaluates to ``30``. We can represent the expression as a tree: +An example of a small arithmetic expression could be :rust:`10 + 20`, which +evaluates to :rust:`30`. We can represent the expression as a tree: .. raw:: html @@ -26,7 +26,7 @@ evaluates to ``30``. We can represent the expression as a tree: '--------' '--------' A bigger and more complex expression would be -``(10 * 9) + ((3 - 4) * 5)``, which evaluate to ``85``. We represent +:rust:`(10 * 9) + ((3 - 4) * 5)`, which evaluate to :rust:`85`. We represent this as a much bigger tree: .. raw:: html @@ -59,15 +59,15 @@ In code, we will represent the tree with two types: {{#include exercise.rs:Expression}} -The ``Box`` type here is a smart pointer, and will be covered in detail -later in the course. An expression can be "boxed" with ``Box::new`` as +The :rust:`Box` type here is a smart pointer, and will be covered in detail +later in the course. An expression can be "boxed" with :rust:`Box::new` as seen in the tests. To evaluate a boxed expression, use the deref -operator (``*``) to "unbox" it: ``eval(*boxed_expr)``. +operator (:rust:`*`) to "unbox" it: :rust:`eval(*boxed_expr)`. Copy and paste the code into the Rust playground, and begin implementing -``eval``. The final product should pass the tests. It may be helpful to -use ``todo!()`` and get the tests to pass one-by-one. You can also skip -a test temporarily with ``#[ignore]``: +:rust:`eval`. The final product should pass the tests. It may be helpful to +use :rust:`todo!()` and get the tests to pass one-by-one. You can also skip +a test temporarily with :rust:`#[ignore]`: .. code:: none diff --git a/courses/comprehensive_rust_training/090_methods_and_traits/01_methods.rst b/courses/comprehensive_rust_training/090_methods_and_traits/01_methods.rst index 38a9599ea..2871d40e3 100644 --- a/courses/comprehensive_rust_training/090_methods_and_traits/01_methods.rst +++ b/courses/comprehensive_rust_training/090_methods_and_traits/01_methods.rst @@ -7,9 +7,9 @@ Methods --------- Rust allows you to associate functions with your new types. You do this -with an ``impl`` block: +with an :rust:`impl` block: -.. code:: rust,editable +.. code:: rust #[derive(Debug)] struct CarRace { @@ -54,21 +54,21 @@ with an ``impl`` block: // race.add_lap(42); } -The ``self`` arguments specify the "receiver" - the object the method +The :rust:`self` arguments specify the "receiver" - the object the method acts on. There are several common receivers for a method: -- ``&self``: borrows the object from the caller using a shared and +- :rust:`&self`: borrows the object from the caller using a shared and immutable reference. The object can be used again afterwards. -- ``&mut self``: borrows the object from the caller using a unique and +- :rust:`&mut self`: borrows the object from the caller using a unique and mutable reference. The object can be used again afterwards. -- ``self``: takes ownership of the object and moves it away from the +- :rust:`self`: takes ownership of the object and moves it away from the caller. The method becomes the owner of the object. The object will be dropped (deallocated) when the method returns, unless its ownership is explicitly transmitted. Complete ownership does not automatically mean mutability. -- ``mut self``: same as above, but the method can mutate the object. +- :rust:`mut self`: same as above, but the method can mutate the object. - No receiver: this becomes a static method on the struct. Typically - used to create constructors which are called ``new`` by convention. + used to create constructors which are called :rust:`new` by convention. .. raw:: html @@ -82,25 +82,25 @@ Key Points: functions. - Methods are called on an instance of a type (such as a struct or - enum), the first parameter represents the instance as ``self``. + enum), the first parameter represents the instance as :rust:`self`. - Developers may choose to use methods to take advantage of method receiver syntax and to help keep them more organized. By using methods we can keep all the implementation code in one predictable place. -- Point out the use of the keyword ``self``, a method receiver. +- Point out the use of the keyword :rust:`self`, a method receiver. - - Show that it is an abbreviated term for ``self: Self`` and perhaps + - Show that it is an abbreviated term for :rust:`self: Self` and perhaps show how the struct name could also be used. - - Explain that ``Self`` is a type alias for the type the ``impl`` + - Explain that :rust:`Self` is a type alias for the type the :rust:`impl` block is in and can be used elsewhere in the block. - - Note how ``self`` is used like other structs and dot notation can + - Note how :rust:`self` is used like other structs and dot notation can be used to refer to individual fields. - - This might be a good time to demonstrate how the ``&self`` differs - from ``self`` by trying to run ``finish`` twice. - - Beyond variants on ``self``, there are also + - This might be a good time to demonstrate how the :rust:`&self` differs + from :rust:`self` by trying to run :rust:`finish` twice. + - Beyond variants on :rust:`self`, there are also :url:`special wrapper types ` - allowed to be receiver types, such as ``Box``. + allowed to be receiver types, such as :rust:`Box`. .. raw:: html diff --git a/courses/comprehensive_rust_training/090_methods_and_traits/02_traits.rst b/courses/comprehensive_rust_training/090_methods_and_traits/02_traits.rst index 576f78323..4ca3f1d7c 100644 --- a/courses/comprehensive_rust_training/090_methods_and_traits/02_traits.rst +++ b/courses/comprehensive_rust_training/090_methods_and_traits/02_traits.rst @@ -9,7 +9,7 @@ Traits Rust lets you abstract over types with traits. They're similar to interfaces: -.. code:: rust,editable +.. code:: rust trait Pet { /// Return a sentence from this pet. diff --git a/courses/comprehensive_rust_training/090_methods_and_traits/03_deriving.rst b/courses/comprehensive_rust_training/090_methods_and_traits/03_deriving.rst index 71637bfe2..4b62ac2cc 100644 --- a/courses/comprehensive_rust_training/090_methods_and_traits/03_deriving.rst +++ b/courses/comprehensive_rust_training/090_methods_and_traits/03_deriving.rst @@ -9,7 +9,7 @@ Deriving Supported traits can be automatically implemented for your custom types, as follows: -.. code:: rust,editable +.. code:: rust #[derive(Debug, Clone, Default)] struct Player { @@ -33,9 +33,9 @@ Details --------- Derivation is implemented with macros, and many crates provide useful -derive macros to add useful functionality. For example, ``serde`` can +derive macros to add useful functionality. For example, :rust:`serde` can derive serialization support for a struct using -``#[derive(Serialize)]``. +:rust:`#[derive(Serialize)]`. .. raw:: html diff --git a/courses/comprehensive_rust_training/090_methods_and_traits/04_exercise.rst b/courses/comprehensive_rust_training/090_methods_and_traits/04_exercise.rst index 9470d4fe0..b33499f1e 100644 --- a/courses/comprehensive_rust_training/090_methods_and_traits/04_exercise.rst +++ b/courses/comprehensive_rust_training/090_methods_and_traits/04_exercise.rst @@ -6,21 +6,21 @@ Exercise: Logger Trait Exercise: Logger Trait ------------------------ -Let's design a simple logging utility, using a trait ``Logger`` with a -``log`` method. Code which might log its progress can then take an -``&impl Logger``. In testing, this might put messages in the test +Let's design a simple logging utility, using a trait :rust:`Logger` with a +:rust:`log` method. Code which might log its progress can then take an +:rust:`&impl Logger`. In testing, this might put messages in the test logfile, while in a production build it would send messages to a log server. -However, the ``StderrLogger`` given below logs all messages, regardless -of verbosity. Your task is to write a ``VerbosityFilter`` type that will +However, the :rust:`StderrLogger` given below logs all messages, regardless +of verbosity. Your task is to write a :rust:`VerbosityFilter` type that will ignore messages above a maximum verbosity. This is a common pattern: a struct wrapping a trait implementation and implementing that same trait, adding behavior in the process. What other kinds of wrappers might be useful in a logging utility? -.. code:: rust,compile_fail +.. code:: rust {{#include exercise.rs:setup}} diff --git a/courses/comprehensive_rust_training/100_generics/01_generic_functions.rst b/courses/comprehensive_rust_training/100_generics/01_generic_functions.rst index c997d1650..d8af0e06e 100644 --- a/courses/comprehensive_rust_training/100_generics/01_generic_functions.rst +++ b/courses/comprehensive_rust_training/100_generics/01_generic_functions.rst @@ -10,7 +10,7 @@ Rust supports generics, which lets you abstract algorithms or data structures (such as sorting or a binary tree) over the types used or stored. -.. code:: rust,editable +.. code:: rust /// Pick `even` or `odd` depending on the value of `n`. fn pick(n: i32, even: T, odd: T) -> T { @@ -35,11 +35,11 @@ Details - Rust infers a type for T based on the types of the arguments and return value. -- In this example we only use the primitive types ``i32`` and ``&str`` - for ``T``, but we can use any type here, including user-defined +- In this example we only use the primitive types :rust:`i32` and :rust:`&str` + for :rust:`T`, but we can use any type here, including user-defined types: - .. code:: rust,ignore + .. code:: rust struct Foo { val: u8, @@ -49,8 +49,8 @@ Details - This is similar to C++ templates, but Rust partially compiles the generic function immediately, so that function must be valid for all - types matching the constraints. For example, try modifying ``pick`` - to return ``even + odd`` if ``n == 0``. Even if only the ``pick`` + types matching the constraints. For example, try modifying :rust:`pick` + to return :rust:`even + odd` if :rust:`n == 0`. Even if only the :rust:`pick` instantiation with integers is used, Rust still considers it invalid. C++ would let you do this. diff --git a/courses/comprehensive_rust_training/100_generics/02_generic_data.rst b/courses/comprehensive_rust_training/100_generics/02_generic_data.rst index e4f10203c..283394a08 100644 --- a/courses/comprehensive_rust_training/100_generics/02_generic_data.rst +++ b/courses/comprehensive_rust_training/100_generics/02_generic_data.rst @@ -8,7 +8,7 @@ Generic Data Types You can use generics to abstract over the concrete field type: -.. code:: rust,editable +.. code:: rust #[derive(Debug)] struct Point { @@ -39,21 +39,21 @@ You can use generics to abstract over the concrete field type: Details --------- -- *Q:* Why ``T`` is specified twice in ``impl Point {}``? Isn't +- *Q:* Why :rust:`T` is specified twice in :rust:`impl Point {}`? Isn't that redundant? - This is because it is a generic implementation section for generic type. They are independently generic. - - It means these methods are defined for any ``T``. - - It is possible to write ``impl Point { .. }``. + - It means these methods are defined for any :rust:`T`. + - It is possible to write :rust:`impl Point { .. }`. - - ``Point`` is still generic and you can use ``Point``, but + - :rust:`Point` is still generic and you can use :rust:`Point`, but methods in this block will only be available for - ``Point``. + :rust:`Point`. -- Try declaring a new variable ``let p = Point { x: 5, y: 10.0 };``. +- Try declaring a new variable :rust:`let p = Point { x: 5, y: 10.0 };`. Update the code to allow points that have elements of different - types, by using two type variables, e.g., ``T`` and ``U``. + types, by using two type variables, e.g., :rust:`T` and :rust:`U`. .. raw:: html diff --git a/courses/comprehensive_rust_training/100_generics/03_generic_traits.rst b/courses/comprehensive_rust_training/100_generics/03_generic_traits.rst index 2de9eb696..657151b20 100644 --- a/courses/comprehensive_rust_training/100_generics/03_generic_traits.rst +++ b/courses/comprehensive_rust_training/100_generics/03_generic_traits.rst @@ -9,7 +9,7 @@ Generic Traits Traits can also be generic, just like types and functions. A trait's parameters get concrete types when it is used. -.. code:: rust,editable +.. code:: rust #[derive(Debug)] struct Foo(String); @@ -38,13 +38,13 @@ parameters get concrete types when it is used. Details --------- -- The ``From`` trait will be covered later in the course, but its +- The :rust:`From` trait will be covered later in the course, but its :url:`definition in the std docs ` is simple. - Implementations of the trait do not need to cover all possible type - parameters. Here, ``Foo::from("hello")`` would not compile because - there is no ``From<&str>`` implementation for ``Foo``. + parameters. Here, :rust:`Foo::from("hello")` would not compile because + there is no :rust:`From<&str>` implementation for :rust:`Foo`. - Generic traits take types as "input", while associated types are a kind of "output" type. A trait can have multiple implementations for diff --git a/courses/comprehensive_rust_training/100_generics/04_trait_bounds.rst b/courses/comprehensive_rust_training/100_generics/04_trait_bounds.rst index 142d3c81b..47b6eda3d 100644 --- a/courses/comprehensive_rust_training/100_generics/04_trait_bounds.rst +++ b/courses/comprehensive_rust_training/100_generics/04_trait_bounds.rst @@ -9,9 +9,9 @@ Trait Bounds When working with generics, you often want to require the types to implement some trait, so that you can call this trait's methods. -You can do this with ``T: Trait``: +You can do this with :rust:`T: Trait`: -.. code:: rust,editable +.. code:: rust fn duplicate(a: T) -> (T, T) { (a.clone(), a.clone()) @@ -31,14 +31,14 @@ You can do this with ``T: Trait``: Details --------- -- Try making a ``NonCloneable`` and passing it to ``duplicate``. +- Try making a :rust:`NonCloneable` and passing it to :rust:`duplicate`. -- When multiple traits are necessary, use ``+`` to join them. +- When multiple traits are necessary, use :rust:`+` to join them. -- Show a ``where`` clause, students will encounter it when reading +- Show a :rust:`where` clause, students will encounter it when reading code. - .. code:: rust,ignore + .. code:: rust fn duplicate(a: T) -> (T, T) where @@ -51,11 +51,11 @@ Details - It has additional features making it more powerful. - If someone asks, the extra feature is that the type on the left - of ":" can be arbitrary, like ``Option``. + of ":" can be arbitrary, like :rust:`Option`. - Note that Rust does not (yet) support specialization. For example, - given the original ``duplicate``, it is invalid to add a specialized - ``duplicate(a: u32)``. + given the original :rust:`duplicate`, it is invalid to add a specialized + :rust:`duplicate(a: u32)`. .. raw:: html diff --git a/courses/comprehensive_rust_training/100_generics/05_impl_trait.rst b/courses/comprehensive_rust_training/100_generics/05_impl_trait.rst index d93da92dd..db1761b6b 100644 --- a/courses/comprehensive_rust_training/100_generics/05_impl_trait.rst +++ b/courses/comprehensive_rust_training/100_generics/05_impl_trait.rst @@ -1,15 +1,15 @@ ================ -``impl Trait`` +:rust:`impl Trait` ================ ---------------- -``impl Trait`` +:rust:`impl Trait` ---------------- -Similar to trait bounds, an ``impl Trait`` syntax can be used in +Similar to trait bounds, an :rust:`impl Trait` syntax can be used in function arguments and return values: -.. code:: rust,editable +.. code:: rust // Syntactic sugar for: // fn add_42_millions>(x: T) -> i32 { @@ -36,10 +36,10 @@ function arguments and return values: Details --------- -``impl Trait`` allows you to work with types which you cannot name. The -meaning of ``impl Trait`` is a bit different in the different positions. +:rust:`impl Trait` allows you to work with types which you cannot name. The +meaning of :rust:`impl Trait` is a bit different in the different positions. -- For a parameter, ``impl Trait`` is like an anonymous generic +- For a parameter, :rust:`impl Trait` is like an anonymous generic parameter with a trait bound. - For a return type, it means that the return type is some concrete @@ -48,14 +48,14 @@ meaning of ``impl Trait`` is a bit different in the different positions. API. Inference is hard in return position. A function returning - ``impl Foo`` picks the concrete type it returns, without writing it + :rust:`impl Foo` picks the concrete type it returns, without writing it out in the source. A function returning a generic type like - ``collect() -> B`` can return any type satisfying ``B``, and the + :rust:`collect() -> B` can return any type satisfying :rust:`B`, and the caller may need to choose one, such as with - ``let x: Vec<_> = foo.collect()`` or with the turbofish, - ``foo.collect::>()``. + :rust:`let x: Vec<_> = foo.collect()` or with the turbofish, + :rust:`foo.collect::>()`. -What is the type of ``debuggable``? Try ``let debuggable: () = ..`` to +What is the type of :rust:`debuggable`? Try :rust:`let debuggable: () = ..` to see what the error message shows. .. raw:: html diff --git a/courses/comprehensive_rust_training/100_generics/06_dyn_trait.rst b/courses/comprehensive_rust_training/100_generics/06_dyn_trait.rst index 661ae0fa9..c529d5c2f 100644 --- a/courses/comprehensive_rust_training/100_generics/06_dyn_trait.rst +++ b/courses/comprehensive_rust_training/100_generics/06_dyn_trait.rst @@ -1,15 +1,15 @@ =============== -``dyn Trait`` +:rust:`dyn Trait` =============== --------------- -``dyn Trait`` +:rust:`dyn Trait` --------------- In addition to using traits for static dispatch via generics, Rust also supports using them for type-erased, dynamic dispatch via trait objects: -.. code:: rust,editable +.. code:: rust struct Dog { name: String, @@ -62,33 +62,33 @@ supports using them for type-erased, dynamic dispatch via trait objects: Details --------- -- Generics, including ``impl Trait``, use monomorphization to create a +- Generics, including :rust:`impl Trait`, use monomorphization to create a specialized instance of the function for each different type that the generic is instantiated with. This means that calling a trait method from within a generic function still uses static dispatch, as the compiler has full type information and can resolve which type's trait implementation to use. -- When using ``dyn Trait``, it instead uses dynamic dispatch through a +- When using :rust:`dyn Trait`, it instead uses dynamic dispatch through a :url:`virtual method table ` - (vtable). This means that there's a single version of ``fn dynamic`` - that is used regardless of what type of ``Pet`` is passed in. + (vtable). This means that there's a single version of :rust:`fn dynamic` + that is used regardless of what type of :rust:`Pet` is passed in. -- When using ``dyn Trait``, the trait object needs to be behind some +- When using :rust:`dyn Trait`, the trait object needs to be behind some kind of indirection. In this case it's a reference, though smart - pointer types like ``Box`` can also be used (this will be + pointer types like :rust:`Box` can also be used (this will be demonstrated on day 3). -- At runtime, a ``&dyn Pet`` is represented as a "fat pointer", i.e. a +- At runtime, a :rust:`&dyn Pet` is represented as a "fat pointer", i.e. a pair of two pointers: One pointer points to the concrete object that - implements ``Pet``, and the other points to the vtable for the trait - implementation for that type. When calling the ``talk`` method on - ``&dyn Pet`` the compiler looks up the function pointer for ``talk`` + implements :rust:`Pet`, and the other points to the vtable for the trait + implementation for that type. When calling the :rust:`talk` method on + :rust:`&dyn Pet` the compiler looks up the function pointer for :rust:`talk` in the vtable and then invokes the function, passing the pointer to - the ``Dog`` or ``Cat`` into that function. The compiler doesn't need - to know the concrete type of the ``Pet`` in order to do this. + the :rust:`Dog` or :rust:`Cat` into that function. The compiler doesn't need + to know the concrete type of the :rust:`Pet` in order to do this. -- A ``dyn Trait`` is considered to be "type-erased", because we no +- A :rust:`dyn Trait` is considered to be "type-erased", because we no longer have compile-time knowledge of what the concrete type is. .. raw:: html diff --git a/courses/comprehensive_rust_training/100_generics/07_exercise.rst b/courses/comprehensive_rust_training/100_generics/07_exercise.rst index 2ce073e67..804ec88fc 100644 --- a/courses/comprehensive_rust_training/100_generics/07_exercise.rst +++ b/courses/comprehensive_rust_training/100_generics/07_exercise.rst @@ -1,17 +1,17 @@ =========================== -Exercise: Generic ``min`` +Exercise: Generic :rust:`min` =========================== --------------------------- -Exercise: Generic ``min`` +Exercise: Generic :rust:`min` --------------------------- -In this short exercise, you will implement a generic ``min`` function +In this short exercise, you will implement a generic :rust:`min` function that determines the minimum of two values, using the :url:`Ord ` trait. -.. code:: rust,compile_fail +.. code:: rust use std::cmp::Ordering; diff --git a/courses/comprehensive_rust_training/110_std_types/01_std.rst b/courses/comprehensive_rust_training/110_std_types/01_std.rst index 2ca301da9..5901ea3ae 100644 --- a/courses/comprehensive_rust_training/110_std_types/01_std.rst +++ b/courses/comprehensive_rust_training/110_std_types/01_std.rst @@ -8,15 +8,15 @@ Standard Library Rust comes with a standard library which helps establish a set of common types used by Rust libraries and programs. This way, two libraries can -work together smoothly because they both use the same ``String`` type. +work together smoothly because they both use the same :rust:`String` type. -In fact, Rust contains several layers of the Standard Library: ``core``, -``alloc`` and ``std``. +In fact, Rust contains several layers of the Standard Library: :rust:`core`, +:rust:`alloc` and :rust:`std`. -- ``core`` includes the most basic types and functions that don't - depend on ``libc``, allocator or even the presence of an operating +- :rust:`core` includes the most basic types and functions that don't + depend on :rust:`libc`, allocator or even the presence of an operating system. -- ``alloc`` includes types which require a global heap allocator, such - as ``Vec``, ``Box`` and ``Arc``. -- Embedded Rust applications often only use ``core``, and sometimes - ``alloc``. +- :rust:`alloc` includes types which require a global heap allocator, such + as :rust:`Vec`, :rust:`Box` and :rust:`Arc`. +- Embedded Rust applications often only use :rust:`core`, and sometimes + :rust:`alloc`. diff --git a/courses/comprehensive_rust_training/110_std_types/02_docs.rst b/courses/comprehensive_rust_training/110_std_types/02_docs.rst index aeca4d1ab..04af9bffc 100644 --- a/courses/comprehensive_rust_training/110_std_types/02_docs.rst +++ b/courses/comprehensive_rust_training/110_std_types/02_docs.rst @@ -17,11 +17,11 @@ Rust comes with extensive documentation. For example: or :url:`BinaryHeap `. -Use ``rustup doc --std`` or https://std.rs to view the documentation. +Use :rust:`rustup doc --std` or https://std.rs to view the documentation. In fact, you can document your own code: -.. code:: rust,editable +.. code:: rust /// Determine whether the first argument is divisible by the second argument. /// @@ -40,9 +40,9 @@ tool. It is idiomatic to document all public items in an API using this pattern. To document an item from inside the item (such as inside a module), use -``//!`` or ``/*! .. */``, called "inner doc comments": +:rust:`//!` or :rust:`/*! .. */`, called "inner doc comments": -.. code:: rust,editable +.. code:: rust //! This module contains functionality relating to divisibility of integers. @@ -52,7 +52,7 @@ To document an item from inside the item (such as inside a module), use Details --------- -- Show students the generated docs for the ``rand`` crate at +- Show students the generated docs for the :rust:`rand` crate at https://docs.rs/rand. .. raw:: html diff --git a/courses/comprehensive_rust_training/110_std_types/03_option.rst b/courses/comprehensive_rust_training/110_std_types/03_option.rst index bbf56b08c..ef233be77 100644 --- a/courses/comprehensive_rust_training/110_std_types/03_option.rst +++ b/courses/comprehensive_rust_training/110_std_types/03_option.rst @@ -6,12 +6,12 @@ Option Option -------- -We have already seen some use of ``Option``. It stores either a value -of type ``T`` or nothing. For example, +We have already seen some use of :rust:`Option`. It stores either a value +of type :rust:`T` or nothing. For example, :url:`String::find ` -returns an ``Option``. +returns an :rust:`Option`. -.. code:: rust,editable,should_panic +.. code:: rust fn main() { let name = "Alexander the Great"; @@ -29,21 +29,21 @@ returns an ``Option``. Details --------- -- ``Option`` is widely used, not just in the standard library. -- ``unwrap`` will return the value in an ``Option``, or panic. - ``expect`` is similar but takes an error message. +- :rust:`Option` is widely used, not just in the standard library. +- :rust:`unwrap` will return the value in an :rust:`Option`, or panic. + :rust:`expect` is similar but takes an error message. - You can panic on None, but you can't "accidentally" forget to check for None. - - It's common to ``unwrap``/``expect`` all over the place when + - It's common to :rust:`unwrap`/:rust:`expect` all over the place when hacking something together, but production code typically handles - ``None`` in a nicer fashion. + :rust:`None` in a nicer fashion. -- The "niche optimization" means that ``Option`` often has the same - size in memory as ``T``, if there is some representation that is not +- The "niche optimization" means that :rust:`Option` often has the same + size in memory as :rust:`T`, if there is some representation that is not a valid value of T. For example, a reference cannot be NULL, so - ``Option<&T>`` automatically uses NULL to represent the ``None`` - variant, and thus can be stored in the same memory as ``&T``. + :rust:`Option<&T>` automatically uses NULL to represent the :rust:`None` + variant, and thus can be stored in the same memory as :rust:`&T`. .. raw:: html diff --git a/courses/comprehensive_rust_training/110_std_types/04_result.rst b/courses/comprehensive_rust_training/110_std_types/04_result.rst index ab5840e70..89ab12959 100644 --- a/courses/comprehensive_rust_training/110_std_types/04_result.rst +++ b/courses/comprehensive_rust_training/110_std_types/04_result.rst @@ -6,12 +6,12 @@ Result Result -------- -``Result`` is similar to ``Option``, but indicates the success or +:rust:`Result` is similar to :rust:`Option`, but indicates the success or failure of an operation, each with a different enum variant. It is -generic: ``Result`` where ``T`` is used in the ``Ok`` variant and -``E`` appears in the ``Err`` variant. +generic: :rust:`Result` where :rust:`T` is used in the :rust:`Ok` variant and +:rust:`E` appears in the :rust:`Err` variant. -.. code:: rust,editable +.. code:: rust use std::fs::File; use std::io::Read; @@ -39,15 +39,15 @@ generic: ``Result`` where ``T`` is used in the ``Ok`` variant and Details --------- -- As with ``Option``, the successful value sits inside of ``Result``, +- As with :rust:`Option`, the successful value sits inside of :rust:`Result`, forcing the developer to explicitly extract it. This encourages error checking. In the case where an error should never happen, - ``unwrap()`` or ``expect()`` can be called, and this is a signal of + :rust:`unwrap()` or :rust:`expect()` can be called, and this is a signal of the developer intent too. -- ``Result`` documentation is a recommended read. Not during the +- :rust:`Result` documentation is a recommended read. Not during the course, but it is worth mentioning. It contains a lot of convenience methods and functions that help functional-style programming. -- ``Result`` is the standard type to implement error handling as we +- :rust:`Result` is the standard type to implement error handling as we will see on Day 4. .. raw:: html diff --git a/courses/comprehensive_rust_training/110_std_types/05_string.rst b/courses/comprehensive_rust_training/110_std_types/05_string.rst index a64dda94b..63e67f91c 100644 --- a/courses/comprehensive_rust_training/110_std_types/05_string.rst +++ b/courses/comprehensive_rust_training/110_std_types/05_string.rst @@ -9,7 +9,7 @@ String :url:`String ` is a growable UTF-8 encoded string: -.. code:: rust,editable +.. code:: rust fn main() { let mut s1 = String::new(); @@ -25,9 +25,9 @@ is a growable UTF-8 encoded string: println!("s3: len = {}, number of chars = {}", s3.len(), s3.chars().count()); } -``String`` implements +:rust:`String` implements :url:`Deref `, -which means that you can call all ``str`` methods on a ``String``. +which means that you can call all :rust:`str` methods on a :rust:`String`. .. raw:: html @@ -35,41 +35,41 @@ which means that you can call all ``str`` methods on a ``String``. Details --------- -- ``String::new`` returns a new empty string, use - ``String::with_capacity`` when you know how much data you want to +- :rust:`String::new` returns a new empty string, use + :rust:`String::with_capacity` when you know how much data you want to push to the string. -- ``String::len`` returns the size of the ``String`` in bytes (which +- :rust:`String::len` returns the size of the :rust:`String` in bytes (which can be different from its length in characters). -- ``String::chars`` returns an iterator over the actual characters. - Note that a ``char`` can be different from what a human will consider +- :rust:`String::chars` returns an iterator over the actual characters. + Note that a :rust:`char` can be different from what a human will consider a "character" due to :url:`grapheme clusters `. - When people refer to strings they could either be talking about - ``&str`` or ``String``. -- When a type implements ``Deref``, the compiler will let - you transparently call methods from ``T``. + :rust:`&str` or :rust:`String`. +- When a type implements :rust:`Deref`, the compiler will let + you transparently call methods from :rust:`T`. - - We haven't discussed the ``Deref`` trait yet, so at this point + - We haven't discussed the :rust:`Deref` trait yet, so at this point this mostly explains the structure of the sidebar in the documentation. - - ``String`` implements ``Deref`` which transparently - gives it access to ``str``\ 's methods. - - Write and compare ``let s3 = s1.deref();`` and ``let s3 = &*s1;``. + - :rust:`String` implements :rust:`Deref` which transparently + gives it access to :rust:`str`\ 's methods. + - Write and compare :rust:`let s3 = s1.deref();` and :rust:`let s3 = &*s1;`. -- ``String`` is implemented as a wrapper around a vector of bytes, many +- :rust:`String` is implemented as a wrapper around a vector of bytes, many of the operations you see supported on vectors are also supported on - ``String``, but with some extra guarantees. -- Compare the different ways to index a ``String``: + :rust:`String`, but with some extra guarantees. +- Compare the different ways to index a :rust:`String`: - - To a character by using ``s3.chars().nth(i).unwrap()`` where ``i`` + - To a character by using :rust:`s3.chars().nth(i).unwrap()` where :rust:`i` is in-bound, out-of-bounds. - - To a substring by using ``s3[0..4]``, where that slice is on + - To a substring by using :rust:`s3[0..4]`, where that slice is on character boundaries or not. - Many types can be converted to a string with the :url:`to_string ` method. This trait is automatically implemented for all types that - implement ``Display``, so anything that can be formatted can also be + implement :rust:`Display`, so anything that can be formatted can also be converted to a string. .. raw:: html diff --git a/courses/comprehensive_rust_training/110_std_types/06_vec.rst b/courses/comprehensive_rust_training/110_std_types/06_vec.rst index 5bcc46dc5..83c1e361f 100644 --- a/courses/comprehensive_rust_training/110_std_types/06_vec.rst +++ b/courses/comprehensive_rust_training/110_std_types/06_vec.rst @@ -1,15 +1,15 @@ ========= -``Vec`` +:rust:`Vec` ========= --------- -``Vec`` +:rust:`Vec` --------- :url:`Vec ` is the standard resizable heap-allocated buffer: -.. code:: rust,editable +.. code:: rust fn main() { let mut v1 = Vec::new(); @@ -33,9 +33,9 @@ standard resizable heap-allocated buffer: println!("{v3:?}"); } -``Vec`` implements +:rust:`Vec` implements :url:`Deref `, -which means that you can call slice methods on a ``Vec``. +which means that you can call slice methods on a :rust:`Vec`. .. raw:: html @@ -43,20 +43,20 @@ which means that you can call slice methods on a ``Vec``. Details --------- -- ``Vec`` is a type of collection, along with ``String`` and - ``HashMap``. The data it contains is stored on the heap. This means +- :rust:`Vec` is a type of collection, along with :rust:`String` and + :rust:`HashMap`. The data it contains is stored on the heap. This means the amount of data doesn't need to be known at compile time. It can grow or shrink at runtime. -- Notice how ``Vec`` is a generic type too, but you don't have to - specify ``T`` explicitly. As always with Rust type inference, the - ``T`` was established during the first ``push`` call. -- ``vec![...]`` is a canonical macro to use instead of ``Vec::new()`` +- Notice how :rust:`Vec` is a generic type too, but you don't have to + specify :rust:`T` explicitly. As always with Rust type inference, the + :rust:`T` was established during the first :rust:`push` call. +- :rust:`vec![...]` is a canonical macro to use instead of :rust:`Vec::new()` and it supports adding initial elements to the vector. -- To index the vector you use ``[`` ``]``, but they will panic if out - of bounds. Alternatively, using ``get`` will return an ``Option``. - The ``pop`` function will remove the last element. +- To index the vector you use :rust:`[` :rust:`]`, but they will panic if out + of bounds. Alternatively, using :rust:`get` will return an :rust:`Option`. + The :rust:`pop` function will remove the last element. - Slices are covered on day 3. For now, students only need to know that - a value of type ``Vec`` gives access to all of the documented slice + a value of type :rust:`Vec` gives access to all of the documented slice methods, too. .. raw:: html diff --git a/courses/comprehensive_rust_training/110_std_types/07_hashmap.rst b/courses/comprehensive_rust_training/110_std_types/07_hashmap.rst index c933bd828..b172e0de3 100644 --- a/courses/comprehensive_rust_training/110_std_types/07_hashmap.rst +++ b/courses/comprehensive_rust_training/110_std_types/07_hashmap.rst @@ -1,14 +1,14 @@ ============= -``HashMap`` +:rust:`HashMap` ============= ------------- -``HashMap`` +:rust:`HashMap` ------------- Standard hash map with protection against HashDoS attacks: -.. code:: rust,editable +.. code:: rust use std::collections::HashMap; @@ -47,7 +47,7 @@ Standard hash map with protection against HashDoS attacks: Details --------- -- ``HashMap`` is not defined in the prelude and needs to be brought +- :rust:`HashMap` is not defined in the prelude and needs to be brought into scope. - Try the following lines of code. The first line will see if a book is @@ -55,7 +55,7 @@ Details line will insert the alternative value in the hashmap if the book is not found. - .. code:: rust,ignore + .. code:: rust let pc1 = page_counts .get("Harry Potter and the Sorcerer's Stone") @@ -64,7 +64,7 @@ Details .entry("The Hunger Games") .or_insert(374); -- Unlike ``vec!``, there is unfortunately no standard ``hashmap!`` +- Unlike :rust:`vec!`, there is unfortunately no standard :rust:`hashmap!` macro. - Although, since Rust 1.56, HashMap implements @@ -72,20 +72,20 @@ Details which allows us to easily initialize a hash map from a literal array: - .. code:: rust,ignore + .. code:: rust let page_counts = HashMap::from([ ("Harry Potter and the Sorcerer's Stone".to_string(), 336), ("The Hunger Games".to_string(), 374), ]); -- Alternatively HashMap can be built from any ``Iterator`` which yields +- Alternatively HashMap can be built from any :rust:`Iterator` which yields key-value tuples. - This type has several "method-specific" return types, such as - ``std::collections::hash_map::Keys``. These types often appear in + :rust:`std::collections::hash_map::Keys`. These types often appear in searches of the Rust docs. Show students the docs for this type, and - the helpful link back to the ``keys`` method. + the helpful link back to the :rust:`keys` method. .. raw:: html diff --git a/courses/comprehensive_rust_training/110_std_types/08_exercise.rst b/courses/comprehensive_rust_training/110_std_types/08_exercise.rst index a383f7b92..ab1ea2b1c 100644 --- a/courses/comprehensive_rust_training/110_std_types/08_exercise.rst +++ b/courses/comprehensive_rust_training/110_std_types/08_exercise.rst @@ -12,16 +12,16 @@ generic. It uses a to keep track of which values have been seen and how many times each one has appeared. -The initial version of ``Counter`` is hard coded to only work for -``u32`` values. Make the struct and its methods generic over the type of -value being tracked, that way ``Counter`` can track any type of value. +The initial version of :rust:`Counter` is hard coded to only work for +:rust:`u32` values. Make the struct and its methods generic over the type of +value being tracked, that way :rust:`Counter` can track any type of value. If you finish early, try using the :url:`entry ` method to halve the number of hash lookups required to implement the -``count`` method. +:rust:`count` method. -.. code:: rust,compile_fail,editable +.. code:: rust use std::collections::HashMap; diff --git a/courses/comprehensive_rust_training/120_std_traits/01_comparisons.rst b/courses/comprehensive_rust_training/120_std_traits/01_comparisons.rst index 0c1167a3a..9b22ab1db 100644 --- a/courses/comprehensive_rust_training/120_std_traits/01_comparisons.rst +++ b/courses/comprehensive_rust_training/120_std_traits/01_comparisons.rst @@ -10,14 +10,14 @@ These traits support comparisons between values. All traits can be derived for types containing fields that implement these traits. -------------------------- -``PartialEq`` and ``Eq`` +:rust:`PartialEq` and :rust:`Eq` -------------------------- -``PartialEq`` is a partial equivalence relation, with required method -``eq`` and provided method ``ne``. The ``==`` and ``!=`` operators will +:rust:`PartialEq` is a partial equivalence relation, with required method +:rust:`eq` and provided method :rust:`ne`. The :rust:`==` and :rust:`!=` operators will call these methods. -.. code:: rust,editable +.. code:: rust struct Key { id: u32, @@ -29,19 +29,19 @@ call these methods. } } -``Eq`` is a full equivalence relation (reflexive, symmetric, and -transitive) and implies ``PartialEq``. Functions that require full -equivalence will use ``Eq`` as a trait bound. +:rust:`Eq` is a full equivalence relation (reflexive, symmetric, and +transitive) and implies :rust:`PartialEq`. Functions that require full +equivalence will use :rust:`Eq` as a trait bound. ---------------------------- -``PartialOrd`` and ``Ord`` +:rust:`PartialOrd` and :rust:`Ord` ---------------------------- -``PartialOrd`` defines a partial ordering, with a ``partial_cmp`` -method. It is used to implement the ``<``, ``<=``, ``>=``, and ``>`` +:rust:`PartialOrd` defines a partial ordering, with a :rust:`partial_cmp` +method. It is used to implement the :rust:`<`, :rust:`<=`, :rust:`>=`, and :rust:`>` operators. -.. code:: rust,editable +.. code:: rust use std::cmp::Ordering; #[derive(Eq, PartialEq)] @@ -58,7 +58,7 @@ operators. } } -``Ord`` is a total ordering, with ``cmp`` returning ``Ordering``. +:rust:`Ord` is a total ordering, with :rust:`cmp` returning :rust:`Ordering`. .. raw:: html @@ -66,10 +66,10 @@ operators. Details --------- -``PartialEq`` can be implemented between different types, but ``Eq`` +:rust:`PartialEq` can be implemented between different types, but :rust:`Eq` cannot, because it is reflexive: -.. code:: rust,editable +.. code:: rust struct Key { id: u32, diff --git a/courses/comprehensive_rust_training/120_std_traits/02_operators.rst b/courses/comprehensive_rust_training/120_std_traits/02_operators.rst index aa0e63cf8..58754f411 100644 --- a/courses/comprehensive_rust_training/120_std_traits/02_operators.rst +++ b/courses/comprehensive_rust_training/120_std_traits/02_operators.rst @@ -9,7 +9,7 @@ Operators Operator overloading is implemented via traits in :url:`std::ops `: -.. code:: rust,editable +.. code:: rust #[derive(Debug, Copy, Clone)] struct Point { @@ -39,28 +39,28 @@ Details Discussion points: -- You could implement ``Add`` for ``&Point``. In which situations is +- You could implement :rust:`Add` for :rust:`&Point`. In which situations is that useful? - - Answer: ``Add:add`` consumes ``self``. If type ``T`` for which you - are overloading the operator is not ``Copy``, you should consider - overloading the operator for ``&T`` as well. This avoids + - Answer: :rust:`Add:add` consumes :rust:`self`. If type :rust:`T` for which you + are overloading the operator is not :rust:`Copy`, you should consider + overloading the operator for :rust:`&T` as well. This avoids unnecessary cloning on the call site. -- Why is ``Output`` an associated type? Could it be made a type +- Why is :rust:`Output` an associated type? Could it be made a type parameter of the method? - Short answer: Function type parameters are controlled by the - caller, but associated types (like ``Output``) are controlled by + caller, but associated types (like :rust:`Output`) are controlled by the implementer of a trait. -- You could implement ``Add`` for two different types, e.g. - ``impl Add<(i32, i32)> for Point`` would add a tuple to a ``Point``. +- You could implement :rust:`Add` for two different types, e.g. + :rust:`impl Add<(i32, i32)> for Point` would add a tuple to a :rust:`Point`. -The ``Not`` trait (``!`` operator) is notable because it does not +The :rust:`Not` trait (:rust:`!` operator) is notable because it does not "boolify" like the same operator in C-family languages; instead, for integer types it negates each bit of the number, which arithmetically is -equivalent to subtracting it from -1: ``!5 == -6``. +equivalent to subtracting it from -1: :rust:`!5 == -6`. .. raw:: html diff --git a/courses/comprehensive_rust_training/120_std_traits/03_from_and_into.rst b/courses/comprehensive_rust_training/120_std_traits/03_from_and_into.rst index 0ac85bf70..5acf328cd 100644 --- a/courses/comprehensive_rust_training/120_std_traits/03_from_and_into.rst +++ b/courses/comprehensive_rust_training/120_std_traits/03_from_and_into.rst @@ -1,18 +1,18 @@ ======================= -``From`` and ``Into`` +:rust:`From` and :rust:`Into` ======================= ----------------------- -``From`` and ``Into`` +:rust:`From` and :rust:`Into` ----------------------- Types implement :url:`From ` and :url:`Into ` to -facilitate type conversions. Unlike ``as``, these traits correspond to +facilitate type conversions. Unlike :rust:`as`, these traits correspond to lossless, infallible conversions. -.. code:: rust,editable +.. code:: rust fn main() { let s = String::from("hello"); @@ -27,7 +27,7 @@ automatically implemented when :url:`From ` is implemented: -.. code:: rust,editable +.. code:: rust fn main() { let s: String = "hello".into(); @@ -43,12 +43,12 @@ implemented: Details --------- -- That's why it is common to only implement ``From``, as your type will - get ``Into`` implementation too. +- That's why it is common to only implement :rust:`From`, as your type will + get :rust:`Into` implementation too. - When declaring a function argument input type like "anything that can - be converted into a ``String``", the rule is opposite, you should use - ``Into``. Your function will accept types that implement ``From`` and - those that *only* implement ``Into``. + be converted into a :rust:`String`", the rule is opposite, you should use + :rust:`Into`. Your function will accept types that implement :rust:`From` and + those that *only* implement :rust:`Into`. .. raw:: html diff --git a/courses/comprehensive_rust_training/120_std_traits/04_casting.rst b/courses/comprehensive_rust_training/120_std_traits/04_casting.rst index 010951b57..5a5541468 100644 --- a/courses/comprehensive_rust_training/120_std_traits/04_casting.rst +++ b/courses/comprehensive_rust_training/120_std_traits/04_casting.rst @@ -7,9 +7,9 @@ Casting --------- Rust has no *implicit* type conversions, but does support explicit casts -with ``as``. These generally follow C semantics where those are defined. +with :rust:`as`. These generally follow C semantics where those are defined. -.. code:: rust,editable +.. code:: rust fn main() { let value: i64 = 1000; @@ -18,20 +18,20 @@ with ``as``. These generally follow C semantics where those are defined. println!("as u8: {}", value as u8); } -The results of ``as`` are *always* defined in Rust and consistent across +The results of :rust:`as` are *always* defined in Rust and consistent across platforms. This might not match your intuition for changing sign or casting to a smaller type - check the docs, and comment for clarity. -Casting with ``as`` is a relatively sharp tool that is easy to use +Casting with :rust:`as` is a relatively sharp tool that is easy to use incorrectly, and can be a source of subtle bugs as future maintenance work changes the types that are used or the ranges of values in types. Casts are best used only when the intent is to indicate unconditional -truncation (e.g. selecting the bottom 32 bits of a ``u64`` with -``as u32``, regardless of what was in the high bits). +truncation (e.g. selecting the bottom 32 bits of a :rust:`u64` with +:rust:`as u32`, regardless of what was in the high bits). -For infallible casts (e.g. ``u32`` to ``u64``), prefer using ``From`` or -``Into`` over ``as`` to confirm that the cast is in fact infallible. For -fallible casts, ``TryFrom`` and ``TryInto`` are available when you want +For infallible casts (e.g. :rust:`u32` to :rust:`u64`), prefer using :rust:`From` or +:rust:`Into` over :rust:`as` to confirm that the cast is in fact infallible. For +fallible casts, :rust:`TryFrom` and :rust:`TryInto` are available when you want to handle casts that fit differently from those that don't. .. raw:: html @@ -42,11 +42,11 @@ Details Consider taking a break after this slide. -``as`` is similar to a C++ static cast. Use of ``as`` in cases where +:rust:`as` is similar to a C++ static cast. Use of :rust:`as` in cases where data might be lost is generally discouraged, or at least deserves an explanatory comment. -This is common in casting integers to ``usize`` for use as an index. +This is common in casting integers to :rust:`usize` for use as an index. .. raw:: html diff --git a/courses/comprehensive_rust_training/120_std_traits/05_read_and_write.rst b/courses/comprehensive_rust_training/120_std_traits/05_read_and_write.rst index 1a4b58504..7a5294774 100644 --- a/courses/comprehensive_rust_training/120_std_traits/05_read_and_write.rst +++ b/courses/comprehensive_rust_training/120_std_traits/05_read_and_write.rst @@ -1,17 +1,17 @@ ======================== -``Read`` and ``Write`` +:rust:`Read` and :rust:`Write` ======================== ------------------------ -``Read`` and ``Write`` +:rust:`Read` and :rust:`Write` ------------------------ Using :url:`Read ` and :url:`BufRead `, -you can abstract over ``u8`` sources: +you can abstract over :rust:`u8` sources: -.. code:: rust,editable +.. code:: rust use std::io::{BufRead, BufReader, Read, Result}; @@ -31,9 +31,9 @@ you can abstract over ``u8`` sources: Similarly, :url:`Write ` lets -you abstract over ``u8`` sinks: +you abstract over :rust:`u8` sinks: -.. code:: rust,editable +.. code:: rust use std::io::{Result, Write}; diff --git a/courses/comprehensive_rust_training/120_std_traits/06_default.rst b/courses/comprehensive_rust_training/120_std_traits/06_default.rst index 01c23f312..dea5fb8a6 100644 --- a/courses/comprehensive_rust_training/120_std_traits/06_default.rst +++ b/courses/comprehensive_rust_training/120_std_traits/06_default.rst @@ -1,15 +1,15 @@ ======================= -The ``Default`` Trait +The :rust:`Default` Trait ======================= ----------------------- -The ``Default`` Trait +The :rust:`Default` Trait ----------------------- :url:`Default ` trait produces a default value for a type. -.. code:: rust,editable +.. code:: rust #[derive(Debug, Default)] struct Derived { @@ -46,18 +46,18 @@ Details --------- - It can be implemented directly or it can be derived via - ``#[derive(Default)]``. + :rust:`#[derive(Default)]`. - A derived implementation will produce a value where all fields are set to their default values. - - This means all types in the struct must implement ``Default`` too. + - This means all types in the struct must implement :rust:`Default` too. -- Standard Rust types often implement ``Default`` with reasonable - values (e.g. ``0``, ``""``, etc). +- Standard Rust types often implement :rust:`Default` with reasonable + values (e.g. :rust:`0`, :rust:`""`, etc). - The partial struct initialization works nicely with default. - The Rust standard library is aware that types can implement - ``Default`` and provides convenience methods that use it. -- The ``..`` syntax is called + :rust:`Default` and provides convenience methods that use it. +- The :rust:`..` syntax is called :url:`struct update syntax `. .. raw:: html diff --git a/courses/comprehensive_rust_training/120_std_traits/07_closures.rst b/courses/comprehensive_rust_training/120_std_traits/07_closures.rst index 0f423cd07..91e7c1265 100644 --- a/courses/comprehensive_rust_training/120_std_traits/07_closures.rst +++ b/courses/comprehensive_rust_training/120_std_traits/07_closures.rst @@ -13,7 +13,7 @@ However, they implement special :url:`FnOnce ` traits: -.. code:: rust,editable +.. code:: rust fn apply_and_log(func: impl FnOnce(i32) -> i32, func_name: &str, input: i32) { println!("Calling {func_name}({input}): {}", func(input)) @@ -43,41 +43,41 @@ traits: Details --------- -An ``Fn`` (e.g. ``add_3``) neither consumes nor mutates captured values. +An :rust:`Fn` (e.g. :rust:`add_3`) neither consumes nor mutates captured values. It can be called needing only a shared reference to the closure, which means the closure can be executed repeatedly and even concurrently. -An ``FnMut`` (e.g. ``accumulate``) might mutate captured values. The +An :rust:`FnMut` (e.g. :rust:`accumulate`) might mutate captured values. The closure object is accessed via exclusive reference, so it can be called repeatedly but not concurrently. -If you have an ``FnOnce`` (e.g. ``multiply_sum``), you may only call it +If you have an :rust:`FnOnce` (e.g. :rust:`multiply_sum`), you may only call it once. Doing so consumes the closure and any values captured by move. -``FnMut`` is a subtype of ``FnOnce``. ``Fn`` is a subtype of ``FnMut`` -and ``FnOnce``. I.e. you can use an ``FnMut`` wherever an ``FnOnce`` is -called for, and you can use an ``Fn`` wherever an ``FnMut`` or -``FnOnce`` is called for. +:rust:`FnMut` is a subtype of :rust:`FnOnce`. :rust:`Fn` is a subtype of :rust:`FnMut` +and :rust:`FnOnce`. I.e. you can use an :rust:`FnMut` wherever an :rust:`FnOnce` is +called for, and you can use an :rust:`Fn` wherever an :rust:`FnMut` or +:rust:`FnOnce` is called for. When you define a function that takes a closure, you should take -``FnOnce`` if you can (i.e. you call it once), or ``FnMut`` else, and -last ``Fn``. This allows the most flexibility for the caller. +:rust:`FnOnce` if you can (i.e. you call it once), or :rust:`FnMut` else, and +last :rust:`Fn`. This allows the most flexibility for the caller. In contrast, when you have a closure, the most flexible you can have is -``Fn`` (which can be passed to a consumer of any of the 3 closure -traits), then ``FnMut``, and lastly ``FnOnce``. +:rust:`Fn` (which can be passed to a consumer of any of the 3 closure +traits), then :rust:`FnMut`, and lastly :rust:`FnOnce`. -The compiler also infers ``Copy`` (e.g. for ``add_3``) and ``Clone`` -(e.g. ``multiply_sum``), depending on what the closure captures. -Function pointers (references to ``fn`` items) implement ``Copy`` and -``Fn``. +The compiler also infers :rust:`Copy` (e.g. for :rust:`add_3`) and :rust:`Clone` +(e.g. :rust:`multiply_sum`), depending on what the closure captures. +Function pointers (references to :rust:`fn` items) implement :rust:`Copy` and +:rust:`Fn`. By default, closures will capture each variable from an outer scope by the least demanding form of access they can (by shared reference if -possible, then exclusive reference, then by move). The ``move`` keyword +possible, then exclusive reference, then by move). The :rust:`move` keyword forces capture by value. -.. code:: rust,editable +.. code:: rust fn make_greeter(prefix: String) -> impl Fn(&str) { return move |name| println!("{} {}", prefix, name); diff --git a/courses/comprehensive_rust_training/120_std_traits/08_exercise.rst b/courses/comprehensive_rust_training/120_std_traits/08_exercise.rst index 8179c86c9..2eb120c38 100644 --- a/courses/comprehensive_rust_training/120_std_traits/08_exercise.rst +++ b/courses/comprehensive_rust_training/120_std_traits/08_exercise.rst @@ -11,7 +11,7 @@ In this example, you will implement the classic playground, and implement the missing bits. Only rotate ASCII alphabetic characters, to ensure the result is still valid UTF-8. -.. code:: rust,compile_fail +.. code:: rust {{#include exercise.rs:head }} @@ -19,5 +19,5 @@ characters, to ensure the result is still valid UTF-8. {{#include exercise.rs:main }} -What happens if you chain two ``RotDecoder`` instances together, each +What happens if you chain two :rust:`RotDecoder` instances together, each rotating by 13 characters? diff --git a/courses/comprehensive_rust_training/130_memory_management/01_review.rst b/courses/comprehensive_rust_training/130_memory_management/01_review.rst index c38397a64..8a55efc10 100644 --- a/courses/comprehensive_rust_training/130_memory_management/01_review.rst +++ b/courses/comprehensive_rust_training/130_memory_management/01_review.rst @@ -25,10 +25,10 @@ Programs allocate memory in two ways: Example --------- -Creating a ``String`` puts fixed-sized metadata on the stack and +Creating a :rust:`String` puts fixed-sized metadata on the stack and dynamically sized data, the actual string, on the heap: -.. code:: rust,editable +.. code:: rust fn main() { let s1 = String::from("Hello"); @@ -54,7 +54,7 @@ dynamically sized data, the actual string, on the heap: Details --------- -- Mention that a ``String`` is backed by a ``Vec``, so it has a +- Mention that a :rust:`String` is backed by a :rust:`Vec`, so it has a capacity and length and can grow if mutable via reallocation on the heap. @@ -68,10 +68,10 @@ Details More to Explore ----------------- -We can inspect the memory layout with ``unsafe`` Rust. However, you +We can inspect the memory layout with :rust:`unsafe` Rust. However, you should point out that this is rightfully unsafe! -.. code:: rust,editable +.. code:: rust fn main() { let mut s1 = String::from("Hello"); diff --git a/courses/comprehensive_rust_training/130_memory_management/02_approaches.rst b/courses/comprehensive_rust_training/130_memory_management/02_approaches.rst index 9384d7550..67a2db382 100644 --- a/courses/comprehensive_rust_training/130_memory_management/02_approaches.rst +++ b/courses/comprehensive_rust_training/130_memory_management/02_approaches.rst @@ -39,12 +39,12 @@ Details This slide is intended to help students coming from other languages to put Rust in context. -- C must manage heap manually with ``malloc`` and ``free``. Common - errors include forgetting to call ``free``, calling it multiple times +- C must manage heap manually with :rust:`malloc` and :rust:`free`. Common + errors include forgetting to call :rust:`free`, calling it multiple times for the same pointer, or dereferencing a pointer after the memory it points to has been freed. -- C++ has tools like smart pointers (``unique_ptr``, ``shared_ptr``) +- C++ has tools like smart pointers (:rust:`unique_ptr`, :rust:`shared_ptr`) that take advantage of language guarantees about calling destructors to ensure memory is freed when a function returns. It is still quite easy to mis-use these tools and create similar bugs to C. diff --git a/courses/comprehensive_rust_training/130_memory_management/03_ownership.rst b/courses/comprehensive_rust_training/130_memory_management/03_ownership.rst index a196d4dae..7cbe61e8d 100644 --- a/courses/comprehensive_rust_training/130_memory_management/03_ownership.rst +++ b/courses/comprehensive_rust_training/130_memory_management/03_ownership.rst @@ -13,7 +13,7 @@ error to use a variable outside its scope: -.. code:: rust,editable,compile_fail +.. code:: rust struct Point(i32, i32); diff --git a/courses/comprehensive_rust_training/130_memory_management/04_move.rst b/courses/comprehensive_rust_training/130_memory_management/04_move.rst index 04f9a8707..2c5145099 100644 --- a/courses/comprehensive_rust_training/130_memory_management/04_move.rst +++ b/courses/comprehensive_rust_training/130_memory_management/04_move.rst @@ -8,7 +8,7 @@ Move Semantics An assignment will transfer *ownership* between variables: -.. code:: rust,editable +.. code:: rust fn main() { let s1: String = String::from("Hello!"); @@ -17,12 +17,12 @@ An assignment will transfer *ownership* between variables: // println!("s1: {s1}"); } -- The assignment of ``s1`` to ``s2`` transfers ownership. -- When ``s1`` goes out of scope, nothing happens: it does not own +- The assignment of :rust:`s1` to :rust:`s2` transfers ownership. +- When :rust:`s1` goes out of scope, nothing happens: it does not own anything. -- When ``s2`` goes out of scope, the string data is freed. +- When :rust:`s2` goes out of scope, the string data is freed. -Before move to ``s2``: +Before move to :rust:`s2`: .. code:: bob @@ -39,7 +39,7 @@ Before move to ``s2``: : : `- - - - - - - - - - - - - -' -After move to ``s2``: +After move to :rust:`s2`: .. code:: bob @@ -65,7 +65,7 @@ After move to ``s2``: When you pass a value to a function, the value is assigned to the function parameter. This transfers ownership: -.. code:: rust,editable +.. code:: rust fn say_hello(name: String) { println!("Hello {name}") @@ -84,29 +84,29 @@ Details --------- - Mention that this is the opposite of the defaults in C++, which - copies by value unless you use ``std::move`` (and the move + copies by value unless you use :rust:`std::move` (and the move constructor is defined!). - It is only the ownership that moves. Whether any machine code is generated to manipulate the data itself is a matter of optimization, and such copies are aggressively optimized away. -- Simple values (such as integers) can be marked ``Copy`` (see later +- Simple values (such as integers) can be marked :rust:`Copy` (see later slides). -- In Rust, clones are explicit (by using ``clone``). +- In Rust, clones are explicit (by using :rust:`clone`). -In the ``say_hello`` example: +In the :rust:`say_hello` example: -- With the first call to ``say_hello``, ``main`` gives up ownership of - ``name``. Afterwards, ``name`` cannot be used anymore within - ``main``. -- The heap memory allocated for ``name`` will be freed at the end of - the ``say_hello`` function. -- ``main`` can retain ownership if it passes ``name`` as a reference - (``&name``) and if ``say_hello`` accepts a reference as a parameter. -- Alternatively, ``main`` can pass a clone of ``name`` in the first - call (``name.clone()``). +- With the first call to :rust:`say_hello`, :rust:`main` gives up ownership of + :rust:`name`. Afterwards, :rust:`name` cannot be used anymore within + :rust:`main`. +- The heap memory allocated for :rust:`name` will be freed at the end of + the :rust:`say_hello` function. +- :rust:`main` can retain ownership if it passes :rust:`name` as a reference + (:rust:`&name`) and if :rust:`say_hello` accepts a reference as a parameter. +- Alternatively, :rust:`main` can pass a clone of :rust:`name` in the first + call (:rust:`name.clone()`). - Rust makes it harder than C++ to inadvertently create copies by making move semantics the default, and by forcing programmers to make clones explicit. @@ -130,9 +130,9 @@ Modern C++ solves this differently: std::string s1 = "Cpp"; std::string s2 = s1; // Duplicate the data in s1. -- The heap data from ``s1`` is duplicated and ``s2`` gets its own +- The heap data from :rust:`s1` is duplicated and :rust:`s2` gets its own independent copy. -- When ``s1`` and ``s2`` go out of scope, they each free their own +- When :rust:`s1` and :rust:`s2` go out of scope, they each free their own memory. Before copy-assignment: @@ -176,19 +176,19 @@ After copy-assignment: Key points: -- C++ has made a slightly different choice than Rust. Because ``=`` +- C++ has made a slightly different choice than Rust. Because :rust:`=` copies data, the string data has to be cloned. Otherwise we would get a double-free when either string goes out of scope. - C++ also has :url:`std::move `, which is used to indicate when a value may be moved from. If the - example had been ``s2 = std::move(s1)``, no heap allocation would - take place. After the move, ``s1`` would be in a valid but + example had been :rust:`s2 = std::move(s1)`, no heap allocation would + take place. After the move, :rust:`s1` would be in a valid but unspecified state. Unlike Rust, the programmer is allowed to keep - using ``s1``. + using :rust:`s1`. -- Unlike Rust, ``=`` in C++ can run arbitrary code as determined by the +- Unlike Rust, :rust:`=` in C++ can run arbitrary code as determined by the type which is being copied or moved. .. raw:: html diff --git a/courses/comprehensive_rust_training/130_memory_management/05_clone.rst b/courses/comprehensive_rust_training/130_memory_management/05_clone.rst index a9a029b88..c70daa943 100644 --- a/courses/comprehensive_rust_training/130_memory_management/05_clone.rst +++ b/courses/comprehensive_rust_training/130_memory_management/05_clone.rst @@ -6,10 +6,10 @@ Clone Clone ------- -Sometimes you *want* to make a copy of a value. The ``Clone`` trait +Sometimes you *want* to make a copy of a value. The :rust:`Clone` trait accomplishes this. -.. code:: rust,editable +.. code:: rust fn say_hello(name: String) { println!("Hello {name}") @@ -27,18 +27,18 @@ accomplishes this. Details --------- -- The idea of ``Clone`` is to make it easy to spot where heap - allocations are occurring. Look for ``.clone()`` and a few others - like ``vec!`` or ``Box::new``. +- The idea of :rust:`Clone` is to make it easy to spot where heap + allocations are occurring. Look for :rust:`.clone()` and a few others + like :rust:`vec!` or :rust:`Box::new`. - It's common to "clone your way out" of problems with the borrow checker, and return later to try to optimize those clones away. -- ``clone`` generally performs a deep copy of the value, meaning that +- :rust:`clone` generally performs a deep copy of the value, meaning that if you e.g. clone an array, all of the elements of the array are cloned as well. -- The behavior for ``clone`` is user-defined, so it can perform custom +- The behavior for :rust:`clone` is user-defined, so it can perform custom cloning logic if needed. .. raw:: html diff --git a/courses/comprehensive_rust_training/130_memory_management/06_copy_types.rst b/courses/comprehensive_rust_training/130_memory_management/06_copy_types.rst index 0e2c21589..72bef3e0e 100644 --- a/courses/comprehensive_rust_training/130_memory_management/06_copy_types.rst +++ b/courses/comprehensive_rust_training/130_memory_management/06_copy_types.rst @@ -13,7 +13,7 @@ default: -.. code:: rust,editable +.. code:: rust fn main() { let x = 42; @@ -22,7 +22,7 @@ default: println!("y: {y}"); } -These types implement the ``Copy`` trait. +These types implement the :rust:`Copy` trait. You can opt-in your own types to use copy semantics: @@ -30,7 +30,7 @@ You can opt-in your own types to use copy semantics: -.. code:: rust,editable +.. code:: rust #[derive(Copy, Clone, Debug)] struct Point(i32, i32); @@ -42,8 +42,8 @@ You can opt-in your own types to use copy semantics: println!("p2: {p2:?}"); } -- After the assignment, both ``p1`` and ``p2`` own their own data. -- We can also use ``p1.clone()`` to explicitly copy the data. +- After the assignment, both :rust:`p1` and :rust:`p2` own their own data. +- We can also use :rust:`p1.clone()` to explicitly copy the data. .. raw:: html @@ -58,16 +58,16 @@ Copying and cloning are not the same thing: - Copying does not allow for custom logic (unlike copy constructors in C++). - Cloning is a more general operation and also allows for custom - behavior by implementing the ``Clone`` trait. -- Copying does not work on types that implement the ``Drop`` trait. + behavior by implementing the :rust:`Clone` trait. +- Copying does not work on types that implement the :rust:`Drop` trait. In the above example, try the following: -- Add a ``String`` field to ``struct Point``. It will not compile - because ``String`` is not a ``Copy`` type. -- Remove ``Copy`` from the ``derive`` attribute. The compiler error is - now in the ``println!`` for ``p1``. -- Show that it works if you clone ``p1`` instead. +- Add a :rust:`String` field to :rust:`struct Point`. It will not compile + because :rust:`String` is not a :rust:`Copy` type. +- Remove :rust:`Copy` from the :rust:`derive` attribute. The compiler error is + now in the :rust:`println!` for :rust:`p1`. +- Show that it works if you clone :rust:`p1` instead. ================= More to Explore @@ -77,7 +77,7 @@ More to Explore More to Explore ----------------- -- Shared references are ``Copy``/``Clone``, mutable references are not. +- Shared references are :rust:`Copy`/:rust:`Clone`, mutable references are not. This is because Rust requires that mutable references be exclusive, so while it's valid to make a copy of a shared reference, creating a copy of a mutable reference would violate Rust's borrowing rules. diff --git a/courses/comprehensive_rust_training/130_memory_management/07_drop.rst b/courses/comprehensive_rust_training/130_memory_management/07_drop.rst index 337bb58b1..fa9c82639 100644 --- a/courses/comprehensive_rust_training/130_memory_management/07_drop.rst +++ b/courses/comprehensive_rust_training/130_memory_management/07_drop.rst @@ -1,16 +1,16 @@ ==================== -The ``Drop`` Trait +The :rust:`Drop` Trait ==================== -------------------- -The ``Drop`` Trait +The :rust:`Drop` Trait -------------------- Values which implement :url:`Drop ` can specify code to run when they go out of scope: -.. code:: rust,editable +.. code:: rust struct Droppable { name: &'static str, @@ -43,31 +43,31 @@ specify code to run when they go out of scope: Details --------- -- Note that ``std::mem::drop`` is not the same as - ``std::ops::Drop::drop``. +- Note that :rust:`std::mem::drop` is not the same as + :rust:`std::ops::Drop::drop`. - Values are automatically dropped when they go out of scope. -- When a value is dropped, if it implements ``std::ops::Drop`` then its - ``Drop::drop`` implementation will be called. +- When a value is dropped, if it implements :rust:`std::ops::Drop` then its + :rust:`Drop::drop` implementation will be called. - All its fields will then be dropped too, whether or not it implements - ``Drop``. -- ``std::mem::drop`` is just an empty function that takes any value. + :rust:`Drop`. +- :rust:`std::mem::drop` is just an empty function that takes any value. The significance is that it takes ownership of the value, so at the end of its scope it gets dropped. This makes it a convenient way to explicitly drop values earlier than they would otherwise go out of scope. - - This can be useful for objects that do some work on ``drop``: + - This can be useful for objects that do some work on :rust:`drop`: releasing locks, closing files, etc. Discussion points: -- Why doesn't ``Drop::drop`` take ``self``? +- Why doesn't :rust:`Drop::drop` take :rust:`self`? - - Short-answer: If it did, ``std::mem::drop`` would be called at the - end of the block, resulting in another call to ``Drop::drop``, and + - Short-answer: If it did, :rust:`std::mem::drop` would be called at the + end of the block, resulting in another call to :rust:`Drop::drop`, and a stack overflow! -- Try replacing ``drop(a)`` with ``a.drop()``. +- Try replacing :rust:`drop(a)` with :rust:`a.drop()`. .. raw:: html diff --git a/courses/comprehensive_rust_training/130_memory_management/08_exercise.rst b/courses/comprehensive_rust_training/130_memory_management/08_exercise.rst index 869bfbf6e..86d9a9ca7 100644 --- a/courses/comprehensive_rust_training/130_memory_management/08_exercise.rst +++ b/courses/comprehensive_rust_training/130_memory_management/08_exercise.rst @@ -12,7 +12,7 @@ value piece-by-piece, using convenience functions. Fill in the missing pieces. -.. code:: rust,should_panic,editable +.. code:: rust {{#include exercise.rs:Package}} {{#include exercise.rs:as_dependency}} diff --git a/courses/comprehensive_rust_training/140_smart_pointers/01_box.rst b/courses/comprehensive_rust_training/140_smart_pointers/01_box.rst index 3f7842256..2a3ac5bdb 100644 --- a/courses/comprehensive_rust_training/140_smart_pointers/01_box.rst +++ b/courses/comprehensive_rust_training/140_smart_pointers/01_box.rst @@ -1,15 +1,15 @@ ============ -``Box`` +:rust:`Box` ============ ------------ -``Box`` +:rust:`Box` ------------ :url:`Box ` is an owned pointer to data on the heap: -.. code:: rust,editable +.. code:: rust fn main() { let five = Box::new(5); @@ -29,14 +29,14 @@ owned pointer to data on the heap: : : : : `- - - - - - -' `- - - - - - -' -``Box`` implements ``Deref``, which means that you can +:rust:`Box` implements :rust:`Deref`, which means that you can :url:`call methods from T directly on a Box `. Recursive data types or data types with dynamic sizes cannot be stored -inline without a pointer indirection. ``Box`` accomplishes that +inline without a pointer indirection. :rust:`Box` accomplishes that indirection: -.. code:: rust,editable +.. code:: rust #[derive(Debug)] enum List { @@ -71,33 +71,33 @@ indirection: Details --------- -- ``Box`` is like ``std::unique_ptr`` in C++, except that it's +- :rust:`Box` is like :rust:`std::unique_ptr` in C++, except that it's guaranteed to be not null. -- A ``Box`` can be useful when you: +- A :rust:`Box` can be useful when you: - have a type whose size can't be known at compile time, but the Rust compiler wants to know an exact size. - want to transfer ownership of a large amount of data. To avoid copying large amounts of data on the stack, instead store the data - on the heap in a ``Box`` so only the pointer is moved. + on the heap in a :rust:`Box` so only the pointer is moved. -- If ``Box`` was not used and we attempted to embed a ``List`` directly - into the ``List``, the compiler would not be able to compute a fixed - size for the struct in memory (the ``List`` would be of infinite +- If :rust:`Box` was not used and we attempted to embed a :rust:`List` directly + into the :rust:`List`, the compiler would not be able to compute a fixed + size for the struct in memory (the :rust:`List` would be of infinite size). -- ``Box`` solves this problem as it has the same size as a regular - pointer and just points at the next element of the ``List`` in the +- :rust:`Box` solves this problem as it has the same size as a regular + pointer and just points at the next element of the :rust:`List` in the heap. -- Remove the ``Box`` in the List definition and show the compiler +- Remove the :rust:`Box` in the List definition and show the compiler error. We get the message "recursive without indirection", because - for data recursion, we have to use indirection, a ``Box`` or + for data recursion, we have to use indirection, a :rust:`Box` or reference of some kind, instead of storing the value directly. -- Though ``Box`` looks like ``std::unique_ptr`` in C++, it cannot be - empty/null. This makes ``Box`` one of the types that allow the +- Though :rust:`Box` looks like :rust:`std::unique_ptr` in C++, it cannot be + empty/null. This makes :rust:`Box` one of the types that allow the compiler to optimize storage of some enums (the "niche optimization"). diff --git a/courses/comprehensive_rust_training/140_smart_pointers/02_rc.rst b/courses/comprehensive_rust_training/140_smart_pointers/02_rc.rst index a31d911e5..bbd03cc39 100644 --- a/courses/comprehensive_rust_training/140_smart_pointers/02_rc.rst +++ b/courses/comprehensive_rust_training/140_smart_pointers/02_rc.rst @@ -1,16 +1,16 @@ ======== -``Rc`` +:rust:`Rc` ======== -------- -``Rc`` +:rust:`Rc` -------- :url:`Rc ` is a reference-counted shared pointer. Use this when you need to refer to the same data from multiple places: -.. code:: rust,editable +.. code:: rust use std::rc::Rc; @@ -22,7 +22,7 @@ same data from multiple places: println!("b: {b}"); } -- See ```Arc`:url:` <../concurrency/shared-state/arc.md>` and +- See :rust:`Arc`:url:` <../concurrency/shared-state/arc.md>` and :url:`Mutex ` if you are in a multi-threaded context. - You can *downgrade* a shared pointer into a @@ -35,18 +35,18 @@ same data from multiple places: Details --------- -- ``Rc``\ 's count ensures that its contained value is valid for as +- :rust:`Rc`\ 's count ensures that its contained value is valid for as long as there are references. -- ``Rc`` in Rust is like ``std::shared_ptr`` in C++. -- ``Rc::clone`` is cheap: it creates a pointer to the same allocation +- :rust:`Rc` in Rust is like :rust:`std::shared_ptr` in C++. +- :rust:`Rc::clone` is cheap: it creates a pointer to the same allocation and increases the reference count. Does not make a deep clone and can generally be ignored when looking for performance issues in code. -- ``make_mut`` actually clones the inner value if necessary +- :rust:`make_mut` actually clones the inner value if necessary ("clone-on-write") and returns a mutable reference. -- Use ``Rc::strong_count`` to check the reference count. -- ``Rc::downgrade`` gives you a *weakly reference-counted* object to +- Use :rust:`Rc::strong_count` to check the reference count. +- :rust:`Rc::downgrade` gives you a *weakly reference-counted* object to create cycles that will be dropped properly (likely in combination - with ``RefCell``). + with :rust:`RefCell`). .. raw:: html diff --git a/courses/comprehensive_rust_training/140_smart_pointers/03_trait_objects.rst b/courses/comprehensive_rust_training/140_smart_pointers/03_trait_objects.rst index 7eb764bbe..1e4ea0689 100644 --- a/courses/comprehensive_rust_training/140_smart_pointers/03_trait_objects.rst +++ b/courses/comprehensive_rust_training/140_smart_pointers/03_trait_objects.rst @@ -7,10 +7,10 @@ Owned Trait Objects --------------------- We previously saw how trait objects can be used with references, e.g -``&dyn Pet``. However, we can also use trait objects with smart pointers -like ``Box`` to create an owned trait object: ``Box``. +:rust:`&dyn Pet`. However, we can also use trait objects with smart pointers +like :rust:`Box` to create an owned trait object: :rust:`Box`. -.. code:: rust,editable +.. code:: rust struct Dog { name: String, @@ -46,7 +46,7 @@ like ``Box`` to create an owned trait object: ``Box``. } } -Memory layout after allocating ``pets``: +Memory layout after allocating :rust:`pets`: .. code:: bob @@ -87,25 +87,25 @@ Details --------- - Types that implement a given trait may be of different sizes. This - makes it impossible to have things like ``Vec`` in the + makes it impossible to have things like :rust:`Vec` in the example above. -- ``dyn Pet`` is a way to tell the compiler about a dynamically sized - type that implements ``Pet``. +- :rust:`dyn Pet` is a way to tell the compiler about a dynamically sized + type that implements :rust:`Pet`. -- In the example, ``pets`` is allocated on the stack and the vector +- In the example, :rust:`pets` is allocated on the stack and the vector data is on the heap. The two vector elements are *fat pointers*: - A fat pointer is a double-width pointer. It has two components: a pointer to the actual object and a pointer to the :url:`virtual method table ` - (vtable) for the ``Pet`` implementation of that particular object. - - The data for the ``Dog`` named Fido is the ``name`` and ``age`` - fields. The ``Cat`` has a ``lives`` field. + (vtable) for the :rust:`Pet` implementation of that particular object. + - The data for the :rust:`Dog` named Fido is the :rust:`name` and :rust:`age` + fields. The :rust:`Cat` has a :rust:`lives` field. - Compare these outputs in the above example: - .. code:: rust,ignore + .. code:: rust println!("{} {}", std::mem::size_of::(), std::mem::size_of::()); println!("{} {}", std::mem::size_of::<&Dog>(), std::mem::size_of::<&Cat>()); diff --git a/courses/comprehensive_rust_training/140_smart_pointers/04_exercise.rst b/courses/comprehensive_rust_training/140_smart_pointers/04_exercise.rst index e9bcba20f..1b3934b7b 100644 --- a/courses/comprehensive_rust_training/140_smart_pointers/04_exercise.rst +++ b/courses/comprehensive_rust_training/140_smart_pointers/04_exercise.rst @@ -17,7 +17,7 @@ Implement the following types, so that the given tests pass. Extra Credit: implement an iterator over a binary tree that returns the values in order. -.. code:: rust,editable,ignore +.. code:: rust {{#include exercise.rs:types}} diff --git a/courses/comprehensive_rust_training/150_borrowing/01_shared.rst b/courses/comprehensive_rust_training/150_borrowing/01_shared.rst index e68894fa4..86647b171 100644 --- a/courses/comprehensive_rust_training/150_borrowing/01_shared.rst +++ b/courses/comprehensive_rust_training/150_borrowing/01_shared.rst @@ -13,7 +13,7 @@ function, you can let a function *borrow* the value: -.. code:: rust,editable +.. code:: rust #[derive(Debug)] struct Point(i32, i32); @@ -29,7 +29,7 @@ function, you can let a function *borrow* the value: println!("{p1:?} + {p2:?} = {p3:?}"); } -- The ``add`` function *borrows* two points and returns a new point. +- The :rust:`add` function *borrows* two points and returns a new point. - The caller retains ownership of the inputs. .. raw:: html @@ -51,7 +51,7 @@ More to Explore Notes on stack returns and inlining: -- Demonstrate that the return from ``add`` is cheap because the +- Demonstrate that the return from :rust:`add` is cheap because the compiler can eliminate the copy operation, by inlining the call to add into main. Change the above code to print stack addresses and run it on the @@ -64,7 +64,7 @@ Notes on stack returns and inlining: - .. code:: rust,editable + .. code:: rust #[derive(Debug)] struct Point(i32, i32); @@ -84,7 +84,7 @@ Notes on stack returns and inlining: } - The Rust compiler can do automatic inlining, that can be disabled on - a function level with ``#[inline(never)]``. + a function level with :rust:`#[inline(never)]`. - Once disabled, the printed address will change on all optimization levels. Looking at Godbolt or Playground, one can see that in this diff --git a/courses/comprehensive_rust_training/150_borrowing/02_borrowck.rst b/courses/comprehensive_rust_training/150_borrowing/02_borrowck.rst index d17e15bf7..2b0dd20e3 100644 --- a/courses/comprehensive_rust_training/150_borrowing/02_borrowck.rst +++ b/courses/comprehensive_rust_training/150_borrowing/02_borrowck.rst @@ -14,7 +14,7 @@ it borrows: -.. code:: rust,editable,compile_fail +.. code:: rust fn main() { let x_ref = { @@ -34,7 +34,7 @@ There's also a second main rule that the borrow checker enforces: The -.. code:: rust,editable,compile_fail +.. code:: rust fn main() { let mut a: i32 = 10; @@ -61,12 +61,12 @@ Details - Note that the requirement is that conflicting references not *exist* at the same point. It does not matter where the reference is dereferenced. -- The above code does not compile because ``a`` is borrowed as mutable - (through ``c``) and as immutable (through ``b``) at the same time. -- Move the ``println!`` statement for ``b`` before the scope that - introduces ``c`` to make the code compile. -- After that change, the compiler realizes that ``b`` is only ever used - before the new mutable borrow of ``a`` through ``c``. This is a +- The above code does not compile because :rust:`a` is borrowed as mutable + (through :rust:`c`) and as immutable (through :rust:`b`) at the same time. +- Move the :rust:`println!` statement for :rust:`b` before the scope that + introduces :rust:`c` to make the code compile. +- After that change, the compiler realizes that :rust:`b` is only ever used + before the new mutable borrow of :rust:`a` through :rust:`c`. This is a feature of the borrow checker called "non-lexical lifetimes". - The exclusive reference constraint is quite strong. Rust uses it to ensure that data races do not occur. Rust also *relies* on this diff --git a/courses/comprehensive_rust_training/150_borrowing/03_examples.rst b/courses/comprehensive_rust_training/150_borrowing/03_examples.rst index 406bf994d..027e33027 100644 --- a/courses/comprehensive_rust_training/150_borrowing/03_examples.rst +++ b/courses/comprehensive_rust_training/150_borrowing/03_examples.rst @@ -10,7 +10,7 @@ As a concrete example of how these borrowing rules prevent memory errors, consider the case of modifying a collection while there are references to its elements: -.. code:: rust,editable,compile_fail +.. code:: rust fn main() { let mut vec = vec![1, 2, 3, 4, 5]; @@ -21,7 +21,7 @@ references to its elements: Similarly, consider the case of iterator invalidation: -.. code:: rust,editable,compile_fail +.. code:: rust fn main() { let mut vec = vec![1, 2, 3, 4, 5]; diff --git a/courses/comprehensive_rust_training/160_lifetimes/01_lifetime_annotations.rst b/courses/comprehensive_rust_training/160_lifetimes/01_lifetime_annotations.rst index 3bb19ba62..9a5e0ba5d 100644 --- a/courses/comprehensive_rust_training/160_lifetimes/01_lifetime_annotations.rst +++ b/courses/comprehensive_rust_training/160_lifetimes/01_lifetime_annotations.rst @@ -10,10 +10,10 @@ A reference has a *lifetime*, which must not "outlive" the value it refers to. This is verified by the borrow checker. The lifetime can be implicit - this is what we have seen so far. -Lifetimes can also be explicit: ``&'a Point``, ``&'document str``. -Lifetimes start with ``'`` and ``'a`` is a typical default name. Read -``&'a Point`` as "a borrowed ``Point`` which is valid for at least the -lifetime ``a``". +Lifetimes can also be explicit: :rust:`&'a Point`, :rust:`&'document str`. +Lifetimes start with :rust:`'` and :rust:`'a` is a typical default name. Read +:rust:`&'a Point` as "a borrowed :rust:`Point` which is valid for at least the +lifetime :rust:`a`". Lifetimes are always inferred by the compiler: you cannot assign a lifetime yourself. Explicit lifetime annotations create constraints @@ -28,7 +28,7 @@ returning values from functions. -.. code:: rust,editable,compile_fail +.. code:: rust #[derive(Debug)] struct Point(i32, i32); @@ -55,19 +55,19 @@ Details --------- In this example, the compiler does not know what lifetime to infer for -``p3``. Looking inside the function body shows that it can only safely -assume that ``p3``\ 's lifetime is the shorter of ``p1`` and ``p2``. But +:rust:`p3`. Looking inside the function body shows that it can only safely +assume that :rust:`p3`\ 's lifetime is the shorter of :rust:`p1` and :rust:`p2`. But just like types, Rust requires explicit annotations of lifetimes on function arguments and return values. -Add ``'a`` appropriately to ``left_most``: +Add :rust:`'a` appropriately to :rust:`left_most`: -.. code:: rust,ignore +.. code:: rust fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point { -This says, "given p1 and p2 which both outlive ``'a``, the return value -lives for at least ``'a``. +This says, "given p1 and p2 which both outlive :rust:`'a`, the return value +lives for at least :rust:`'a`. In common cases, lifetimes can be elided, as described on the next slide. diff --git a/courses/comprehensive_rust_training/160_lifetimes/02_lifetime_elision.rst b/courses/comprehensive_rust_training/160_lifetimes/02_lifetime_elision.rst index 83328267f..b51513197 100644 --- a/courses/comprehensive_rust_training/160_lifetimes/02_lifetime_elision.rst +++ b/courses/comprehensive_rust_training/160_lifetimes/02_lifetime_elision.rst @@ -15,9 +15,9 @@ is not inference - it is just a syntactic shorthand. - If there is only one argument lifetime, it is given to all un-annotated return values. - If there are multiple argument lifetimes, but the first one is for - ``self``, that lifetime is given to all un-annotated return values. + :rust:`self`, that lifetime is given to all un-annotated return values. -.. code:: rust,editable +.. code:: rust #[derive(Debug)] struct Point(i32, i32); @@ -52,14 +52,14 @@ is not inference - it is just a syntactic shorthand. Details --------- -In this example, ``cab_distance`` is trivially elided. +In this example, :rust:`cab_distance` is trivially elided. -The ``nearest`` function provides another example of a function with +The :rust:`nearest` function provides another example of a function with multiple references in its arguments that requires explicit annotation. Try adjusting the signature to "lie" about the lifetimes returned: -.. code:: rust,ignore +.. code:: rust fn nearest<'a, 'q>(points: &'a [Point], query: &'q Point) -> Option<&'q Point> { diff --git a/courses/comprehensive_rust_training/160_lifetimes/03_struct_lifetimes.rst b/courses/comprehensive_rust_training/160_lifetimes/03_struct_lifetimes.rst index 6b8a6bfd4..8deaa6ed2 100644 --- a/courses/comprehensive_rust_training/160_lifetimes/03_struct_lifetimes.rst +++ b/courses/comprehensive_rust_training/160_lifetimes/03_struct_lifetimes.rst @@ -9,7 +9,7 @@ Lifetimes in Data Structures If a data type stores borrowed data, it must be annotated with a lifetime: -.. code:: rust,editable +.. code:: rust #[derive(Debug)] struct Highlight<'doc>(&'doc str); @@ -33,11 +33,11 @@ lifetime: Details --------- -- In the above example, the annotation on ``Highlight`` enforces that - the data underlying the contained ``&str`` lives at least as long as - any instance of ``Highlight`` that uses that data. -- If ``text`` is consumed before the end of the lifetime of ``fox`` (or - ``dog``), the borrow checker throws an error. +- In the above example, the annotation on :rust:`Highlight` enforces that + the data underlying the contained :rust:`&str` lives at least as long as + any instance of :rust:`Highlight` that uses that data. +- If :rust:`text` is consumed before the end of the lifetime of :rust:`fox` (or + :rust:`dog`), the borrow checker throws an error. - Types with borrowed data force users to hold on to the original data. This can be useful for creating lightweight views, but it generally makes them somewhat harder to use. diff --git a/courses/comprehensive_rust_training/160_lifetimes/04_exercise.rst b/courses/comprehensive_rust_training/160_lifetimes/04_exercise.rst index db4e1792f..5c30108d9 100644 --- a/courses/comprehensive_rust_training/160_lifetimes/04_exercise.rst +++ b/courses/comprehensive_rust_training/160_lifetimes/04_exercise.rst @@ -14,8 +14,8 @@ copied. Fully parsing a protobuf message requires knowing the types of the fields, indexed by their field numbers. That is typically provided in a -``proto`` file. In this exercise, we'll encode that information into -``match`` statements in functions that get called for each field. +:rust:`proto` file. In this exercise, we'll encode that information into +:rust:`match` statements in functions that get called for each field. We'll use the following proto: @@ -38,17 +38,17 @@ Messages A proto message is encoded as a series of fields, one after the next. Each is implemented as a "tag" followed by the value. The tag contains a -field number (e.g., ``2`` for the ``id`` field of a ``Person`` message) +field number (e.g., :rust:`2` for the :rust:`id` field of a :rust:`Person` message) and a wire type defining how the payload should be determined from the byte stream. These are combined into a single integer, as decoded in -``unpack_tag`` below. +:rust:`unpack_tag` below. -------- Varint -------- Integers, including the tag, are represented with a variable-length -encoding called VARINT. Luckily, ``parse_varint`` is defined for you +encoding called VARINT. Luckily, :rust:`parse_varint` is defined for you below. ------------ @@ -58,31 +58,31 @@ Wire Types Proto defines several wire types, only two of which are used in this exercise. -The ``Varint`` wire type contains a single varint, and is used to encode -proto values of type ``int32`` such as ``Person.id``. +The :rust:`Varint` wire type contains a single varint, and is used to encode +proto values of type :rust:`int32` such as :rust:`Person.id`. -The ``Len`` wire type contains a length expressed as a varint, followed +The :rust:`Len` wire type contains a length expressed as a varint, followed by a payload of that number of bytes. This is used to encode proto -values of type ``string`` such as ``Person.name``. It is also used to -encode proto values containing sub-messages such as ``Person.phones``, +values of type :rust:`string` such as :rust:`Person.name`. It is also used to +encode proto values containing sub-messages such as :rust:`Person.phones`, where the payload contains an encoding of the sub-message. ---------- Exercise ---------- -The given code also defines callbacks to handle ``Person`` and -``PhoneNumber`` fields, and to parse a message into a series of calls to +The given code also defines callbacks to handle :rust:`Person` and +:rust:`PhoneNumber` fields, and to parse a message into a series of calls to those callbacks. -What remains for you is to implement the ``parse_field`` function and -the ``ProtoMessage`` trait for ``Person`` and ``PhoneNumber``. +What remains for you is to implement the :rust:`parse_field` function and +the :rust:`ProtoMessage` trait for :rust:`Person` and :rust:`PhoneNumber`. .. raw:: html -.. code:: rust,editable,compile_fail +.. code:: rust {{#include exercise.rs:preliminaries }} @@ -110,9 +110,9 @@ Details --------- - In this exercise there are various cases where protobuf parsing might - fail, e.g. if you try to parse an ``i32`` when there are fewer than 4 + fail, e.g. if you try to parse an :rust:`i32` when there are fewer than 4 bytes left in the data buffer. In normal Rust code we'd handle this - with the ``Result`` enum, but for simplicity in this exercise we + with the :rust:`Result` enum, but for simplicity in this exercise we panic if any errors are encountered. On day 4 we'll cover error handling in Rust in more detail. diff --git a/courses/comprehensive_rust_training/170_iterators/01_motivation.rst b/courses/comprehensive_rust_training/170_iterators/01_motivation.rst index 2d4938485..55ea95cb1 100644 --- a/courses/comprehensive_rust_training/170_iterators/01_motivation.rst +++ b/courses/comprehensive_rust_training/170_iterators/01_motivation.rst @@ -17,7 +17,7 @@ define: In a C-style for loop you declare these things directly: -.. code:: c,editable +.. code:: c for (int i = 0; i < array_len; i += 1) { int elem = array[i]; @@ -33,15 +33,15 @@ Details --------- - This slide provides context for what Rust iterators do under the - hood. We use the (hopefully) familiar construct of a C-style ``for`` + hood. We use the (hopefully) familiar construct of a C-style :rust:`for` loop to show how iteration requires some state and some logic, that way on the next slide we can show how an iterator bundles these together. -- Rust doesn't have a C-style ``for`` loop, but we can express the same - thing with ``while``: +- Rust doesn't have a C-style :rust:`for` loop, but we can express the same + thing with :rust:`while`: - .. code:: rust,editable + .. code:: rust let array = [2, 4, 6, 8]; let mut i = 0; @@ -54,12 +54,12 @@ Details More to Explore ----------------- -There's another way to express array iteration using ``for`` in C and +There's another way to express array iteration using :rust:`for` in C and C++: You can use a pointer to the front and a pointer to the end of the array and then compare those pointers to determine when the loop should end. -.. code:: c,editable +.. code:: c for (int *ptr = array; ptr < array + len; ptr += 1) { int elem = *ptr; diff --git a/courses/comprehensive_rust_training/170_iterators/02_iterator.rst b/courses/comprehensive_rust_training/170_iterators/02_iterator.rst index ee812891b..65ebffccc 100644 --- a/courses/comprehensive_rust_training/170_iterators/02_iterator.rst +++ b/courses/comprehensive_rust_training/170_iterators/02_iterator.rst @@ -1,9 +1,9 @@ ==================== -``Iterator`` Trait +:rust:`Iterator` Trait ==================== -------------------- -``Iterator`` Trait +:rust:`Iterator` Trait -------------------- The @@ -12,7 +12,7 @@ trait defines how an object can be used to produce a sequence of values. For example, if we wanted to create an iterator that can produce the elements of a slice it might look something like this: -.. code:: rust,editable +.. code:: rust struct SliceIter<'s> { slice: &'s [i32], @@ -47,32 +47,32 @@ elements of a slice it might look something like this: Details --------- -- The ``SliceIter`` example implements the same logic as the C-style - ``for`` loop demonstrated on the last slide. +- The :rust:`SliceIter` example implements the same logic as the C-style + :rust:`for` loop demonstrated on the last slide. - Point out to the students that iterators are lazy: Creating the iterator just initializes the struct but does not otherwise do any - work. No work happens until the ``next`` method is called. + work. No work happens until the :rust:`next` method is called. - Iterators don't need to be finite! It's entirely valid to have an iterator that will produce values forever. For example, a half open - range like ``0..`` will keep going until integer overflow occurs. + range like :rust:`0..` will keep going until integer overflow occurs. ----------------- More to Explore ----------------- -- The "real" version of ``SliceIter`` is the +- The "real" version of :rust:`SliceIter` is the :url:`slice::Iter ` type in the standard library, however the real version uses pointers under the hood instead of an index in order to eliminate bounds checks. -- The ``SliceIter`` example is a good example of a struct that contains +- The :rust:`SliceIter` example is a good example of a struct that contains a reference and therefore uses lifetime annotations. -- You can also demonstrate adding a generic parameter to ``SliceIter`` - to allow it to work with any kind of slice (not just ``&[i32]``). +- You can also demonstrate adding a generic parameter to :rust:`SliceIter` + to allow it to work with any kind of slice (not just :rust:`&[i32]`). .. raw:: html diff --git a/courses/comprehensive_rust_training/170_iterators/03_helpers.rst b/courses/comprehensive_rust_training/170_iterators/03_helpers.rst index 1246fd39d..36055d910 100644 --- a/courses/comprehensive_rust_training/170_iterators/03_helpers.rst +++ b/courses/comprehensive_rust_training/170_iterators/03_helpers.rst @@ -1,16 +1,16 @@ ============================= -``Iterator`` Helper Methods +:rust:`Iterator` Helper Methods ============================= ----------------------------- -``Iterator`` Helper Methods +:rust:`Iterator` Helper Methods ----------------------------- -In addition to the ``next`` method that defines how an iterator behaves, -the ``Iterator`` trait provides 70+ helper methods that can be used to +In addition to the :rust:`next` method that defines how an iterator behaves, +the :rust:`Iterator` trait provides 70+ helper methods that can be used to build customized iterators. -.. code:: rust,editable +.. code:: rust let result: i32 = (1..=10) // Create a range from 1 to 10 .filter(|&x| x % 2 == 0) // Keep only even numbers @@ -25,8 +25,8 @@ build customized iterators. Details --------- -- The ``Iterator`` trait implements many common functional programming - operations over collections (e.g. ``map``, ``filter``, ``reduce``, +- The :rust:`Iterator` trait implements many common functional programming + operations over collections (e.g. :rust:`map`, :rust:`filter`, :rust:`reduce`, etc). This is the trait where you can find all the documentation about them. @@ -34,7 +34,7 @@ Details new iterator with different behavior. These are know as "iterator adapter methods". -- Some methods, like ``sum`` and ``count``, consume the iterator and +- Some methods, like :rust:`sum` and :rust:`count`, consume the iterator and pull all of the elements out of it. - These methods are designed to be chained together so that it's easy diff --git a/courses/comprehensive_rust_training/170_iterators/04_collect.rst b/courses/comprehensive_rust_training/170_iterators/04_collect.rst index b0463ce1d..25146fe1b 100644 --- a/courses/comprehensive_rust_training/170_iterators/04_collect.rst +++ b/courses/comprehensive_rust_training/170_iterators/04_collect.rst @@ -1,9 +1,9 @@ ============= -``collect`` +:rust:`collect` ============= ------------- -``collect`` +:rust:`collect` ------------- The @@ -11,7 +11,7 @@ The method lets you build a collection from an :url:`Iterator `. -.. code:: rust,editable +.. code:: rust fn main() { let primes = vec![2, 3, 5, 7]; @@ -25,20 +25,20 @@ method lets you build a collection from an Details --------- -- Any iterator can be collected in to a ``Vec``, ``VecDeque``, or - ``HashSet``. Iterators that produce key-value pairs (i.e. a - two-element tuple) can also be collected into ``HashMap`` and - ``BTreeMap``. +- Any iterator can be collected in to a :rust:`Vec`, :rust:`VecDeque`, or + :rust:`HashSet`. Iterators that produce key-value pairs (i.e. a + two-element tuple) can also be collected into :rust:`HashMap` and + :rust:`BTreeMap`. -Show the students the definition for ``collect`` in the standard library -docs. There are two ways to specify the generic type ``B`` for this +Show the students the definition for :rust:`collect` in the standard library +docs. There are two ways to specify the generic type :rust:`B` for this method: -- With the "turbofish": ``some_iterator.collect::()``, - as shown. The ``_`` shorthand used here lets Rust infer the type of - the ``Vec`` elements. +- With the "turbofish": :rust:`some_iterator.collect::()`, + as shown. The :rust:`_` shorthand used here lets Rust infer the type of + the :rust:`Vec` elements. - With type inference: - ``let prime_squares: Vec<_> = some_iterator.collect()``. Rewrite the + :rust:`let prime_squares: Vec<_> = some_iterator.collect()`. Rewrite the example to use this form. ----------------- @@ -49,11 +49,11 @@ More to Explore :url:`FromIterator ` trait, which defines how each type of collection gets built from an iterator. -- In addition to the basic implementations of ``FromIterator`` for - ``Vec``, ``HashMap``, etc., there are also more specialized +- In addition to the basic implementations of :rust:`FromIterator` for + :rust:`Vec`, :rust:`HashMap`, etc., there are also more specialized implementations which let you do cool things like convert an - ``Iterator>`` into a ``Result, E>``. -- The reason type annotations are often needed with ``collect`` is + :rust:`Iterator>` into a :rust:`Result, E>`. +- The reason type annotations are often needed with :rust:`collect` is because it's generic over its return type. This makes it harder for the compiler to infer the correct type in a lot of cases. diff --git a/courses/comprehensive_rust_training/170_iterators/05_intoiterator.rst b/courses/comprehensive_rust_training/170_iterators/05_intoiterator.rst index c009c0143..b655a76b1 100644 --- a/courses/comprehensive_rust_training/170_iterators/05_intoiterator.rst +++ b/courses/comprehensive_rust_training/170_iterators/05_intoiterator.rst @@ -1,18 +1,18 @@ ================== -``IntoIterator`` +:rust:`IntoIterator` ================== ------------------ -``IntoIterator`` +:rust:`IntoIterator` ------------------ -The ``Iterator`` trait tells you how to *iterate* once you have created +The :rust:`Iterator` trait tells you how to *iterate* once you have created an iterator. The related trait :url:`IntoIterator ` defines how to create an iterator for a type. It is used automatically -by the ``for`` loop. +by the :rust:`for` loop. -.. code:: rust,editable +.. code:: rust struct Grid { x_coords: Vec, @@ -63,35 +63,35 @@ by the ``for`` loop. Details --------- -- ``IntoIterator`` is the trait that makes for loops work. It is - implemented by collection types such as ``Vec`` and references to - them such as ``&Vec`` and ``&[T]``. Ranges also implement it. This +- :rust:`IntoIterator` is the trait that makes for loops work. It is + implemented by collection types such as :rust:`Vec` and references to + them such as :rust:`&Vec` and :rust:`&[T]`. Ranges also implement it. This is why you can iterate over a vector with - ``for i in some_vec { .. }`` but ``some_vec.next()`` doesn't exist. + :rust:`for i in some_vec { .. }` but :rust:`some_vec.next()` doesn't exist. -Click through to the docs for ``IntoIterator``. Every implementation of -``IntoIterator`` must declare two types: +Click through to the docs for :rust:`IntoIterator`. Every implementation of +:rust:`IntoIterator` must declare two types: -- ``Item``: the type to iterate over, such as ``i8``, -- ``IntoIter``: the ``Iterator`` type returned by the ``into_iter`` +- :rust:`Item`: the type to iterate over, such as :rust:`i8`, +- :rust:`IntoIter`: the :rust:`Iterator` type returned by the :rust:`into_iter` method. -Note that ``IntoIter`` and ``Item`` are linked: the iterator must have -the same ``Item`` type, which means that it returns ``Option`` +Note that :rust:`IntoIter` and :rust:`Item` are linked: the iterator must have +the same :rust:`Item` type, which means that it returns :rust:`Option` The example iterates over all combinations of x and y coordinates. -Try iterating over the grid twice in ``main``. Why does this fail? Note -that ``IntoIterator::into_iter`` takes ownership of ``self``. +Try iterating over the grid twice in :rust:`main`. Why does this fail? Note +that :rust:`IntoIterator::into_iter` takes ownership of :rust:`self`. -Fix this issue by implementing ``IntoIterator`` for ``&Grid`` and -storing a reference to the ``Grid`` in ``GridIter``. +Fix this issue by implementing :rust:`IntoIterator` for :rust:`&Grid` and +storing a reference to the :rust:`Grid` in :rust:`GridIter`. The same problem can occur for standard library types: -``for e in some_vector`` will take ownership of ``some_vector`` and +:rust:`for e in some_vector` will take ownership of :rust:`some_vector` and iterate over owned elements from that vector. Use -``for e in &some_vector`` instead, to iterate over references to -elements of ``some_vector``. +:rust:`for e in &some_vector` instead, to iterate over references to +elements of :rust:`some_vector`. .. raw:: html diff --git a/courses/comprehensive_rust_training/170_iterators/06_exercise.rst b/courses/comprehensive_rust_training/170_iterators/06_exercise.rst index cb21ac074..3fa9703f9 100644 --- a/courses/comprehensive_rust_training/170_iterators/06_exercise.rst +++ b/courses/comprehensive_rust_training/170_iterators/06_exercise.rst @@ -12,7 +12,7 @@ methods in the trait to implement a complex calculation. Copy the following code to https://play.rust-lang.org/ and make the -tests pass. Use an iterator expression and ``collect`` the result to +tests pass. Use an iterator expression and :rust:`collect` the result to construct the return value. .. code:: rust diff --git a/courses/comprehensive_rust_training/180_modules/01_modules.rst b/courses/comprehensive_rust_training/180_modules/01_modules.rst index d56709e5b..8e0acda4e 100644 --- a/courses/comprehensive_rust_training/180_modules/01_modules.rst +++ b/courses/comprehensive_rust_training/180_modules/01_modules.rst @@ -6,11 +6,11 @@ Modules Modules --------- -We have seen how ``impl`` blocks let us namespace functions to a type. +We have seen how :rust:`impl` blocks let us namespace functions to a type. -Similarly, ``mod`` lets us namespace types and functions: +Similarly, :rust:`mod` lets us namespace types and functions: -.. code:: rust,editable +.. code:: rust mod foo { pub fn do_something() { @@ -35,7 +35,7 @@ Similarly, ``mod`` lets us namespace types and functions: Details --------- -- Packages provide functionality and include a ``Cargo.toml`` file that +- Packages provide functionality and include a :rust:`Cargo.toml` file that describes how to build a bundle of 1+ crates. - Crates are a tree of modules, where a binary crate creates an executable and a library crate compiles to a library. diff --git a/courses/comprehensive_rust_training/180_modules/02_filesystem.rst b/courses/comprehensive_rust_training/180_modules/02_filesystem.rst index 5349471b9..734559852 100644 --- a/courses/comprehensive_rust_training/180_modules/02_filesystem.rst +++ b/courses/comprehensive_rust_training/180_modules/02_filesystem.rst @@ -9,24 +9,24 @@ Filesystem Hierarchy Omitting the module content will tell Rust to look for it in another file: -.. code:: rust,editable,compile_fail +.. code:: rust mod garden; -This tells Rust that the ``garden`` module content is found at -``src/garden.rs``. Similarly, a ``garden::vegetables`` module can be -found at ``src/garden/vegetables.rs``. +This tells Rust that the :rust:`garden` module content is found at +:rust:`src/garden.rs`. Similarly, a :rust:`garden::vegetables` module can be +found at :rust:`src/garden/vegetables.rs`. -The ``crate`` root is in: +The :rust:`crate` root is in: -- ``src/lib.rs`` (for a library crate) -- ``src/main.rs`` (for a binary crate) +- :rust:`src/lib.rs` (for a library crate) +- :rust:`src/main.rs` (for a binary crate) Modules defined in files can be documented, too, using "inner doc comments". These document the item that contains them - in this case, a module. -.. code:: rust,editable,compile_fail +.. code:: rust //! This module implements the garden, including a highly performant germination //! implementation. @@ -51,12 +51,12 @@ module. Details --------- -- Before Rust 2018, modules needed to be located at ``module/mod.rs`` - instead of ``module.rs``, and this is still a working alternative for +- Before Rust 2018, modules needed to be located at :rust:`module/mod.rs` + instead of :rust:`module.rs`, and this is still a working alternative for editions after 2018. -- The main reason to introduce ``filename.rs`` as alternative to - ``filename/mod.rs`` was because many files named ``mod.rs`` can be +- The main reason to introduce :rust:`filename.rs` as alternative to + :rust:`filename/mod.rs` was because many files named :rust:`mod.rs` can be hard to distinguish in IDEs. - Deeper nesting can use folders, even if the main module is a file: @@ -72,13 +72,13 @@ Details - The place rust will look for modules can be changed with a compiler directive: - .. code:: rust,ignore + .. code:: rust #[path = "some/path.rs"] mod some_module; This is useful, for example, if you would like to place tests for a - module in a file named ``some_module_test.rs``, similar to the + module in a file named :rust:`some_module_test.rs`, similar to the convention in Go. .. raw:: html diff --git a/courses/comprehensive_rust_training/180_modules/03_visibility.rst b/courses/comprehensive_rust_training/180_modules/03_visibility.rst index 326167c49..b9698ca8e 100644 --- a/courses/comprehensive_rust_training/180_modules/03_visibility.rst +++ b/courses/comprehensive_rust_training/180_modules/03_visibility.rst @@ -10,10 +10,10 @@ Modules are a privacy boundary: - Module items are private by default (hides implementation details). - Parent and sibling items are always visible. -- In other words, if an item is visible in module ``foo``, it's visible - in all the descendants of ``foo``. +- In other words, if an item is visible in module :rust:`foo`, it's visible + in all the descendants of :rust:`foo`. -.. code:: rust,editable +.. code:: rust mod outer { fn private() { @@ -46,14 +46,14 @@ Modules are a privacy boundary: Details --------- -- Use the ``pub`` keyword to make modules public. +- Use the :rust:`pub` keyword to make modules public. -Additionally, there are advanced ``pub(...)`` specifiers to restrict the +Additionally, there are advanced :rust:`pub(...)` specifiers to restrict the scope of public visibility. - See the :url:`Rust Reference `. -- Configuring ``pub(crate)`` visibility is a common pattern. +- Configuring :rust:`pub(crate)` visibility is a common pattern. - Less commonly, you can give visibility to a specific path. - In any case, visibility must be granted to an ancestor module (and all of its descendants). diff --git a/courses/comprehensive_rust_training/180_modules/04_encapsulation.rst b/courses/comprehensive_rust_training/180_modules/04_encapsulation.rst index 4152ab31f..02950586b 100644 --- a/courses/comprehensive_rust_training/180_modules/04_encapsulation.rst +++ b/courses/comprehensive_rust_training/180_modules/04_encapsulation.rst @@ -12,7 +12,7 @@ Private fields are likewise visible within the rest of the module details of struct, controlling what data and functionality is visible externally. -.. code:: rust,editable +.. code:: rust use outer::Foo; @@ -58,10 +58,10 @@ Details behaves differently while showing how we can still achieve encapsulation. -- Note how the ``is_big`` field is fully controlled by ``Foo``, - allowing ``Foo`` to control how it's initialized and enforce any - invariants it needs to (e.g. that ``is_big`` is only ``true`` if - ``val > 100``). +- Note how the :rust:`is_big` field is fully controlled by :rust:`Foo`, + allowing :rust:`Foo` to control how it's initialized and enforce any + invariants it needs to (e.g. that :rust:`is_big` is only :rust:`true` if + :rust:`val > 100`). - Point out how helper functions can be defined in the same module (including child modules) in order to get access to the type's @@ -79,10 +79,10 @@ More to Explore ----------------- - If students want more information about privacy (or lack thereof) in - enums, you can bring up ``#[doc_hidden]`` and ``#[non_exhaustive]`` + enums, you can bring up :rust:`#[doc_hidden]` and :rust:`#[non_exhaustive]` and show how they're used to limit what can be done with an enum. -- Module privacy still applies when there are ``impl`` blocks in other +- Module privacy still applies when there are :rust:`impl` blocks in other modules :url:`(example in the playground) `. diff --git a/courses/comprehensive_rust_training/180_modules/05_paths.rst b/courses/comprehensive_rust_training/180_modules/05_paths.rst index a0f41faab..365068f91 100644 --- a/courses/comprehensive_rust_training/180_modules/05_paths.rst +++ b/courses/comprehensive_rust_training/180_modules/05_paths.rst @@ -6,10 +6,10 @@ use, super, self use, super, self ------------------ -A module can bring symbols from another module into scope with ``use``. +A module can bring symbols from another module into scope with :rust:`use`. You will typically see something like this at the top of each module: -.. code:: rust,editable +.. code:: rust use std::collections::HashSet; use std::process::abort; @@ -22,13 +22,13 @@ Paths are resolved as follows: 1. As a relative path: - - ``foo`` or ``self::foo`` refers to ``foo`` in the current module, - - ``super::foo`` refers to ``foo`` in the parent module. + - :rust:`foo` or :rust:`self::foo` refers to :rust:`foo` in the current module, + - :rust:`super::foo` refers to :rust:`foo` in the parent module. 2. As an absolute path: - - ``crate::foo`` refers to ``foo`` in the root of the current crate, - - ``bar::foo`` refers to ``foo`` in the ``bar`` crate. + - :rust:`crate::foo` refers to :rust:`foo` in the root of the current crate, + - :rust:`bar::foo` refers to :rust:`foo` in the :rust:`bar` crate. .. raw:: html @@ -37,25 +37,25 @@ Details --------- - It is common to "re-export" symbols at a shorter path. For example, - the top-level ``lib.rs`` in a crate might have + the top-level :rust:`lib.rs` in a crate might have - .. code:: rust,ignore + .. code:: rust mod storage; pub use storage::disk::DiskStorage; pub use storage::network::NetworkStorage; - making ``DiskStorage`` and ``NetworkStorage`` available to other + making :rust:`DiskStorage` and :rust:`NetworkStorage` available to other crates with a convenient, short path. - For the most part, only items that appear in a module need to be - ``use``\ 'd. However, a trait must be in scope to call any methods on + :rust:`use`\ 'd. However, a trait must be in scope to call any methods on that trait, even if a type implementing that trait is already in - scope. For example, to use the ``read_to_string`` method on a type - implementing the ``Read`` trait, you need to ``use std::io::Read``. + scope. For example, to use the :rust:`read_to_string` method on a type + implementing the :rust:`Read` trait, you need to :rust:`use std::io::Read`. -- The ``use`` statement can have a wildcard: ``use std::io::*``. This +- The :rust:`use` statement can have a wildcard: :rust:`use std::io::*`. This is discouraged because it is not clear which items are imported, and those might change over time. diff --git a/courses/comprehensive_rust_training/180_modules/06_exercise.rst b/courses/comprehensive_rust_training/180_modules/06_exercise.rst index d4b094ad5..78e9e1b94 100644 --- a/courses/comprehensive_rust_training/180_modules/06_exercise.rst +++ b/courses/comprehensive_rust_training/180_modules/06_exercise.rst @@ -7,8 +7,8 @@ Exercise: Modules for a GUI Library ------------------------------------- In this exercise, you will reorganize a small GUI Library -implementation. This library defines a ``Widget`` trait and a few -implementations of that trait, as well as a ``main`` function. +implementation. This library defines a :rust:`Widget` trait and a few +implementations of that trait, as well as a :rust:`main` function. It is typical to put each type or set of closely-related types into its own module, so each widget type should get its own module. @@ -26,8 +26,8 @@ Cargo project on your local filesystem: cd gui-modules cargo run -Edit the resulting ``src/main.rs`` to add ``mod`` statements, and add -additional files in the ``src`` directory. +Edit the resulting :rust:`src/main.rs` to add :rust:`mod` statements, and add +additional files in the :rust:`src` directory. -------- Source @@ -46,7 +46,7 @@ Details --------- Encourage students to divide the code in a way that feels natural for -them, and get accustomed to the required ``mod``, ``use``, and ``pub`` +them, and get accustomed to the required :rust:`mod`, :rust:`use`, and :rust:`pub` declarations. Afterward, discuss what organizations are most idiomatic. .. raw:: html diff --git a/courses/comprehensive_rust_training/190_testing/01_unit_tests.rst b/courses/comprehensive_rust_training/190_testing/01_unit_tests.rst index a69211bfd..340e87592 100644 --- a/courses/comprehensive_rust_training/190_testing/01_unit_tests.rst +++ b/courses/comprehensive_rust_training/190_testing/01_unit_tests.rst @@ -7,11 +7,11 @@ Unit Tests ------------ Rust and Cargo come with a simple unit test framework. Tests are marked -with ``#[test]``. Unit tests are often put in a nested ``tests`` module, -using ``#[cfg(test)]`` to conditionally compile them only when building +with :rust:`#[test]`. Unit tests are often put in a nested :rust:`tests` module, +using :rust:`#[cfg(test)]` to conditionally compile them only when building tests. -.. code:: rust,editable,ignore +.. code:: rust fn first_word(text: &str) -> &str { match text.find(' ') { @@ -41,8 +41,8 @@ tests. } - This lets you unit test private helpers. -- The ``#[cfg(test)]`` attribute is only active when you run - ``cargo test``. +- The :rust:`#[cfg(test)]` attribute is only active when you run + :rust:`cargo test`. .. raw:: html diff --git a/courses/comprehensive_rust_training/190_testing/02_other.rst b/courses/comprehensive_rust_training/190_testing/02_other.rst index 98b19998e..f653fddc8 100644 --- a/courses/comprehensive_rust_training/190_testing/02_other.rst +++ b/courses/comprehensive_rust_training/190_testing/02_other.rst @@ -12,9 +12,9 @@ Integration Tests If you want to test your library as a client, use an integration test. -Create a ``.rs`` file under ``tests/``: +Create a :rust:`.rs` file under :rust:`tests/`: -.. code:: rust,ignore +.. code:: rust // tests/my_library.rs use my_library::init; @@ -36,18 +36,18 @@ Rust has built-in support for documentation tests: /// Shortens a string to the given length. /// - /// ``` + /// :rust:` /// # use playground::shorten_string; /// assert_eq!(shorten_string("Hello World", 5), "Hello"); /// assert_eq!(shorten_string("Hello World", 20), "Hello World"); - /// ``` + /// :rust:` pub fn shorten_string(s: &str, length: usize) -> &str { &s[..std::cmp::min(length, s.len())] } -- Code blocks in ``///`` comments are automatically seen as Rust code. -- The code will be compiled and executed as part of ``cargo test``. -- Adding ``#`` in the code will hide it from the docs, but will still +- Code blocks in :rust:`///` comments are automatically seen as Rust code. +- The code will be compiled and executed as part of :rust:`cargo test`. +- Adding :rust:`#` in the code will hide it from the docs, but will still compile/run it. - Test the above code on the :url:`Rust Playground `. diff --git a/courses/comprehensive_rust_training/190_testing/03_lints.rst b/courses/comprehensive_rust_training/190_testing/03_lints.rst index 9c013adc8..f4807c5f0 100644 --- a/courses/comprehensive_rust_training/190_testing/03_lints.rst +++ b/courses/comprehensive_rust_training/190_testing/03_lints.rst @@ -10,7 +10,7 @@ The Rust compiler produces fantastic error messages, as well as helpful built-in lints. :url:`Clippy ` provides even more lints, organized into groups that can be enabled per-project. -.. code:: rust,editable,should_panic,warnunused +.. code:: rust #[deny(clippy::cast_possible_truncation)] fn main() { @@ -28,12 +28,12 @@ Details --------- There are compiler lints visible here, but not clippy lints. Run -``clippy`` on the playground site to show clippy warnings. Clippy has +:rust:`clippy` on the playground site to show clippy warnings. Clippy has extensive documentation of its lints, and adds new lints (including default-deny lints) all the time. -Note that errors or warnings with ``help: ...`` can be fixed with -``cargo fix`` or via your editor. +Note that errors or warnings with :rust:`help: ...` can be fixed with +:rust:`cargo fix` or via your editor. .. raw:: html diff --git a/courses/comprehensive_rust_training/190_testing/04_exercise.rst b/courses/comprehensive_rust_training/190_testing/04_exercise.rst index ddf5e2b28..94daa62ed 100644 --- a/courses/comprehensive_rust_training/190_testing/04_exercise.rst +++ b/courses/comprehensive_rust_training/190_testing/04_exercise.rst @@ -13,15 +13,15 @@ input and does the following to validate the credit card number: - Ignore all spaces. Reject numbers with fewer than two digits. - Moving from **right to left**, double every second digit: for the - number ``1234``, we double ``3`` and ``1``. For the number ``98765``, - we double ``6`` and ``8``. + number :rust:`1234`, we double :rust:`3` and :rust:`1`. For the number :rust:`98765`, + we double :rust:`6` and :rust:`8`. - After doubling a digit, sum the digits if the result is greater than - 9. So doubling ``7`` becomes ``14`` which becomes ``1 + 4 = 5``. + 9. So doubling :rust:`7` becomes :rust:`14` which becomes :rust:`1 + 4 = 5`. - Sum all the undoubled and doubled digits. -- The credit card number is valid if the sum ends with ``0``. +- The credit card number is valid if the sum ends with :rust:`0`. The provided code provides a buggy implementation of the luhn algorithm, along with two basic unit tests that confirm that most of the algorithm diff --git a/courses/comprehensive_rust_training/200_error_handling/01_panics.rst b/courses/comprehensive_rust_training/200_error_handling/01_panics.rst index 79499cab7..3164ade61 100644 --- a/courses/comprehensive_rust_training/200_error_handling/01_panics.rst +++ b/courses/comprehensive_rust_training/200_error_handling/01_panics.rst @@ -10,7 +10,7 @@ Rust handles fatal errors with a "panic". Rust will trigger a panic if a fatal error happens at runtime: -.. code:: rust,editable,should_panic +.. code:: rust fn main() { let v = vec![10, 20, 30]; @@ -21,12 +21,12 @@ Rust will trigger a panic if a fatal error happens at runtime: - Panics are symptoms of bugs in the program. - Runtime failures like failed bounds checks can panic - - Assertions (such as ``assert!``) panic on failure - - Purpose-specific panics can use the ``panic!`` macro. + - Assertions (such as :rust:`assert!`) panic on failure + - Purpose-specific panics can use the :rust:`panic!` macro. - A panic will "unwind" the stack, dropping values just as if the functions had returned. -- Use non-panicking APIs (such as ``Vec::get``) if crashing is not +- Use non-panicking APIs (such as :rust:`Vec::get`) if crashing is not acceptable. .. raw:: html @@ -38,7 +38,7 @@ Details By default, a panic will cause the stack to unwind. The unwinding can be caught: -.. code:: rust,editable +.. code:: rust use std::panic; @@ -53,11 +53,11 @@ caught: } - Catching is unusual; do not attempt to implement exceptions with - ``catch_unwind``! + :rust:`catch_unwind`! - This can be useful in servers which should keep running even if a single request crashes. -- This does not work if ``panic = 'abort'`` is set in your - ``Cargo.toml``. +- This does not work if :rust:`panic = 'abort'` is set in your + :rust:`Cargo.toml`. .. raw:: html diff --git a/courses/comprehensive_rust_training/200_error_handling/02_result.rst b/courses/comprehensive_rust_training/200_error_handling/02_result.rst index bc3aa5022..b99958a01 100644 --- a/courses/comprehensive_rust_training/200_error_handling/02_result.rst +++ b/courses/comprehensive_rust_training/200_error_handling/02_result.rst @@ -1,16 +1,16 @@ ============ -``Result`` +:rust:`Result` ============ ------------ -``Result`` +:rust:`Result` ------------ Our primary mechanism for error handling in Rust is the :url:`Result ` enum, which we briefly saw when discussing standard library types. -.. code:: rust,editable +.. code:: rust use std::fs::File; use std::io::Read; @@ -38,17 +38,17 @@ enum, which we briefly saw when discussing standard library types. Details --------- -- ``Result`` has two variants: ``Ok`` which contains the success value, - and ``Err`` which contains an error value of some kind. +- :rust:`Result` has two variants: :rust:`Ok` which contains the success value, + and :rust:`Err` which contains an error value of some kind. - Whether or not a function can produce an error is encoded in the - function's type signature by having the function return a ``Result`` + function's type signature by having the function return a :rust:`Result` value. -- Like with ``Option``, there is no way to forget to handle an error: +- Like with :rust:`Option`, there is no way to forget to handle an error: You cannot access either the success value or the error value without - first pattern matching on the ``Result`` to check which variant you - have. Methods like ``unwrap`` make it easier to write quick-and-dirty + first pattern matching on the :rust:`Result` to check which variant you + have. Methods like :rust:`unwrap` make it easier to write quick-and-dirty code that doesn't do robust error handling, but means that you can always see in your source code where proper error handling is being skipped. @@ -77,7 +77,7 @@ Exceptions throw an exception or not. - Exceptions generally unwind the call stack, propagating upward until - a ``try`` block is reached. An error originating deep in the call + a :rust:`try` block is reached. An error originating deep in the call stack may impact an unrelated function further up. --------------- diff --git a/courses/comprehensive_rust_training/200_error_handling/03_try.rst b/courses/comprehensive_rust_training/200_error_handling/03_try.rst index 2074a0289..81c16c7b0 100644 --- a/courses/comprehensive_rust_training/200_error_handling/03_try.rst +++ b/courses/comprehensive_rust_training/200_error_handling/03_try.rst @@ -7,11 +7,11 @@ Try Operator -------------- Runtime errors like connection-refused or file-not-found are handled -with the ``Result`` type, but matching this type on every call can be -cumbersome. The try-operator ``?`` is used to return errors to the +with the :rust:`Result` type, but matching this type on every call can be +cumbersome. The try-operator :rust:`?` is used to return errors to the caller. It lets you turn the common -.. code:: rust,ignore +.. code:: rust match some_expression { Ok(value) => value, @@ -20,13 +20,13 @@ caller. It lets you turn the common into the much simpler -.. code:: rust,ignore +.. code:: rust some_expression? We can use this to simplify our error handling code: -.. code:: rust,editable +.. code:: rust use std::io::Read; use std::{fs, io}; @@ -57,18 +57,18 @@ We can use this to simplify our error handling code: Details --------- -Simplify the ``read_username`` function to use ``?``. +Simplify the :rust:`read_username` function to use :rust:`?`. Key points: -- The ``username`` variable can be either ``Ok(string)`` or - ``Err(error)``. -- Use the ``fs::write`` call to test out the different scenarios: no +- The :rust:`username` variable can be either :rust:`Ok(string)` or + :rust:`Err(error)`. +- Use the :rust:`fs::write` call to test out the different scenarios: no file, empty file, file with username. -- Note that ``main`` can return a ``Result<(), E>`` as long as it - implements ``std::process::Termination``. In practice, this means - that ``E`` implements ``Debug``. The executable will print the - ``Err`` variant and return a nonzero exit status on error. +- Note that :rust:`main` can return a :rust:`Result<(), E>` as long as it + implements :rust:`std::process::Termination`. In practice, this means + that :rust:`E` implements :rust:`Debug`. The executable will print the + :rust:`Err` variant and return a nonzero exit status on error. .. raw:: html diff --git a/courses/comprehensive_rust_training/200_error_handling/04_try_conversions.rst b/courses/comprehensive_rust_training/200_error_handling/04_try_conversions.rst index aa772da79..2b8dc3bbf 100644 --- a/courses/comprehensive_rust_training/200_error_handling/04_try_conversions.rst +++ b/courses/comprehensive_rust_training/200_error_handling/04_try_conversions.rst @@ -6,23 +6,23 @@ Try Conversions Try Conversions ----------------- -The effective expansion of ``?`` is a little more complicated than +The effective expansion of :rust:`?` is a little more complicated than previously indicated: -.. code:: rust,ignore +.. code:: rust expression? works the same as -.. code:: rust,ignore +.. code:: rust match expression { Ok(value) => value, Err(err) => return Err(From::from(err)), } -The ``From::from`` call here means we attempt to convert the error type +The :rust:`From::from` call here means we attempt to convert the error type to the type returned by the function. This makes it easy to encapsulate errors into higher-level errors. @@ -30,7 +30,7 @@ errors into higher-level errors. Example --------- -.. code:: rust,editable +.. code:: rust use std::error::Error; use std::io::Read; @@ -80,24 +80,24 @@ Example Details --------- -The ``?`` operator must return a value compatible with the return type -of the function. For ``Result``, it means that the error types have to -be compatible. A function that returns ``Result`` can -only use ``?`` on a value of type ``Result`` if -``ErrorOuter`` and ``ErrorInner`` are the same type or if ``ErrorOuter`` -implements ``From``. +The :rust:`?` operator must return a value compatible with the return type +of the function. For :rust:`Result`, it means that the error types have to +be compatible. A function that returns :rust:`Result` can +only use :rust:`?` on a value of type :rust:`Result` if +:rust:`ErrorOuter` and :rust:`ErrorInner` are the same type or if :rust:`ErrorOuter` +implements :rust:`From`. -A common alternative to a ``From`` implementation is -``Result::map_err``, especially when the conversion only happens in one +A common alternative to a :rust:`From` implementation is +:rust:`Result::map_err`, especially when the conversion only happens in one place. -There is no compatibility requirement for ``Option``. A function -returning ``Option`` can use the ``?`` operator on ``Option`` for -arbitrary ``T`` and ``U`` types. +There is no compatibility requirement for :rust:`Option`. A function +returning :rust:`Option` can use the :rust:`?` operator on :rust:`Option` for +arbitrary :rust:`T` and :rust:`U` types. -A function that returns ``Result`` cannot use ``?`` on ``Option`` and -vice versa. However, ``Option::ok_or`` converts ``Option`` to ``Result`` -whereas ``Result::ok`` turns ``Result`` into ``Option``. +A function that returns :rust:`Result` cannot use :rust:`?` on :rust:`Option` and +vice versa. However, :rust:`Option::ok_or` converts :rust:`Option` to :rust:`Result` +whereas :rust:`Result::ok` turns :rust:`Result` into :rust:`Option`. .. raw:: html diff --git a/courses/comprehensive_rust_training/200_error_handling/05_error.rst b/courses/comprehensive_rust_training/200_error_handling/05_error.rst index 465936d86..334051b20 100644 --- a/courses/comprehensive_rust_training/200_error_handling/05_error.rst +++ b/courses/comprehensive_rust_training/200_error_handling/05_error.rst @@ -8,10 +8,10 @@ Dynamic Error Types Sometimes we want to allow any type of error to be returned without writing our own enum covering all the different possibilities. The -``std::error::Error`` trait makes it easy to create a trait object that +:rust:`std::error::Error` trait makes it easy to create a trait object that can contain any error. -.. code:: rust,editable +.. code:: rust use std::error::Error; use std::fs; @@ -38,16 +38,16 @@ can contain any error. Details --------- -The ``read_count`` function can return ``std::io::Error`` (from file -operations) or ``std::num::ParseIntError`` (from ``String::parse``). +The :rust:`read_count` function can return :rust:`std::io::Error` (from file +operations) or :rust:`std::num::ParseIntError` (from :rust:`String::parse`). Boxing errors saves on code, but gives up the ability to cleanly handle different error cases differently in the program. As such it's generally -not a good idea to use ``Box`` in the public API of a +not a good idea to use :rust:`Box` in the public API of a library, but it can be a good option in a program where you just want to display the error message somewhere. -Make sure to implement the ``std::error::Error`` trait when defining a +Make sure to implement the :rust:`std::error::Error` trait when defining a custom error type so it can be boxed. .. raw:: html diff --git a/courses/comprehensive_rust_training/200_error_handling/06_thiserror.rst b/courses/comprehensive_rust_training/200_error_handling/06_thiserror.rst index 804ee042f..b8759d878 100644 --- a/courses/comprehensive_rust_training/200_error_handling/06_thiserror.rst +++ b/courses/comprehensive_rust_training/200_error_handling/06_thiserror.rst @@ -1,17 +1,17 @@ =============== -``thiserror`` +:rust:`thiserror` =============== --------------- -``thiserror`` +:rust:`thiserror` --------------- The :url:`thiserror ` crate provides macros to help avoid boilerplate when defining error types. It provides derive -macros that assist in implementing ``From``, ``Display``, and the -``Error`` trait. +macros that assist in implementing :rust:`From`, :rust:`Display`, and the +:rust:`Error` trait. -.. code:: rust,editable,compile_fail +.. code:: rust use std::io::Read; use std::{fs, io}; @@ -48,12 +48,12 @@ macros that assist in implementing ``From``, ``Display``, and the Details --------- -- The ``Error`` derive macro is provided by ``thiserror``, and has lots +- The :rust:`Error` derive macro is provided by :rust:`thiserror`, and has lots of useful attributes to help define error types in a compact way. -- The message from ``#[error]`` is used to derive the ``Display`` +- The message from :rust:`#[error]` is used to derive the :rust:`Display` trait. -- Note that the (``thiserror::``)\ ``Error`` derive macro, while it has - the effect of implementing the (``std::error::``)\ ``Error`` trait, +- Note that the (:rust:`thiserror::`)\ :rust:`Error` derive macro, while it has + the effect of implementing the (:rust:`std::error::`)\ :rust:`Error` trait, is not the same this; traits and macros do not share a namespace. .. raw:: html diff --git a/courses/comprehensive_rust_training/200_error_handling/07_anyhow.rst b/courses/comprehensive_rust_training/200_error_handling/07_anyhow.rst index 8ae8a4613..ad143202a 100644 --- a/courses/comprehensive_rust_training/200_error_handling/07_anyhow.rst +++ b/courses/comprehensive_rust_training/200_error_handling/07_anyhow.rst @@ -1,9 +1,9 @@ ============ -``anyhow`` +:rust:`anyhow` ============ ------------ -``anyhow`` +:rust:`anyhow` ------------ The :url:`anyhow ` crate provides a rich error @@ -15,7 +15,7 @@ This can be combined with the convenience macros from :url:`thiserror ` to avoid writing out trait impls explicitly for custom error types. -.. code:: rust,editable,compile_fail +.. code:: rust use anyhow::{bail, Context, Result}; use std::fs; @@ -52,19 +52,19 @@ trait impls explicitly for custom error types. Details --------- -- ``anyhow::Error`` is essentially a wrapper around ``Box``. +- :rust:`anyhow::Error` is essentially a wrapper around :rust:`Box`. As such it's again generally not a good choice for the public API of a library, but is widely used in applications. -- ``anyhow::Result`` is a type alias for - ``Result``. -- Functionality provided by ``anyhow::Error`` may be familiar to Go - developers, as it provides similar behavior to the Go ``error`` type - and ``Result`` is much like a Go ``(T, error)`` +- :rust:`anyhow::Result` is a type alias for + :rust:`Result`. +- Functionality provided by :rust:`anyhow::Error` may be familiar to Go + developers, as it provides similar behavior to the Go :rust:`error` type + and :rust:`Result` is much like a Go :rust:`(T, error)` (with the convention that only one element of the pair is meaningful). -- ``anyhow::Context`` is a trait implemented for the standard - ``Result`` and ``Option`` types. ``use anyhow::Context`` is necessary - to enable ``.context()`` and ``.with_context()`` on those types. +- :rust:`anyhow::Context` is a trait implemented for the standard + :rust:`Result` and :rust:`Option` types. :rust:`use anyhow::Context` is necessary + to enable :rust:`.context()` and :rust:`.with_context()` on those types. ================= More to Explore @@ -74,8 +74,8 @@ More to Explore More to Explore ----------------- -- ``anyhow::Error`` has support for downcasting, much like - ``std::any::Any``; the specific error type stored inside can be +- :rust:`anyhow::Error` has support for downcasting, much like + :rust:`std::any::Any`; the specific error type stored inside can be extracted for examination if desired with :url:`Error::downcast `. diff --git a/courses/comprehensive_rust_training/200_error_handling/08_exercise.rst b/courses/comprehensive_rust_training/200_error_handling/08_exercise.rst index b65584ce6..36ef2c0d5 100644 --- a/courses/comprehensive_rust_training/200_error_handling/08_exercise.rst +++ b/courses/comprehensive_rust_training/200_error_handling/08_exercise.rst @@ -8,12 +8,12 @@ Exercise: Rewriting with Result In this exercise we're revisiting the expression evaluator exercise that we did in day 2. Our initial solution ignores a possible error case: -Dividing by zero! Rewrite ``eval`` to instead use idiomatic error +Dividing by zero! Rewrite :rust:`eval` to instead use idiomatic error handling to handle this error case and return an error when it occurs. -We provide a simple ``DivideByZeroError`` type to use as the error type -for ``eval``. +We provide a simple :rust:`DivideByZeroError` type to use as the error type +for :rust:`eval`. -.. code:: rust,editable +.. code:: rust {{#include exercise.rs:types}} diff --git a/courses/comprehensive_rust_training/210_unsafe_rust/01_unsafe.rst b/courses/comprehensive_rust_training/210_unsafe_rust/01_unsafe.rst index 93800cc8b..fa63ef976 100644 --- a/courses/comprehensive_rust_training/210_unsafe_rust/01_unsafe.rst +++ b/courses/comprehensive_rust_training/210_unsafe_rust/01_unsafe.rst @@ -22,9 +22,9 @@ Unsafe Rust gives you access to five new capabilities: - Dereference raw pointers. - Access or modify mutable static variables. -- Access ``union`` fields. -- Call ``unsafe`` functions, including ``extern`` functions. -- Implement ``unsafe`` traits. +- Access :rust:`union` fields. +- Call :rust:`unsafe` functions, including :rust:`extern` functions. +- Implement :rust:`unsafe` traits. We will briefly cover unsafe capabilities next. For full details, please see diff --git a/courses/comprehensive_rust_training/210_unsafe_rust/02_dereferencing.rst b/courses/comprehensive_rust_training/210_unsafe_rust/02_dereferencing.rst index 2a1724f99..2c412b21d 100644 --- a/courses/comprehensive_rust_training/210_unsafe_rust/02_dereferencing.rst +++ b/courses/comprehensive_rust_training/210_unsafe_rust/02_dereferencing.rst @@ -6,9 +6,9 @@ Dereferencing Raw Pointers Dereferencing Raw Pointers ---------------------------- -Creating pointers is safe, but dereferencing them requires ``unsafe``: +Creating pointers is safe, but dereferencing them requires :rust:`unsafe`: -.. code:: rust,editable +.. code:: rust fn main() { let mut s = String::from("careful!"); @@ -42,7 +42,7 @@ Details --------- It is good practice (and required by the Android Rust style guide) to -write a comment for each ``unsafe`` block explaining how the code inside +write a comment for each :rust:`unsafe` block explaining how the code inside it satisfies the safety requirements of the unsafe operations it is doing. @@ -62,8 +62,8 @@ i.e.: In most cases the pointer must also be properly aligned. The "NOT SAFE" section gives an example of a common kind of UB bug: -``*r1`` has the ``'static`` lifetime, so ``r3`` has type -``&'static String``, and thus outlives ``s``. Creating a reference from +:rust:`*r1` has the :rust:`'static` lifetime, so :rust:`r3` has type +:rust:`&'static String`, and thus outlives :rust:`s`. Creating a reference from a pointer requires *great care*. .. raw:: html diff --git a/courses/comprehensive_rust_training/210_unsafe_rust/03_mutable_static.rst b/courses/comprehensive_rust_training/210_unsafe_rust/03_mutable_static.rst index cdbc9027d..1688e1246 100644 --- a/courses/comprehensive_rust_training/210_unsafe_rust/03_mutable_static.rst +++ b/courses/comprehensive_rust_training/210_unsafe_rust/03_mutable_static.rst @@ -8,7 +8,7 @@ Mutable Static Variables It is safe to read an immutable static variable: -.. code:: rust,editable +.. code:: rust static HELLO_WORLD: &str = "Hello, world!"; @@ -19,7 +19,7 @@ It is safe to read an immutable static variable: However, since data races can occur, it is unsafe to read and write mutable static variables: -.. code:: rust,editable +.. code:: rust static mut COUNTER: u32 = 0; @@ -47,11 +47,11 @@ Details - The program here is safe because it is single-threaded. However, the Rust compiler is conservative and will assume the worst. Try removing - the ``unsafe`` and see how the compiler explains that it is undefined + the :rust:`unsafe` and see how the compiler explains that it is undefined behavior to mutate a static from multiple threads. - Using a mutable static is generally a bad idea, but there are some - cases where it might make sense in low-level ``no_std`` code, such as + cases where it might make sense in low-level :rust:`no_std` code, such as implementing a heap allocator or working with some C APIs. .. raw:: html diff --git a/courses/comprehensive_rust_training/210_unsafe_rust/04_unions.rst b/courses/comprehensive_rust_training/210_unsafe_rust/04_unions.rst index b8952eaf3..0600dbb66 100644 --- a/courses/comprehensive_rust_training/210_unsafe_rust/04_unions.rst +++ b/courses/comprehensive_rust_training/210_unsafe_rust/04_unions.rst @@ -8,7 +8,7 @@ Unions Unions are like enums, but you need to track the active field yourself: -.. code:: rust,editable +.. code:: rust #[repr(C)] union MyUnion { diff --git a/courses/comprehensive_rust_training/210_unsafe_rust/05_unsafe_functions.rst b/courses/comprehensive_rust_training/210_unsafe_rust/05_unsafe_functions.rst index edccdc7a8..1052738a0 100644 --- a/courses/comprehensive_rust_training/210_unsafe_rust/05_unsafe_functions.rst +++ b/courses/comprehensive_rust_training/210_unsafe_rust/05_unsafe_functions.rst @@ -10,10 +10,10 @@ Unsafe Functions Calling Unsafe Functions -------------------------- -A function or method can be marked ``unsafe`` if it has extra +A function or method can be marked :rust:`unsafe` if it has extra preconditions you must uphold to avoid undefined behaviour: -.. code:: rust,editable +.. code:: rust extern "C" { fn abs(input: i32) -> i32; @@ -52,10 +52,10 @@ preconditions you must uphold to avoid undefined behaviour: Writing Unsafe Functions -------------------------- -You can mark your own functions as ``unsafe`` if they require particular +You can mark your own functions as :rust:`unsafe` if they require particular conditions to avoid undefined behaviour. -.. code:: rust,editable +.. code:: rust /// Swaps the values pointed to by the given pointers. /// @@ -92,15 +92,15 @@ Details Calling Unsafe Functions -------------------------- -``get_unchecked``, like most ``_unchecked`` functions, is unsafe, -because it can create UB if the range is incorrect. ``abs`` is unsafe +:rust:`get_unchecked`, like most :rust:`_unchecked` functions, is unsafe, +because it can create UB if the range is incorrect. :rust:`abs` is unsafe for a different reason: it is an external function (FFI). Calling external functions is usually only a problem when those functions do things with pointers which might violate Rust's memory model, but in general any C function might have undefined behaviour under any arbitrary circumstances. -The ``"C"`` in this example is the ABI; +The :rust:`"C"` in this example is the ABI; :url:`other ABIs are available too `. .. _writing-unsafe-functions-1: @@ -109,12 +109,12 @@ The ``"C"`` in this example is the ABI; Writing Unsafe Functions -------------------------- -We wouldn't actually use pointers for a ``swap`` function - it can be +We wouldn't actually use pointers for a :rust:`swap` function - it can be done safely with references. Note that unsafe code is allowed within an unsafe function without an -``unsafe`` block. We can prohibit this with -``#[deny(unsafe_op_in_unsafe_fn)]``. Try adding it and see what happens. +:rust:`unsafe` block. We can prohibit this with +:rust:`#[deny(unsafe_op_in_unsafe_fn)]`. Try adding it and see what happens. This will likely change in a future Rust edition. .. raw:: html diff --git a/courses/comprehensive_rust_training/210_unsafe_rust/06_unsafe_traits.rst b/courses/comprehensive_rust_training/210_unsafe_rust/06_unsafe_traits.rst index afcacd5c4..c27cecedc 100644 --- a/courses/comprehensive_rust_training/210_unsafe_rust/06_unsafe_traits.rst +++ b/courses/comprehensive_rust_training/210_unsafe_rust/06_unsafe_traits.rst @@ -6,14 +6,14 @@ Implementing Unsafe Traits Implementing Unsafe Traits ---------------------------- -Like with functions, you can mark a trait as ``unsafe`` if the +Like with functions, you can mark a trait as :rust:`unsafe` if the implementation must guarantee particular conditions to avoid undefined behaviour. -For example, the ``zerocopy`` crate has an unsafe trait that looks +For example, the :rust:`zerocopy` crate has an unsafe trait that looks :url:`something like this `: -.. code:: rust,editable +.. code:: rust use std::{mem, slice}; @@ -37,13 +37,13 @@ For example, the ``zerocopy`` crate has an unsafe trait that looks Details --------- -There should be a ``# Safety`` section on the Rustdoc for the trait +There should be a :rust:`# Safety` section on the Rustdoc for the trait explaining the requirements for the trait to be safely implemented. -The actual safety section for ``IntoBytes`` is rather longer and more +The actual safety section for :rust:`IntoBytes` is rather longer and more complicated. -The built-in ``Send`` and ``Sync`` traits are unsafe. +The built-in :rust:`Send` and :rust:`Sync` traits are unsafe. .. raw:: html diff --git a/courses/comprehensive_rust_training/210_unsafe_rust/07_exercise.rst b/courses/comprehensive_rust_training/210_unsafe_rust/07_exercise.rst index 8c00b46b7..cd475d4f4 100644 --- a/courses/comprehensive_rust_training/210_unsafe_rust/07_exercise.rst +++ b/courses/comprehensive_rust_training/210_unsafe_rust/07_exercise.rst @@ -8,7 +8,7 @@ Safe FFI Wrapper Rust has great support for calling functions through a *foreign function interface* (FFI). We will use this to build a safe wrapper for the -``libc`` functions you would use from C to read the names of files in a +:rust:`libc` functions you would use from C to read the names of files in a directory. You will want to consult the manual pages: @@ -42,19 +42,19 @@ find a number of string types which you need for the exercise: You will convert between all these types: -- ``&str`` to ``CString``: you need to allocate space for a trailing - ``\0`` character, -- ``CString`` to ``*const i8``: you need a pointer to call C functions, -- ``*const i8`` to ``&CStr``: you need something which can find the - trailing ``\0`` character, -- ``&CStr`` to ``&[u8]``: a slice of bytes is the universal interface +- :rust:`&str` to :rust:`CString`: you need to allocate space for a trailing + :rust:`\0` character, +- :rust:`CString` to :rust:`*const i8`: you need a pointer to call C functions, +- :rust:`*const i8` to :rust:`&CStr`: you need something which can find the + trailing :rust:`\0` character, +- :rust:`&CStr` to :rust:`&[u8]`: a slice of bytes is the universal interface for "some unknown data", -- ``&[u8]`` to ``&OsStr``: ``&OsStr`` is a step towards ``OsString``, +- :rust:`&[u8]` to :rust:`&OsStr`: :rust:`&OsStr` is a step towards :rust:`OsString`, use :url:`OsStrExt ` to create it, -- ``&OsStr`` to ``OsString``: you need to clone the data in ``&OsStr`` - to be able to return it and call ``readdir`` again. +- :rust:`&OsStr` to :rust:`OsString`: you need to clone the data in :rust:`&OsStr` + to be able to return it and call :rust:`readdir` again. The :url:`Nomicon ` also has a very useful chapter about FFI. @@ -62,7 +62,7 @@ very useful chapter about FFI. Copy the code below to https://play.rust-lang.org/ and fill in the missing functions and methods: -.. code:: rust,should_panic +.. code:: rust // TODO: remove this when you're done with your implementation. #![allow(unused_imports, unused_variables, dead_code)] From ea86f3cf06ea29b73256058da4704b0bbaba2dc9 Mon Sep 17 00:00:00 2001 From: Michael Frank <55284511+frank-at-adacore@users.noreply.github.com> Date: Thu, 13 Feb 2025 13:19:14 -0500 Subject: [PATCH 2/4] Remove rust role from section/slide titles --- .../030_types_and_values/03_values.rst | 20 +++++++++---------- .../040_control_flow_basics/01_if.rst | 4 ++-- .../040_control_flow_basics/02_match.rst | 4 ++-- .../040_control_flow_basics/03_loops.rst | 2 +- .../04_break_continue.rst | 4 ++-- .../070_user_defined_types/05_const.rst | 4 ++-- .../070_user_defined_types/06_static.rst | 4 ++-- .../04_let_control_flow.rst | 8 ++++---- .../100_generics/05_impl_trait.rst | 4 ++-- .../100_generics/06_dyn_trait.rst | 4 ++-- .../100_generics/07_exercise.rst | 4 ++-- .../110_std_types/06_vec.rst | 4 ++-- .../110_std_types/07_hashmap.rst | 4 ++-- .../120_std_traits/01_comparisons.rst | 4 ++-- .../120_std_traits/03_from_and_into.rst | 4 ++-- .../120_std_traits/05_read_and_write.rst | 4 ++-- .../120_std_traits/06_default.rst | 4 ++-- .../130_memory_management/07_drop.rst | 4 ++-- .../140_smart_pointers/01_box.rst | 4 ++-- .../140_smart_pointers/02_rc.rst | 4 ++-- .../170_iterators/02_iterator.rst | 4 ++-- .../170_iterators/03_helpers.rst | 4 ++-- .../170_iterators/04_collect.rst | 4 ++-- .../170_iterators/05_intoiterator.rst | 4 ++-- .../200_error_handling/02_result.rst | 4 ++-- .../200_error_handling/06_thiserror.rst | 4 ++-- .../200_error_handling/07_anyhow.rst | 4 ++-- 27 files changed, 63 insertions(+), 63 deletions(-) diff --git a/courses/comprehensive_rust_training/030_types_and_values/03_values.rst b/courses/comprehensive_rust_training/030_types_and_values/03_values.rst index 0a4298578..fbae25fff 100644 --- a/courses/comprehensive_rust_training/030_types_and_values/03_values.rst +++ b/courses/comprehensive_rust_training/030_types_and_values/03_values.rst @@ -12,22 +12,22 @@ each type. +---------------+-------------------------------+---------------------+ | | Types | Literals | +===============+===============================+=====================+ -| Signed | :rust:`i8`, :rust:`i16`, :rust:`i32`, | :rust:`-10`, :rust:`0`, | -| integers | :rust:`i64`, :rust:`i128`, :rust:`isize` | :rust:`1_000`, | -| | | :rust:`123_i64` | +| Signed | ``i8``, ``i16``, ``i32``, | ``-10``, ``0``, | +| integers | ``i64``, ``i128``, ``isize`` | ``1_000``, | +| | | ``123_i64`` | +---------------+-------------------------------+---------------------+ -| Unsigned | :rust:`u8`, :rust:`u16`, :rust:`u32`, | :rust:`0`, :rust:`123`, | -| integers | :rust:`u64`, :rust:`u128`, :rust:`usize` | :rust:`10_u16` | +| Unsigned | ``u8``, ``u16``, ``u32``, | ``0``, ``123``, | +| integers | ``u64``, ``u128``, ``usize`` | ``10_u16`` | +---------------+-------------------------------+---------------------+ -| Floating | :rust:`f32`, :rust:`f64` | :rust:`3.14`, | -| point numbers | | :rust:`-10.0e20`, | -| | | :rust:`2_f32` | +| Floating | ``f32``, ``f64`` | ``3.14``, | +| point numbers | | ``-10.0e20``, | +| | | ``2_f32`` | +---------------+-------------------------------+---------------------+ -| Unicode | :rust:`char` | :rust:`'a'`, | +| Unicode | ``char`` | ``'a'``, | | scalar values | | ':math:`\alpha`', | | | | ':math:`\infty`' | +---------------+-------------------------------+---------------------+ -| Booleans | :rust:`bool` | :rust:`true`, :rust:`false` | +| Booleans | ``bool`` | ``true``, ``false`` | +---------------+-------------------------------+---------------------+ The types have widths as follows: diff --git a/courses/comprehensive_rust_training/040_control_flow_basics/01_if.rst b/courses/comprehensive_rust_training/040_control_flow_basics/01_if.rst index 772529051..ea428507a 100644 --- a/courses/comprehensive_rust_training/040_control_flow_basics/01_if.rst +++ b/courses/comprehensive_rust_training/040_control_flow_basics/01_if.rst @@ -1,9 +1,9 @@ ==================== -:rust:`if` expressions +"if" expressions ==================== -------------------- -:rust:`if` expressions +"if" expressions -------------------- You use diff --git a/courses/comprehensive_rust_training/040_control_flow_basics/02_match.rst b/courses/comprehensive_rust_training/040_control_flow_basics/02_match.rst index f44938dd1..164693f65 100644 --- a/courses/comprehensive_rust_training/040_control_flow_basics/02_match.rst +++ b/courses/comprehensive_rust_training/040_control_flow_basics/02_match.rst @@ -1,9 +1,9 @@ ======================= -:rust:`match` Expressions +"match" Expressions ======================= ----------------------- -:rust:`match` Expressions +"match" Expressions ----------------------- :rust:`match` can be used to check a value against one or more options: diff --git a/courses/comprehensive_rust_training/040_control_flow_basics/03_loops.rst b/courses/comprehensive_rust_training/040_control_flow_basics/03_loops.rst index b1090b2e9..2ea6d49b9 100644 --- a/courses/comprehensive_rust_training/040_control_flow_basics/03_loops.rst +++ b/courses/comprehensive_rust_training/040_control_flow_basics/03_loops.rst @@ -10,7 +10,7 @@ There are three looping keywords in Rust: :rust:`while`, :rust:`loop`, and :rust:`for`: ----------- -:rust:`while` +"while" ----------- The diff --git a/courses/comprehensive_rust_training/040_control_flow_basics/04_break_continue.rst b/courses/comprehensive_rust_training/040_control_flow_basics/04_break_continue.rst index 9966172f2..83209e250 100644 --- a/courses/comprehensive_rust_training/040_control_flow_basics/04_break_continue.rst +++ b/courses/comprehensive_rust_training/040_control_flow_basics/04_break_continue.rst @@ -1,9 +1,9 @@ ============================ -:rust:`break` and :rust:`continue` +"break" and "continue" ============================ ---------------------------- -:rust:`break` and :rust:`continue` +"break" and "continue" ---------------------------- If you want to immediately start the next iteration use diff --git a/courses/comprehensive_rust_training/070_user_defined_types/05_const.rst b/courses/comprehensive_rust_training/070_user_defined_types/05_const.rst index 419a4cba7..a76861515 100644 --- a/courses/comprehensive_rust_training/070_user_defined_types/05_const.rst +++ b/courses/comprehensive_rust_training/070_user_defined_types/05_const.rst @@ -1,9 +1,9 @@ =========== -:rust:`const` +"const" =========== ----------- -:rust:`const` +"const" ----------- Constants are evaluated at compile time and their values are inlined diff --git a/courses/comprehensive_rust_training/070_user_defined_types/06_static.rst b/courses/comprehensive_rust_training/070_user_defined_types/06_static.rst index 4f75a5fab..81e08c816 100644 --- a/courses/comprehensive_rust_training/070_user_defined_types/06_static.rst +++ b/courses/comprehensive_rust_training/070_user_defined_types/06_static.rst @@ -1,9 +1,9 @@ ============ -:rust:`static` +"static" ============ ------------ -:rust:`static` +"static" ------------ Static variables will live during the whole execution of the program, diff --git a/courses/comprehensive_rust_training/080_pattern_matching/04_let_control_flow.rst b/courses/comprehensive_rust_training/080_pattern_matching/04_let_control_flow.rst index 20464b901..199920c90 100644 --- a/courses/comprehensive_rust_training/080_pattern_matching/04_let_control_flow.rst +++ b/courses/comprehensive_rust_training/080_pattern_matching/04_let_control_flow.rst @@ -14,11 +14,11 @@ languages. They are used for pattern matching: - :rust:`while let` expressions ======================== -:rust:`if let` expressions +"if let" expressions ======================== ------------------------ -:rust:`if let` expressions +"if let" expressions ------------------------ The @@ -43,11 +43,11 @@ pattern: } ========================== -:rust:`let else` expressions +"let else" expressions ========================== -------------------------- -:rust:`let else` expressions +"let else" expressions -------------------------- For the common case of matching a pattern and returning from the diff --git a/courses/comprehensive_rust_training/100_generics/05_impl_trait.rst b/courses/comprehensive_rust_training/100_generics/05_impl_trait.rst index db1761b6b..d98326492 100644 --- a/courses/comprehensive_rust_training/100_generics/05_impl_trait.rst +++ b/courses/comprehensive_rust_training/100_generics/05_impl_trait.rst @@ -1,9 +1,9 @@ ================ -:rust:`impl Trait` +"impl Trait" ================ ---------------- -:rust:`impl Trait` +"impl Trait" ---------------- Similar to trait bounds, an :rust:`impl Trait` syntax can be used in diff --git a/courses/comprehensive_rust_training/100_generics/06_dyn_trait.rst b/courses/comprehensive_rust_training/100_generics/06_dyn_trait.rst index c529d5c2f..d951d7a50 100644 --- a/courses/comprehensive_rust_training/100_generics/06_dyn_trait.rst +++ b/courses/comprehensive_rust_training/100_generics/06_dyn_trait.rst @@ -1,9 +1,9 @@ =============== -:rust:`dyn Trait` +"dyn Trait" =============== --------------- -:rust:`dyn Trait` +"dyn Trait" --------------- In addition to using traits for static dispatch via generics, Rust also diff --git a/courses/comprehensive_rust_training/100_generics/07_exercise.rst b/courses/comprehensive_rust_training/100_generics/07_exercise.rst index 804ec88fc..1efc4e191 100644 --- a/courses/comprehensive_rust_training/100_generics/07_exercise.rst +++ b/courses/comprehensive_rust_training/100_generics/07_exercise.rst @@ -1,9 +1,9 @@ =========================== -Exercise: Generic :rust:`min` +Exercise: Generic "min" =========================== --------------------------- -Exercise: Generic :rust:`min` +Exercise: Generic "min" --------------------------- In this short exercise, you will implement a generic :rust:`min` function diff --git a/courses/comprehensive_rust_training/110_std_types/06_vec.rst b/courses/comprehensive_rust_training/110_std_types/06_vec.rst index 83c1e361f..0d652e4de 100644 --- a/courses/comprehensive_rust_training/110_std_types/06_vec.rst +++ b/courses/comprehensive_rust_training/110_std_types/06_vec.rst @@ -1,9 +1,9 @@ ========= -:rust:`Vec` +"Vec" ========= --------- -:rust:`Vec` +"Vec" --------- :url:`Vec ` is the diff --git a/courses/comprehensive_rust_training/110_std_types/07_hashmap.rst b/courses/comprehensive_rust_training/110_std_types/07_hashmap.rst index b172e0de3..e157cd7e1 100644 --- a/courses/comprehensive_rust_training/110_std_types/07_hashmap.rst +++ b/courses/comprehensive_rust_training/110_std_types/07_hashmap.rst @@ -1,9 +1,9 @@ ============= -:rust:`HashMap` +"HashMap" ============= ------------- -:rust:`HashMap` +"HashMap" ------------- Standard hash map with protection against HashDoS attacks: diff --git a/courses/comprehensive_rust_training/120_std_traits/01_comparisons.rst b/courses/comprehensive_rust_training/120_std_traits/01_comparisons.rst index 9b22ab1db..0db878fd5 100644 --- a/courses/comprehensive_rust_training/120_std_traits/01_comparisons.rst +++ b/courses/comprehensive_rust_training/120_std_traits/01_comparisons.rst @@ -10,7 +10,7 @@ These traits support comparisons between values. All traits can be derived for types containing fields that implement these traits. -------------------------- -:rust:`PartialEq` and :rust:`Eq` +"PartialEq" and "Eq" -------------------------- :rust:`PartialEq` is a partial equivalence relation, with required method @@ -34,7 +34,7 @@ transitive) and implies :rust:`PartialEq`. Functions that require full equivalence will use :rust:`Eq` as a trait bound. ---------------------------- -:rust:`PartialOrd` and :rust:`Ord` +"PartialOrd" and "Ord" ---------------------------- :rust:`PartialOrd` defines a partial ordering, with a :rust:`partial_cmp` diff --git a/courses/comprehensive_rust_training/120_std_traits/03_from_and_into.rst b/courses/comprehensive_rust_training/120_std_traits/03_from_and_into.rst index 5acf328cd..e10e46398 100644 --- a/courses/comprehensive_rust_training/120_std_traits/03_from_and_into.rst +++ b/courses/comprehensive_rust_training/120_std_traits/03_from_and_into.rst @@ -1,9 +1,9 @@ ======================= -:rust:`From` and :rust:`Into` +"From" and "Into" ======================= ----------------------- -:rust:`From` and :rust:`Into` +"From" and "Into" ----------------------- Types implement diff --git a/courses/comprehensive_rust_training/120_std_traits/05_read_and_write.rst b/courses/comprehensive_rust_training/120_std_traits/05_read_and_write.rst index 7a5294774..23f4d6531 100644 --- a/courses/comprehensive_rust_training/120_std_traits/05_read_and_write.rst +++ b/courses/comprehensive_rust_training/120_std_traits/05_read_and_write.rst @@ -1,9 +1,9 @@ ======================== -:rust:`Read` and :rust:`Write` +"Read" and "Write" ======================== ------------------------ -:rust:`Read` and :rust:`Write` +"Read" and "Write" ------------------------ Using :url:`Read ` diff --git a/courses/comprehensive_rust_training/120_std_traits/06_default.rst b/courses/comprehensive_rust_training/120_std_traits/06_default.rst index dea5fb8a6..3565df09a 100644 --- a/courses/comprehensive_rust_training/120_std_traits/06_default.rst +++ b/courses/comprehensive_rust_training/120_std_traits/06_default.rst @@ -1,9 +1,9 @@ ======================= -The :rust:`Default` Trait +The "Default" Trait ======================= ----------------------- -The :rust:`Default` Trait +The "Default" Trait ----------------------- :url:`Default ` diff --git a/courses/comprehensive_rust_training/130_memory_management/07_drop.rst b/courses/comprehensive_rust_training/130_memory_management/07_drop.rst index fa9c82639..fe1c4323c 100644 --- a/courses/comprehensive_rust_training/130_memory_management/07_drop.rst +++ b/courses/comprehensive_rust_training/130_memory_management/07_drop.rst @@ -1,9 +1,9 @@ ==================== -The :rust:`Drop` Trait +The "Drop" Trait ==================== -------------------- -The :rust:`Drop` Trait +The "Drop" Trait -------------------- Values which implement diff --git a/courses/comprehensive_rust_training/140_smart_pointers/01_box.rst b/courses/comprehensive_rust_training/140_smart_pointers/01_box.rst index 2a3ac5bdb..9dc5f1d09 100644 --- a/courses/comprehensive_rust_training/140_smart_pointers/01_box.rst +++ b/courses/comprehensive_rust_training/140_smart_pointers/01_box.rst @@ -1,9 +1,9 @@ ============ -:rust:`Box` +"Box" ============ ------------ -:rust:`Box` +"Box" ------------ :url:`Box ` is an diff --git a/courses/comprehensive_rust_training/140_smart_pointers/02_rc.rst b/courses/comprehensive_rust_training/140_smart_pointers/02_rc.rst index bbd03cc39..880a2f010 100644 --- a/courses/comprehensive_rust_training/140_smart_pointers/02_rc.rst +++ b/courses/comprehensive_rust_training/140_smart_pointers/02_rc.rst @@ -1,9 +1,9 @@ ======== -:rust:`Rc` +"Rc" ======== -------- -:rust:`Rc` +"Rc" -------- :url:`Rc ` is a diff --git a/courses/comprehensive_rust_training/170_iterators/02_iterator.rst b/courses/comprehensive_rust_training/170_iterators/02_iterator.rst index 65ebffccc..df4645b5b 100644 --- a/courses/comprehensive_rust_training/170_iterators/02_iterator.rst +++ b/courses/comprehensive_rust_training/170_iterators/02_iterator.rst @@ -1,9 +1,9 @@ ==================== -:rust:`Iterator` Trait +"Iterator" Trait ==================== -------------------- -:rust:`Iterator` Trait +"Iterator" Trait -------------------- The diff --git a/courses/comprehensive_rust_training/170_iterators/03_helpers.rst b/courses/comprehensive_rust_training/170_iterators/03_helpers.rst index 36055d910..b5d3bf542 100644 --- a/courses/comprehensive_rust_training/170_iterators/03_helpers.rst +++ b/courses/comprehensive_rust_training/170_iterators/03_helpers.rst @@ -1,9 +1,9 @@ ============================= -:rust:`Iterator` Helper Methods +"Iterator" Helper Methods ============================= ----------------------------- -:rust:`Iterator` Helper Methods +"Iterator" Helper Methods ----------------------------- In addition to the :rust:`next` method that defines how an iterator behaves, diff --git a/courses/comprehensive_rust_training/170_iterators/04_collect.rst b/courses/comprehensive_rust_training/170_iterators/04_collect.rst index 25146fe1b..b06a763ac 100644 --- a/courses/comprehensive_rust_training/170_iterators/04_collect.rst +++ b/courses/comprehensive_rust_training/170_iterators/04_collect.rst @@ -1,9 +1,9 @@ ============= -:rust:`collect` +"collect" ============= ------------- -:rust:`collect` +"collect" ------------- The diff --git a/courses/comprehensive_rust_training/170_iterators/05_intoiterator.rst b/courses/comprehensive_rust_training/170_iterators/05_intoiterator.rst index b655a76b1..e8c2bbd3d 100644 --- a/courses/comprehensive_rust_training/170_iterators/05_intoiterator.rst +++ b/courses/comprehensive_rust_training/170_iterators/05_intoiterator.rst @@ -1,9 +1,9 @@ ================== -:rust:`IntoIterator` +"IntoIterator" ================== ------------------ -:rust:`IntoIterator` +"IntoIterator" ------------------ The :rust:`Iterator` trait tells you how to *iterate* once you have created diff --git a/courses/comprehensive_rust_training/200_error_handling/02_result.rst b/courses/comprehensive_rust_training/200_error_handling/02_result.rst index b99958a01..b8e166d18 100644 --- a/courses/comprehensive_rust_training/200_error_handling/02_result.rst +++ b/courses/comprehensive_rust_training/200_error_handling/02_result.rst @@ -1,9 +1,9 @@ ============ -:rust:`Result` +"Result" ============ ------------ -:rust:`Result` +"Result" ------------ Our primary mechanism for error handling in Rust is the diff --git a/courses/comprehensive_rust_training/200_error_handling/06_thiserror.rst b/courses/comprehensive_rust_training/200_error_handling/06_thiserror.rst index b8759d878..ebe923d06 100644 --- a/courses/comprehensive_rust_training/200_error_handling/06_thiserror.rst +++ b/courses/comprehensive_rust_training/200_error_handling/06_thiserror.rst @@ -1,9 +1,9 @@ =============== -:rust:`thiserror` +"thiserror" =============== --------------- -:rust:`thiserror` +"thiserror" --------------- The :url:`thiserror ` crate provides macros diff --git a/courses/comprehensive_rust_training/200_error_handling/07_anyhow.rst b/courses/comprehensive_rust_training/200_error_handling/07_anyhow.rst index ad143202a..702d0fb45 100644 --- a/courses/comprehensive_rust_training/200_error_handling/07_anyhow.rst +++ b/courses/comprehensive_rust_training/200_error_handling/07_anyhow.rst @@ -1,9 +1,9 @@ ============ -:rust:`anyhow` +"anyhow" ============ ------------ -:rust:`anyhow` +"anyhow" ------------ The :url:`anyhow ` crate provides a rich error From 543e003e2da424006279bca46c4697ae6db9b75d Mon Sep 17 00:00:00 2001 From: Michael Frank <55284511+frank-at-adacore@users.noreply.github.com> Date: Thu, 13 Feb 2025 17:38:26 -0500 Subject: [PATCH 3/4] Update some inline literals to their correct role --- .../020_hello_world/01_what_is_rust.rst | 2 +- .../110_std_types/02_docs.rst | 2 +- .../130_memory_management/02_approaches.rst | 4 ++-- .../130_memory_management/04_move.rst | 2 +- .../160_lifetimes/04_exercise.rst | 2 +- .../180_modules/01_modules.rst | 2 +- .../180_modules/02_filesystem.rst | 18 +++++++++--------- .../180_modules/06_exercise.rst | 4 ++-- .../190_testing/01_unit_tests.rst | 2 +- .../190_testing/02_other.rst | 4 ++-- .../190_testing/03_lints.rst | 2 +- 11 files changed, 22 insertions(+), 22 deletions(-) diff --git a/courses/comprehensive_rust_training/020_hello_world/01_what_is_rust.rst b/courses/comprehensive_rust_training/020_hello_world/01_what_is_rust.rst index 58845362a..02a98a5ae 100644 --- a/courses/comprehensive_rust_training/020_hello_world/01_what_is_rust.rst +++ b/courses/comprehensive_rust_training/020_hello_world/01_what_is_rust.rst @@ -11,7 +11,7 @@ Rust is a new programming language which had its `1.0 release in - Rust is a statically compiled language in a similar role as C++ - - :rust:`rustc` uses LLVM as its backend. + - :command:`rustc` uses LLVM as its backend. - Rust supports many `platforms and architectures `__: diff --git a/courses/comprehensive_rust_training/110_std_types/02_docs.rst b/courses/comprehensive_rust_training/110_std_types/02_docs.rst index 04af9bffc..e37081c61 100644 --- a/courses/comprehensive_rust_training/110_std_types/02_docs.rst +++ b/courses/comprehensive_rust_training/110_std_types/02_docs.rst @@ -17,7 +17,7 @@ Rust comes with extensive documentation. For example: or :url:`BinaryHeap `. -Use :rust:`rustup doc --std` or https://std.rs to view the documentation. +Use :filename:`rustup doc --std` or https://std.rs to view the documentation. In fact, you can document your own code: diff --git a/courses/comprehensive_rust_training/130_memory_management/02_approaches.rst b/courses/comprehensive_rust_training/130_memory_management/02_approaches.rst index 67a2db382..8dbe60b5d 100644 --- a/courses/comprehensive_rust_training/130_memory_management/02_approaches.rst +++ b/courses/comprehensive_rust_training/130_memory_management/02_approaches.rst @@ -39,8 +39,8 @@ Details This slide is intended to help students coming from other languages to put Rust in context. -- C must manage heap manually with :rust:`malloc` and :rust:`free`. Common - errors include forgetting to call :rust:`free`, calling it multiple times +- C must manage heap manually with :cpp:`malloc` and :cpp:`free`. Common + errors include forgetting to call :cpp:`free`, calling it multiple times for the same pointer, or dereferencing a pointer after the memory it points to has been freed. diff --git a/courses/comprehensive_rust_training/130_memory_management/04_move.rst b/courses/comprehensive_rust_training/130_memory_management/04_move.rst index 2c5145099..99da27ea3 100644 --- a/courses/comprehensive_rust_training/130_memory_management/04_move.rst +++ b/courses/comprehensive_rust_training/130_memory_management/04_move.rst @@ -188,7 +188,7 @@ Key points: unspecified state. Unlike Rust, the programmer is allowed to keep using :rust:`s1`. -- Unlike Rust, :rust:`=` in C++ can run arbitrary code as determined by the +- Unlike Rust, :cpp:`=` in C++ can run arbitrary code as determined by the type which is being copied or moved. .. raw:: html diff --git a/courses/comprehensive_rust_training/160_lifetimes/04_exercise.rst b/courses/comprehensive_rust_training/160_lifetimes/04_exercise.rst index 5c30108d9..4fd86882b 100644 --- a/courses/comprehensive_rust_training/160_lifetimes/04_exercise.rst +++ b/courses/comprehensive_rust_training/160_lifetimes/04_exercise.rst @@ -14,7 +14,7 @@ copied. Fully parsing a protobuf message requires knowing the types of the fields, indexed by their field numbers. That is typically provided in a -:rust:`proto` file. In this exercise, we'll encode that information into +:filename:`proto` file. In this exercise, we'll encode that information into :rust:`match` statements in functions that get called for each field. We'll use the following proto: diff --git a/courses/comprehensive_rust_training/180_modules/01_modules.rst b/courses/comprehensive_rust_training/180_modules/01_modules.rst index 8e0acda4e..38a8f3958 100644 --- a/courses/comprehensive_rust_training/180_modules/01_modules.rst +++ b/courses/comprehensive_rust_training/180_modules/01_modules.rst @@ -35,7 +35,7 @@ Similarly, :rust:`mod` lets us namespace types and functions: Details --------- -- Packages provide functionality and include a :rust:`Cargo.toml` file that +- Packages provide functionality and include a :filename:`Cargo.toml` file that describes how to build a bundle of 1+ crates. - Crates are a tree of modules, where a binary crate creates an executable and a library crate compiles to a library. diff --git a/courses/comprehensive_rust_training/180_modules/02_filesystem.rst b/courses/comprehensive_rust_training/180_modules/02_filesystem.rst index 734559852..83aee581a 100644 --- a/courses/comprehensive_rust_training/180_modules/02_filesystem.rst +++ b/courses/comprehensive_rust_training/180_modules/02_filesystem.rst @@ -14,13 +14,13 @@ file: mod garden; This tells Rust that the :rust:`garden` module content is found at -:rust:`src/garden.rs`. Similarly, a :rust:`garden::vegetables` module can be -found at :rust:`src/garden/vegetables.rs`. +:filename:`src/garden.rs`. Similarly, a :rust:`garden::vegetables` module can be +found at :filename:`src/garden/vegetables.rs`. The :rust:`crate` root is in: -- :rust:`src/lib.rs` (for a library crate) -- :rust:`src/main.rs` (for a binary crate) +- :filename:`src/lib.rs` (for a library crate) +- :filename:`src/main.rs` (for a binary crate) Modules defined in files can be documented, too, using "inner doc comments". These document the item that contains them - in this case, a @@ -51,12 +51,12 @@ module. Details --------- -- Before Rust 2018, modules needed to be located at :rust:`module/mod.rs` - instead of :rust:`module.rs`, and this is still a working alternative for +- Before Rust 2018, modules needed to be located at :filename:`module/mod.rs` + instead of :filename:`module.rs`, and this is still a working alternative for editions after 2018. -- The main reason to introduce :rust:`filename.rs` as alternative to - :rust:`filename/mod.rs` was because many files named :rust:`mod.rs` can be +- The main reason to introduce :filename:`filename.rs` as alternative to + :filename:`filename/mod.rs` was because many files named :filename:`mod.rs` can be hard to distinguish in IDEs. - Deeper nesting can use folders, even if the main module is a file: @@ -78,7 +78,7 @@ Details mod some_module; This is useful, for example, if you would like to place tests for a - module in a file named :rust:`some_module_test.rs`, similar to the + module in a file named :filename:`some_module_test.rs`, similar to the convention in Go. .. raw:: html diff --git a/courses/comprehensive_rust_training/180_modules/06_exercise.rst b/courses/comprehensive_rust_training/180_modules/06_exercise.rst index 78e9e1b94..259d363ee 100644 --- a/courses/comprehensive_rust_training/180_modules/06_exercise.rst +++ b/courses/comprehensive_rust_training/180_modules/06_exercise.rst @@ -26,8 +26,8 @@ Cargo project on your local filesystem: cd gui-modules cargo run -Edit the resulting :rust:`src/main.rs` to add :rust:`mod` statements, and add -additional files in the :rust:`src` directory. +Edit the resulting :filename:`src/main.rs` to add :rust:`mod` statements, and add +additional files in the :filename:`src` directory. -------- Source diff --git a/courses/comprehensive_rust_training/190_testing/01_unit_tests.rst b/courses/comprehensive_rust_training/190_testing/01_unit_tests.rst index 340e87592..fb20d56d8 100644 --- a/courses/comprehensive_rust_training/190_testing/01_unit_tests.rst +++ b/courses/comprehensive_rust_training/190_testing/01_unit_tests.rst @@ -42,7 +42,7 @@ tests. - This lets you unit test private helpers. - The :rust:`#[cfg(test)]` attribute is only active when you run - :rust:`cargo test`. + :command:`cargo test`. .. raw:: html diff --git a/courses/comprehensive_rust_training/190_testing/02_other.rst b/courses/comprehensive_rust_training/190_testing/02_other.rst index f653fddc8..0606837f0 100644 --- a/courses/comprehensive_rust_training/190_testing/02_other.rst +++ b/courses/comprehensive_rust_training/190_testing/02_other.rst @@ -12,7 +12,7 @@ Integration Tests If you want to test your library as a client, use an integration test. -Create a :rust:`.rs` file under :rust:`tests/`: +Create a :filename:`.rs` file under :filename:`tests/`: .. code:: rust @@ -46,7 +46,7 @@ Rust has built-in support for documentation tests: } - Code blocks in :rust:`///` comments are automatically seen as Rust code. -- The code will be compiled and executed as part of :rust:`cargo test`. +- The code will be compiled and executed as part of :command:`cargo test`. - Adding :rust:`#` in the code will hide it from the docs, but will still compile/run it. - Test the above code on the diff --git a/courses/comprehensive_rust_training/190_testing/03_lints.rst b/courses/comprehensive_rust_training/190_testing/03_lints.rst index f4807c5f0..e0951b514 100644 --- a/courses/comprehensive_rust_training/190_testing/03_lints.rst +++ b/courses/comprehensive_rust_training/190_testing/03_lints.rst @@ -33,7 +33,7 @@ extensive documentation of its lints, and adds new lints (including default-deny lints) all the time. Note that errors or warnings with :rust:`help: ...` can be fixed with -:rust:`cargo fix` or via your editor. +:command:`cargo fix` or via your editor. .. raw:: html From 309721380a2a900fc3da173b85e40491ff94eb2f Mon Sep 17 00:00:00 2001 From: Michael Frank <55284511+frank-at-adacore@users.noreply.github.com> Date: Fri, 14 Feb 2025 13:41:05 -0500 Subject: [PATCH 4/4] Fix malformed URL and incorrect rust role substitution --- .../comprehensive_rust_training/140_smart_pointers/02_rc.rst | 2 +- courses/comprehensive_rust_training/190_testing/02_other.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/courses/comprehensive_rust_training/140_smart_pointers/02_rc.rst b/courses/comprehensive_rust_training/140_smart_pointers/02_rc.rst index 880a2f010..00d3c894a 100644 --- a/courses/comprehensive_rust_training/140_smart_pointers/02_rc.rst +++ b/courses/comprehensive_rust_training/140_smart_pointers/02_rc.rst @@ -22,7 +22,7 @@ same data from multiple places: println!("b: {b}"); } -- See :rust:`Arc`:url:` <../concurrency/shared-state/arc.md>` and +- See :url:`Arc ` and :url:`Mutex ` if you are in a multi-threaded context. - You can *downgrade* a shared pointer into a diff --git a/courses/comprehensive_rust_training/190_testing/02_other.rst b/courses/comprehensive_rust_training/190_testing/02_other.rst index 0606837f0..801f03632 100644 --- a/courses/comprehensive_rust_training/190_testing/02_other.rst +++ b/courses/comprehensive_rust_training/190_testing/02_other.rst @@ -36,11 +36,11 @@ Rust has built-in support for documentation tests: /// Shortens a string to the given length. /// - /// :rust:` + /// ``` /// # use playground::shorten_string; /// assert_eq!(shorten_string("Hello World", 5), "Hello"); /// assert_eq!(shorten_string("Hello World", 20), "Hello World"); - /// :rust:` + /// ``` pub fn shorten_string(s: &str, length: usize) -> &str { &s[..std::cmp::min(length, s.len())] }