diff --git a/po/fr.po b/po/fr.po
index 89f59a033e37..cb4c2f1dde6d 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -53,7 +53,7 @@ msgid "Day 1: Morning"
msgstr "Jour 1 : Matin"
#: src/SUMMARY.md:18 src/SUMMARY.md:75 src/SUMMARY.md:128 src/SUMMARY.md:185
-#: src/SUMMARY.md:211 src/SUMMARY.md:259
+#: src/SUMMARY.md:211 src/SUMMARY.md:261
msgid "Welcome"
msgstr "Bienvenue"
@@ -131,7 +131,7 @@ msgstr "Surcharge"
#: src/SUMMARY.md:37 src/SUMMARY.md:66 src/SUMMARY.md:90 src/SUMMARY.md:119
#: src/SUMMARY.md:148 src/SUMMARY.md:177 src/SUMMARY.md:204 src/SUMMARY.md:225
-#: src/SUMMARY.md:251 src/SUMMARY.md:273 src/SUMMARY.md:293
+#: src/SUMMARY.md:253 src/SUMMARY.md:275 src/SUMMARY.md:296
msgid "Exercises"
msgstr "Exercices"
@@ -279,7 +279,7 @@ msgstr "Tailles d'énumération"
msgid "Method Receiver"
msgstr "Récepteur de méthode"
-#: src/SUMMARY.md:84 src/SUMMARY.md:159 src/SUMMARY.md:272
+#: src/SUMMARY.md:84 src/SUMMARY.md:159 src/SUMMARY.md:274
msgid "Example"
msgstr "Exemple"
@@ -315,7 +315,7 @@ msgstr "Points et polygones"
msgid "Day 2: Afternoon"
msgstr "Jour 2 : Après-midi"
-#: src/SUMMARY.md:96 src/SUMMARY.md:286
+#: src/SUMMARY.md:96 src/SUMMARY.md:288
msgid "Control Flow"
msgstr "Flux de contrôle"
@@ -600,7 +600,7 @@ msgstr "Implémentation de traits risqués"
msgid "Safe FFI Wrapper"
msgstr "Enveloppe FFI sûre"
-#: src/SUMMARY.md:181 src/SUMMARY.md:249
+#: src/SUMMARY.md:181 src/SUMMARY.md:251
msgid "Android"
msgstr "Android"
@@ -648,7 +648,7 @@ msgstr "Client"
msgid "Changing API"
msgstr "Modification de l'API"
-#: src/SUMMARY.md:197 src/SUMMARY.md:240
+#: src/SUMMARY.md:197 src/SUMMARY.md:241
msgid "Logging"
msgstr "Journalisation"
@@ -728,7 +728,7 @@ msgstr "probe-rs, cargo-embed"
msgid "Debugging"
msgstr "Débogage"
-#: src/SUMMARY.md:224 src/SUMMARY.md:242
+#: src/SUMMARY.md:224 src/SUMMARY.md:244
msgid "Other Projects"
msgstr "Autres projets"
@@ -745,253 +745,266 @@ msgid "Application Processors"
msgstr "Processeurs d'applications"
#: src/SUMMARY.md:231
+msgid "Getting Ready to Rust"
+msgstr ""
+
+#: src/SUMMARY.md:232
msgid "Inline Assembly"
msgstr "Assembleur en ligne"
-#: src/SUMMARY.md:232
+#: src/SUMMARY.md:233
msgid "MMIO"
msgstr "MMIO"
-#: src/SUMMARY.md:233
+#: src/SUMMARY.md:234
msgid "Let's Write a UART Driver"
msgstr "Écrivons un pilote UART"
-#: src/SUMMARY.md:234
+#: src/SUMMARY.md:235
msgid "More Traits"
msgstr "Plus de traits"
-#: src/SUMMARY.md:235
+#: src/SUMMARY.md:236
msgid "A Better UART Driver"
msgstr "Un meilleur pilote UART"
-#: src/SUMMARY.md:236
+#: src/SUMMARY.md:237
msgid "Bitflags"
msgstr "Bitflags"
-#: src/SUMMARY.md:237
+#: src/SUMMARY.md:238
msgid "Multiple Registers"
msgstr "Registres multiples"
-#: src/SUMMARY.md:238
+#: src/SUMMARY.md:239
msgid "Driver"
msgstr "Pilote"
-#: src/SUMMARY.md:239 src/SUMMARY.md:241
+#: src/SUMMARY.md:240 src/SUMMARY.md:242
msgid "Using It"
msgstr "En l'utilisant"
#: src/SUMMARY.md:243
+#, fuzzy
+msgid "Exceptions"
+msgstr "Fonctions"
+
+#: src/SUMMARY.md:245
msgid "Useful Crates"
msgstr "Crates utiles"
-#: src/SUMMARY.md:244
+#: src/SUMMARY.md:246
msgid "zerocopy"
msgstr "zerocopy"
-#: src/SUMMARY.md:245
+#: src/SUMMARY.md:247
msgid "aarch64-paging"
msgstr "aarch64-paging"
-#: src/SUMMARY.md:246
+#: src/SUMMARY.md:248
msgid "buddy_system_allocator"
msgstr "buddy_system_allocator"
-#: src/SUMMARY.md:247
+#: src/SUMMARY.md:249
msgid "tinyvec"
msgstr "tinyvec"
-#: src/SUMMARY.md:248
+#: src/SUMMARY.md:250
msgid "spin"
msgstr "spin"
-#: src/SUMMARY.md:250
+#: src/SUMMARY.md:252
msgid "vmbase"
msgstr "vmbase"
-#: src/SUMMARY.md:252
+#: src/SUMMARY.md:254
msgid "RTC Driver"
msgstr "Pilote RTC"
-#: src/SUMMARY.md:255
+#: src/SUMMARY.md:257
msgid "Concurrency: Morning"
msgstr "Concurrence : Matin"
-#: src/SUMMARY.md:260
+#: src/SUMMARY.md:262
msgid "Threads"
msgstr "Threads"
-#: src/SUMMARY.md:261
+#: src/SUMMARY.md:263
msgid "Scoped Threads"
msgstr "Threads délimités"
-#: src/SUMMARY.md:262
+#: src/SUMMARY.md:264
msgid "Channels"
msgstr "Canaux"
-#: src/SUMMARY.md:263
+#: src/SUMMARY.md:265
msgid "Unbounded Channels"
msgstr "Canaux illimités"
-#: src/SUMMARY.md:264
+#: src/SUMMARY.md:266
msgid "Bounded Channels"
msgstr "Canaux limités"
-#: src/SUMMARY.md:265
+#: src/SUMMARY.md:267
msgid "Send and Sync"
msgstr "Send et Sync"
-#: src/SUMMARY.md:265
+#: src/SUMMARY.md:267
msgid "Send"
msgstr "Send"
-#: src/SUMMARY.md:265
+#: src/SUMMARY.md:267
msgid "Sync"
msgstr "Sync"
-#: src/SUMMARY.md:268
+#: src/SUMMARY.md:270
msgid "Examples"
msgstr "Exemples"
-#: src/SUMMARY.md:269
+#: src/SUMMARY.md:271
msgid "Shared State"
msgstr "État partagé"
-#: src/SUMMARY.md:270
+#: src/SUMMARY.md:272
msgid "Arc"
msgstr "Arc"
-#: src/SUMMARY.md:271
+#: src/SUMMARY.md:273
msgid "Mutex"
msgstr "Mutex"
-#: src/SUMMARY.md:274 src/SUMMARY.md:294
+#: src/SUMMARY.md:276 src/SUMMARY.md:297
msgid "Dining Philosophers"
msgstr "Dîner des philosophes"
-#: src/SUMMARY.md:275
+#: src/SUMMARY.md:277
msgid "Multi-threaded Link Checker"
msgstr "Vérificateur de liens à plusieurs threads"
-#: src/SUMMARY.md:277
+#: src/SUMMARY.md:279
#, fuzzy
msgid "Concurrency: Afternoon"
msgstr "Concurrence : Après-midi"
-#: src/SUMMARY.md:279
+#: src/SUMMARY.md:281
msgid "Async Basics"
msgstr ""
-#: src/SUMMARY.md:280
+#: src/SUMMARY.md:282
msgid "async/await"
msgstr ""
-#: src/SUMMARY.md:281
+#: src/SUMMARY.md:283
msgid "Futures"
msgstr ""
-#: src/SUMMARY.md:282
+#: src/SUMMARY.md:284
#, fuzzy
msgid "Runtimes"
msgstr "Garanties d'exécution"
-#: src/SUMMARY.md:283
+#: src/SUMMARY.md:285
msgid "Tokio"
msgstr ""
-#: src/SUMMARY.md:284
+#: src/SUMMARY.md:286
msgid "Tasks"
msgstr "Tâches"
-#: src/SUMMARY.md:285
+#: src/SUMMARY.md:287
msgid "Async Channels"
msgstr "Canaux asynchrones"
-#: src/SUMMARY.md:287
+#: src/SUMMARY.md:289
msgid "Join"
msgstr ""
-#: src/SUMMARY.md:288
+#: src/SUMMARY.md:290
msgid "Select"
msgstr ""
-#: src/SUMMARY.md:289
+#: src/SUMMARY.md:291
msgid "Pitfalls"
msgstr "Pièges"
-#: src/SUMMARY.md:290
+#: src/SUMMARY.md:292
msgid "Blocking the Executor"
msgstr ""
-#: src/SUMMARY.md:291
+#: src/SUMMARY.md:293
msgid "Pin"
msgstr ""
-#: src/SUMMARY.md:292
+#: src/SUMMARY.md:294
#, fuzzy
msgid "Async Traits"
msgstr "Traits asynchrones"
#: src/SUMMARY.md:295
-msgid "Broadcast Chat Application"
+msgid "Cancellation"
msgstr ""
#: src/SUMMARY.md:298
+msgid "Broadcast Chat Application"
+msgstr ""
+
+#: src/SUMMARY.md:301
msgid "Final Words"
msgstr "Derniers mots"
-#: src/SUMMARY.md:302
+#: src/SUMMARY.md:305
msgid "Thanks!"
msgstr "Merci!"
-#: src/SUMMARY.md:303
+#: src/SUMMARY.md:306
msgid "Other Resources"
msgstr "Autres ressources"
-#: src/SUMMARY.md:304
+#: src/SUMMARY.md:307
msgid "Credits"
msgstr "Crédits"
-#: src/SUMMARY.md:307
+#: src/SUMMARY.md:310
msgid "Solutions"
msgstr "Solutions"
-#: src/SUMMARY.md:312
+#: src/SUMMARY.md:315
msgid "Day 1 Morning"
msgstr "Jour 1 Matin"
-#: src/SUMMARY.md:313
+#: src/SUMMARY.md:316
msgid "Day 1 Afternoon"
msgstr "Jour 1 Après-midi"
-#: src/SUMMARY.md:314
+#: src/SUMMARY.md:317
msgid "Day 2 Morning"
msgstr "Jour 2 Matin"
-#: src/SUMMARY.md:315
+#: src/SUMMARY.md:318
msgid "Day 2 Afternoon"
msgstr "Jour 2 Après-midi"
-#: src/SUMMARY.md:316
+#: src/SUMMARY.md:319
msgid "Day 3 Morning"
msgstr "Jour 3 Matin"
-#: src/SUMMARY.md:317
+#: src/SUMMARY.md:320
msgid "Day 3 Afternoon"
msgstr "Jour 3 Après-midi"
-#: src/SUMMARY.md:318
+#: src/SUMMARY.md:321
msgid "Bare Metal Rust Morning"
msgstr "Bare Metal Rust Matin"
-#: src/SUMMARY.md:319
+#: src/SUMMARY.md:322
msgid "Bare Metal Rust Afternoon"
msgstr "Bare Metal Rust Après-midi"
-#: src/SUMMARY.md:320
+#: src/SUMMARY.md:323
msgid "Concurrency Morning"
msgstr "Matin concurrence"
-#: src/SUMMARY.md:321
+#: src/SUMMARY.md:324
msgid "Concurrency Afternoon"
msgstr "Après-midi concurrence"
@@ -1203,7 +1216,7 @@ msgstr ""
#: src/ownership/lifetimes-data-structures.md:23
#: src/exercises/day-1/afternoon.md:9 src/exercises/day-1/book-library.md:100
#: src/structs.md:29 src/structs/tuple-structs.md:35
-#: src/structs/field-shorthand.md:25 src/enums.md:31
+#: src/structs/field-shorthand.md:25 src/enums.md:32
#: src/enums/variant-payloads.md:33 src/enums/sizes.md:27 src/methods.md:28
#: src/methods/receiver.md:22 src/methods/example.md:44
#: src/pattern-matching.md:23 src/pattern-matching/destructuring-enums.md:33
@@ -1250,6 +1263,7 @@ msgstr ""
#: src/bare-metal/microcontrollers/debugging.md:25
#: src/bare-metal/microcontrollers/other-projects.md:16
#: src/exercises/bare-metal/morning.md:5 src/bare-metal/aps.md:7
+#: src/bare-metal/aps/entry-point.md:75
#: src/bare-metal/aps/inline-assembly.md:41 src/bare-metal/aps/mmio.md:7
#: src/bare-metal/aps/uart.md:53 src/bare-metal/aps/uart/traits.md:22
#: src/bare-metal/aps/better-uart.md:24
@@ -1257,7 +1271,8 @@ msgstr ""
#: src/bare-metal/aps/better-uart/registers.md:39
#: src/bare-metal/aps/better-uart/driver.md:62
#: src/bare-metal/aps/better-uart/using.md:49 src/bare-metal/aps/logging.md:48
-#: src/bare-metal/aps/logging/using.md:44
+#: src/bare-metal/aps/logging/using.md:44 src/bare-metal/aps/exceptions.md:62
+#: src/bare-metal/aps/other-projects.md:15
#: src/bare-metal/useful-crates/zerocopy.md:43
#: src/bare-metal/useful-crates/aarch64-paging.md:26
#: src/bare-metal/useful-crates/buddy_system_allocator.md:24
@@ -1265,16 +1280,18 @@ msgstr ""
#: src/bare-metal/useful-crates/spin.md:21 src/bare-metal/android/vmbase.md:19
#: src/exercises/bare-metal/afternoon.md:5 src/concurrency/threads.md:28
#: src/concurrency/scoped-threads.md:35 src/concurrency/channels.md:25
-#: src/concurrency/send-sync.md:18 src/concurrency/send-sync/send.md:11
-#: src/concurrency/send-sync/sync.md:12 src/concurrency/shared_state/arc.md:27
+#: src/concurrency/channels/bounded.md:29 src/concurrency/send-sync.md:18
+#: src/concurrency/send-sync/send.md:11 src/concurrency/send-sync/sync.md:12
+#: src/concurrency/shared_state/arc.md:27
#: src/concurrency/shared_state/mutex.md:29
#: src/concurrency/shared_state/example.md:21
#: src/exercises/concurrency/morning.md:10 src/async/async-await.md:23
#: src/async/futures.md:30 src/async/runtimes.md:18
-#: src/async/runtimes/tokio.md:31 src/async/tasks.md:51
+#: src/async/runtimes/tokio.md:31 src/async/tasks.md:50
#: src/async/channels.md:33 src/async/control-flow/join.md:34
-#: src/async/control-flow/select.md:59
+#: src/async/control-flow/select.md:60
#: src/async/pitfalls/blocking-executor.md:27 src/async/pitfalls/pin.md:66
+#: src/async/pitfalls/cancellation.md:70
#: src/exercises/concurrency/afternoon.md:11
#: src/exercises/concurrency/dining-philosophers-async.md:75
msgid ""
@@ -1296,7 +1313,7 @@ msgstr ""
#: src/welcome.md:56 src/cargo/rust-ecosystem.md:67
#: src/cargo/code-samples.md:35 src/cargo/running-locally.md:74
#: src/welcome-day-1.md:42 src/welcome-day-1/what-is-rust.md:29
-#: src/hello-world.md:40 src/hello-world/small-example.md:44 src/why-rust.md:24
+#: src/hello-world.md:40 src/hello-world/small-example.md:46 src/why-rust.md:24
#: src/why-rust/compile-time.md:35 src/why-rust/runtime.md:22
#: src/why-rust/modern.md:66 src/basic-syntax/scalar-types.md:43
#: src/basic-syntax/compound-types.md:62 src/basic-syntax/references.md:29
@@ -1313,8 +1330,8 @@ msgstr ""
#: src/ownership/lifetimes-function-calls.md:60
#: src/ownership/lifetimes-data-structures.md:30
#: src/exercises/day-1/afternoon.md:15 src/exercises/day-1/book-library.md:104
-#: src/structs.md:42 src/structs/tuple-structs.md:43
-#: src/structs/field-shorthand.md:72 src/enums.md:41
+#: src/structs.md:42 src/structs/tuple-structs.md:44
+#: src/structs/field-shorthand.md:72 src/enums.md:42
#: src/enums/variant-payloads.md:45 src/enums/sizes.md:155 src/methods.md:41
#: src/methods/receiver.md:28 src/methods/example.md:53
#: src/pattern-matching.md:35 src/pattern-matching/destructuring-enums.md:39
@@ -1362,13 +1379,15 @@ msgstr ""
#: src/bare-metal/microcontrollers/debugging.md:38
#: src/bare-metal/microcontrollers/other-projects.md:26
#: src/exercises/bare-metal/morning.md:11 src/bare-metal/aps.md:15
+#: src/bare-metal/aps/entry-point.md:101
#: src/bare-metal/aps/inline-assembly.md:58 src/bare-metal/aps/mmio.md:17
#: src/bare-metal/aps/uart/traits.md:27 src/bare-metal/aps/better-uart.md:28
#: src/bare-metal/aps/better-uart/bitflags.md:40
#: src/bare-metal/aps/better-uart/registers.md:46
#: src/bare-metal/aps/better-uart/driver.md:67
#: src/bare-metal/aps/better-uart/using.md:55 src/bare-metal/aps/logging.md:52
-#: src/bare-metal/aps/logging/using.md:49
+#: src/bare-metal/aps/logging/using.md:49 src/bare-metal/aps/exceptions.md:75
+#: src/bare-metal/aps/other-projects.md:29
#: src/bare-metal/useful-crates/zerocopy.md:53
#: src/bare-metal/useful-crates/aarch64-paging.md:33
#: src/bare-metal/useful-crates/buddy_system_allocator.md:30
@@ -1376,17 +1395,18 @@ msgstr ""
#: src/bare-metal/useful-crates/spin.md:30 src/bare-metal/android/vmbase.md:25
#: src/exercises/bare-metal/afternoon.md:11 src/concurrency/threads.md:45
#: src/concurrency/scoped-threads.md:40 src/concurrency/channels.md:32
-#: src/concurrency/send-sync.md:23 src/concurrency/send-sync/send.md:16
-#: src/concurrency/send-sync/sync.md:18 src/concurrency/shared_state/arc.md:38
+#: src/concurrency/channels/bounded.md:35 src/concurrency/send-sync.md:23
+#: src/concurrency/send-sync/send.md:16 src/concurrency/send-sync/sync.md:18
+#: src/concurrency/shared_state/arc.md:38
#: src/concurrency/shared_state/mutex.md:45
#: src/concurrency/shared_state/example.md:56
#: src/exercises/concurrency/morning.md:16 src/async/async-await.md:48
#: src/async/futures.md:45 src/async/runtimes.md:29
-#: src/async/runtimes/tokio.md:49 src/async/tasks.md:64
+#: src/async/runtimes/tokio.md:49 src/async/tasks.md:63
#: src/async/channels.md:49 src/async/control-flow/join.md:50
-#: src/async/control-flow/select.md:77
+#: src/async/control-flow/select.md:79
#: src/async/pitfalls/blocking-executor.md:50 src/async/pitfalls/pin.md:112
-#: src/async/pitfalls/async-traits.md:63
+#: src/async/pitfalls/async-traits.md:63 src/async/pitfalls/cancellation.md:114
#: src/exercises/concurrency/afternoon.md:17
#: src/exercises/concurrency/dining-philosophers-async.md:79
msgid ""
@@ -1752,12 +1772,13 @@ msgstr ""
#: src/running-the-course/translations.md:16
msgid ""
+"* [Bengali][bn] by [@raselmandol].\n"
"* [French][fr] by [@KookaS] and [@vcaen].\n"
"* [German][de] by [@Throvn] and [@ronaldfw].\n"
"* [Japanese][ja] by [@CoinEZ-JPN] and [@momotaro1105]."
msgstr ""
-#: src/running-the-course/translations.md:20
+#: src/running-the-course/translations.md:21
msgid ""
"If you want to help with this effort, please see [our instructions] for how "
"to\n"
@@ -2542,6 +2563,7 @@ msgstr ""
"entrées."
#: src/hello-world/small-example.md:29
+#, fuzzy
msgid ""
"* Explain that all variables are statically typed. Try removing `i32` to "
"trigger\n"
@@ -2561,7 +2583,10 @@ msgid ""
"fmt`\n"
" which has the rules of the formatting mini-language. It's important that "
"the\n"
-" students become familiar with searching in the standard library."
+" students become familiar with searching in the standard library.\n"
+" \n"
+" * In a shell `rustup doc std::fmt` will open a browser on the local std::"
+"fmt documentation"
msgstr ""
"* Expliquez que toutes les variables sont typées statiquement. Essayez de "
"supprimer `i32` pour déclencher\n"
@@ -3268,7 +3293,7 @@ msgstr "Une tranche vous donne une vue dans une plus grande collection :"
msgid ""
"```rust,editable\n"
"fn main() {\n"
-" let a: [i32; 6] = [10, 20, 30, 40, 50, 60];\n"
+" let mut a: [i32; 6] = [10, 20, 30, 40, 50, 60];\n"
" println!(\"a: {a:?}\");\n"
"\n"
" let s: &[i32] = &a[2..4];\n"
@@ -4709,7 +4734,7 @@ msgstr ""
#: src/memory-management/rust.md:10
#, fuzzy
-msgid "It achieves this by modeling _ownership_ explicitly."
+msgid "Rust achieves this by modeling _ownership_ explicitly."
msgstr "Il y parvient en modélisant explicitement _ownership_."
#: src/memory-management/rust.md:14
@@ -5318,7 +5343,7 @@ msgid ""
"* The Rust compiler can do return value optimization (RVO).\n"
"* In C++, copy elision has to be defined in the language specification "
"because constructors can have side effects. In Rust, this is not an issue at "
-"all. If RVO did not happen, Rust will always performs a simple and efficient "
+"all. If RVO did not happen, Rust will always perform a simple and efficient "
"`memcpy` copy."
msgstr ""
@@ -5405,7 +5430,7 @@ msgid ""
" a valid solution.\n"
"* Lifetimes for function arguments and return values must be fully "
"specified,\n"
-" but Rust allows these to be elided in most cases with [a few simple\n"
+" but Rust allows lifetimes to be elided in most cases with [a few simple\n"
" rules](https://doc.rust-lang.org/nomicon/lifetime-elision.html)."
msgstr ""
@@ -5690,13 +5715,15 @@ msgid ""
"fn main() {\n"
" let library = Library::new();\n"
"\n"
-" //println!(\"The library is empty: {}\", library.is_empty());\n"
+" //println!(\"The library is empty: library.is_empty() -> {}\", library."
+"is_empty());\n"
" //\n"
" //library.add_book(Book::new(\"Lord of the Rings\", 1954));\n"
" //library.add_book(Book::new(\"Alice's Adventures in Wonderland\", "
"1865));\n"
" //\n"
-" //println!(\"The library is no longer empty: {}\", library.is_empty());\n"
+" //println!(\"The library is no longer empty: library.is_empty() -> {}\", "
+"library.is_empty());\n"
" //\n"
" //\n"
" //library.print_books();\n"
@@ -6029,7 +6056,7 @@ msgid ""
"```"
msgstr ""
-#: src/structs.md:31 src/enums.md:33 src/enums/sizes.md:29 src/methods.md:30
+#: src/structs.md:31 src/enums.md:34 src/enums/sizes.md:29 src/methods.md:30
#: src/methods/example.md:46 src/pattern-matching.md:25
#: src/pattern-matching/match-guards.md:22 src/control-flow/blocks.md:42
#, fuzzy
@@ -6120,7 +6147,9 @@ msgid ""
"single field in the newtype.\n"
" * Rust generally doesn’t like inexplicit things, like automatic "
"unwrapping or for instance using booleans as integers.\n"
-" * Operator overloading is discussed on Day 3 (generics). "
+" * Operator overloading is discussed on Day 3 (generics).\n"
+"* The example is a subtle reference to the [Mars Climate Orbiter](https://en."
+"wikipedia.org/wiki/Mars_Climate_Orbiter) failure."
msgstr ""
"* Les nouveaux types sont un excellent moyen d'encoder des informations "
"supplémentaires sur la valeur dans un type primitif, par exemple :\n"
@@ -6240,6 +6269,7 @@ msgstr ""
msgid ""
"```rust,editable\n"
"fn generate_random_number() -> i32 {\n"
+" // Implementation based on https://xkcd.com/221/\n"
" 4 // Chosen by fair dice roll. Guaranteed to be random.\n"
"}\n"
"\n"
@@ -6264,7 +6294,7 @@ msgid ""
"```"
msgstr ""
-#: src/enums.md:35
+#: src/enums.md:36
#, fuzzy
msgid ""
"* Enumerations allow you to collect a set of values under one type\n"
@@ -6471,7 +6501,7 @@ msgid ""
" * `dbg_size!(Option<&i32>)`: size 8 bytes, align: 8 bytes (null pointer "
"optimization, see below).\n"
"\n"
-" * Niche optimization: Rust will merge use unused bit patterns for the enum\n"
+" * Niche optimization: Rust will merge unused bit patterns for the enum\n"
" discriminant.\n"
"\n"
" * Null pointer optimization: For [some\n"
@@ -7205,7 +7235,7 @@ msgid ""
"// TODO: remove this when you're done with your implementation.\n"
"#![allow(unused_variables, dead_code)]\n"
"\n"
-"struct User {\n"
+"pub struct User {\n"
" name: String,\n"
" age: u32,\n"
" weight: f32,\n"
@@ -7628,8 +7658,8 @@ msgstr ""
#: src/control-flow/if-let-expressions.md:23
msgid ""
-"* `if let` can be more concise than `match`, e.g., when only one case is "
-"interesting. In contrast, `match` requires all branches to be covered.\n"
+"* Unlike `match`, `if let` does not have to cover all branches. This can "
+"make it more concise than `match`.\n"
"* A common usage is handling `Some` values when working with `Option`.\n"
"* Unlike `match`, `if let` does not support guard clauses for pattern "
"matching.\n"
@@ -7753,7 +7783,7 @@ msgstr "## Boucles `for`"
#, fuzzy
msgid ""
"The [`for` loop](https://doc.rust-lang.org/std/keyword.for.html) is closely\n"
-"related to the [`while let` loop](while-let-expression.md). It will\n"
+"related to the [`while let` loop](while-let-expressions.md). It will\n"
"automatically call `into_iter()` on the expression and then iterate over it:"
msgstr ""
"L'expression `for` est étroitement liée à l'expression `while let`. Ce sera\n"
@@ -9633,7 +9663,7 @@ msgid ""
"\n"
"* Move method `not_equal` to a new trait `NotEqual`.\n"
"\n"
-"* Make `NotEqual` a super trait for `Equal`.\n"
+"* Make `Equals` a super trait for `NotEqual`.\n"
" ```rust,editable,compile_fail\n"
" trait NotEqual: Equals {\n"
" fn not_equal(&self, other: &Self) -> bool {\n"
@@ -9654,8 +9684,8 @@ msgid ""
" }\n"
" }\n"
" ```\n"
-" * With the blanket implementation, you no longer need `NotEqual` as a "
-"super trait for `Equal`.\n"
+" * With the blanket implementation, you no longer need `Equals` as a super "
+"trait for `NotEqual`.\n"
" "
msgstr ""
"* Les caractéristiques peuvent spécifier des méthodes pré-implémentées (par "
@@ -10768,19 +10798,21 @@ msgid ""
"```rust,editable\n"
"use std::panic;\n"
"\n"
-"let result = panic::catch_unwind(|| {\n"
-" println!(\"hello!\");\n"
-"});\n"
-"assert!(result.is_ok());\n"
-"\n"
-"let result = panic::catch_unwind(|| {\n"
-" panic!(\"oh no!\");\n"
-"});\n"
-"assert!(result.is_err());\n"
+"fn main() {\n"
+" let result = panic::catch_unwind(|| {\n"
+" println!(\"hello!\");\n"
+" });\n"
+" assert!(result.is_ok());\n"
+" \n"
+" let result = panic::catch_unwind(|| {\n"
+" panic!(\"oh no!\");\n"
+" });\n"
+" assert!(result.is_err());\n"
+"}\n"
"```"
msgstr ""
-#: src/error-handling/panic-unwind.md:19
+#: src/error-handling/panic-unwind.md:21
#, fuzzy
msgid ""
"* This can be useful in servers which should keep running even if a single\n"
@@ -10812,11 +10844,11 @@ msgstr ""
#: src/error-handling/result.md:6
msgid ""
"```rust,editable\n"
-"use std::fs::File;\n"
+"use std::fs;\n"
"use std::io::Read;\n"
"\n"
"fn main() {\n"
-" let file = File::open(\"diary.txt\");\n"
+" let file = fs::File::open(\"diary.txt\");\n"
" match file {\n"
" Ok(mut file) => {\n"
" let mut contents = String::new();\n"
@@ -10905,8 +10937,8 @@ msgstr ""
#: src/error-handling/try-operator.md:21
msgid ""
"```rust,editable\n"
-"use std::fs;\n"
-"use std::io::{self, Read};\n"
+"use std::{fs, io};\n"
+"use std::io::Read;\n"
"\n"
"fn read_username(path: &str) -> Result {\n"
" let username_file_result = fs::File::open(path);\n"
@@ -11090,7 +11122,7 @@ msgid ""
"}\n"
"\n"
"fn read_username(path: &str) -> Result {\n"
-" let mut username = String::with_capacity(100);\n"
+" let mut username = String::new();\n"
" fs::File::open(path)?.read_to_string(&mut username)?;\n"
" if username.is_empty() {\n"
" return Err(ReadUsernameError::EmptyUsername(String::from(path)));\n"
@@ -11149,7 +11181,7 @@ msgstr ""
#: src/error-handling/dynamic-errors.md:6
msgid ""
"```rust,editable,compile_fail\n"
-"use std::fs::{self, File};\n"
+"use std::fs;\n"
"use std::io::Read;\n"
"use thiserror::Error;\n"
"use std::error::Error;\n"
@@ -11159,8 +11191,8 @@ msgid ""
"struct EmptyUsernameError(String);\n"
"\n"
"fn read_username(path: &str) -> Result> {\n"
-" let mut username = String::with_capacity(100);\n"
-" File::open(path)?.read_to_string(&mut username)?;\n"
+" let mut username = String::new();\n"
+" fs::File::open(path)?.read_to_string(&mut username)?;\n"
" if username.is_empty() {\n"
" return Err(EmptyUsernameError(String::from(path)).into());\n"
" }\n"
@@ -12130,7 +12162,7 @@ msgid ""
"mod ffi {\n"
" use std::os::raw::{c_char, c_int};\n"
" #[cfg(not(target_os = \"macos\"))]\n"
-" use std::os::raw::{c_long, c_ulong, c_ushort};\n"
+" use std::os::raw::{c_long, c_ulong, c_ushort, c_uchar};\n"
"\n"
" // Opaque type. See https://doc.rust-lang.org/nomicon/ffi.html.\n"
" #[repr(C)]\n"
@@ -12140,23 +12172,25 @@ msgid ""
"PhantomPinned)>,\n"
" }\n"
"\n"
-" // Layout as per readdir(3) and definitions in /usr/include/x86_64-linux-"
-"gnu.\n"
+" // Layout according to the Linux man page for readdir(3), where ino_t "
+"and\n"
+" // off_t are resolved according to the definitions in\n"
+" // /usr/include/x86_64-linux-gnu/{sys/types.h, bits/typesizes.h}.\n"
" #[cfg(not(target_os = \"macos\"))]\n"
" #[repr(C)]\n"
" pub struct dirent {\n"
-" pub d_ino: c_long,\n"
-" pub d_off: c_ulong,\n"
+" pub d_ino: c_ulong,\n"
+" pub d_off: c_long,\n"
" pub d_reclen: c_ushort,\n"
-" pub d_type: c_char,\n"
+" pub d_type: c_uchar,\n"
" pub d_name: [c_char; 256],\n"
" }\n"
"\n"
-" // Layout as per man entry for dirent\n"
-" #[cfg(target_os = \"macos\")]\n"
+" // Layout according to the macOS man page for dir(5).\n"
+" #[cfg(all(target_os = \"macos\"))]\n"
" #[repr(C)]\n"
" pub struct dirent {\n"
-" pub d_ino: u64,\n"
+" pub d_fileno: u64,\n"
" pub d_seekoff: u64,\n"
" pub d_reclen: u16,\n"
" pub d_namlen: u16,\n"
@@ -12166,7 +12200,22 @@ msgid ""
"\n"
" extern \"C\" {\n"
" pub fn opendir(s: *const c_char) -> *mut DIR;\n"
+"\n"
+" #[cfg(not(all(target_os = \"macos\", target_arch = \"x86_64\")))]\n"
+" pub fn readdir(s: *mut DIR) -> *const dirent;\n"
+"\n"
+" // See https://github.com/rust-lang/libc/issues/414 and the section "
+"on\n"
+" // _DARWIN_FEATURE_64_BIT_INODE in the macOS man page for stat(2).\n"
+" //\n"
+" // \"Platforms that existed before these updates were available\" "
+"refers\n"
+" // to macOS (as opposed to iOS / wearOS / etc.) on Intel and "
+"PowerPC.\n"
+" #[cfg(all(target_os = \"macos\", target_arch = \"x86_64\"))]\n"
+" #[link_name = \"readdir$INODE64\"]\n"
" pub fn readdir(s: *mut DIR) -> *const dirent;\n"
+"\n"
" pub fn closedir(s: *mut DIR) -> c_int;\n"
" }\n"
"}\n"
@@ -15029,6 +15078,136 @@ msgstr ""
"conçue uniquement pour\n"
" machines virtuelles."
+#: src/bare-metal/aps/entry-point.md:1
+msgid "# Getting Ready to Rust"
+msgstr ""
+
+#: src/bare-metal/aps/entry-point.md:3
+msgid ""
+"Before we can start running Rust code, we need to do some initialisation."
+msgstr ""
+
+#: src/bare-metal/aps/entry-point.md:5
+msgid ""
+"```armasm\n"
+".section .init.entry, \"ax\"\n"
+".global entry\n"
+"entry:\n"
+" /*\n"
+" * Load and apply the memory management configuration, ready to enable "
+"MMU and\n"
+" * caches.\n"
+" */\n"
+" adrp x30, idmap\n"
+" msr ttbr0_el1, x30\n"
+"\n"
+" mov_i x30, .Lmairval\n"
+" msr mair_el1, x30\n"
+"\n"
+" mov_i x30, .Ltcrval\n"
+" /* Copy the supported PA range into TCR_EL1.IPS. */\n"
+" mrs x29, id_aa64mmfr0_el1\n"
+" bfi x30, x29, #32, #4\n"
+"\n"
+" msr tcr_el1, x30\n"
+"\n"
+" mov_i x30, .Lsctlrval\n"
+"\n"
+" /*\n"
+" * Ensure everything before this point has completed, then invalidate "
+"any\n"
+" * potentially stale local TLB entries before they start being used.\n"
+" */\n"
+" isb\n"
+" tlbi vmalle1\n"
+" ic iallu\n"
+" dsb nsh\n"
+" isb\n"
+"\n"
+" /*\n"
+" * Configure sctlr_el1 to enable MMU and cache and don't proceed until "
+"this\n"
+" * has completed.\n"
+" */\n"
+" msr sctlr_el1, x30\n"
+" isb\n"
+"\n"
+" /* Disable trapping floating point access in EL1. */\n"
+" mrs x30, cpacr_el1\n"
+" orr x30, x30, #(0x3 << 20)\n"
+" msr cpacr_el1, x30\n"
+" isb\n"
+"\n"
+" /* Zero out the bss section. */\n"
+" adr_l x29, bss_begin\n"
+" adr_l x30, bss_end\n"
+"0: cmp x29, x30\n"
+" b.hs 1f\n"
+" stp xzr, xzr, [x29], #16\n"
+" b 0b\n"
+"\n"
+"1: /* Prepare the stack. */\n"
+" adr_l x30, boot_stack_end\n"
+" mov sp, x30\n"
+"\n"
+" /* Set up exception vector. */\n"
+" adr x30, vector_table_el1\n"
+" msr vbar_el1, x30\n"
+"\n"
+" /* Call into Rust code. */\n"
+" bl main\n"
+"\n"
+" /* Loop forever waiting for interrupts. */\n"
+"2: wfi\n"
+" b 2b\n"
+"```"
+msgstr ""
+
+#: src/bare-metal/aps/entry-point.md:77
+msgid ""
+"* This is the same as it would be for C: initialising the processor state, "
+"zeroing the BSS, and\n"
+" setting up the stack pointer.\n"
+" * The BSS (block starting symbol, for historical reasons) is the part of "
+"the object file which\n"
+" containing statically allocated variables which are initialised to zero. "
+"They are omitted from\n"
+" the image, to avoid wasting space on zeroes. The compiler assumes that "
+"the loader will take care\n"
+" of zeroing them.\n"
+"* The BSS may already be zeroed, depending on how memory is initialised and "
+"the image is loaded, but\n"
+" we zero it to be sure.\n"
+"* We need to enable the MMU and cache before reading or writing any memory. "
+"If we don't:\n"
+" * Unaligned accesses will fault. We build the Rust code for the `aarch64-"
+"unknown-none` target\n"
+" which sets `+strict-align` to prevent the compiler generating unaligned "
+"accesses, so it should\n"
+" be fine in this case, but this is not necessarily the case in general.\n"
+" * If it were running in a VM, this can lead to cache coherency issues. The "
+"problem is that the VM\n"
+" is accessing memory directly with the cache disabled, while the host has "
+"cachable aliases to the\n"
+" same memory. Even if the host doesn't explicitly access the memory, "
+"speculative accesses can\n"
+" lead to cache fills, and then changes from one or the other will get "
+"lost when the cache is\n"
+" cleaned or the VM enables the cache. (Cache is keyed by physical "
+"address, not VA or IPA.)\n"
+"* For simplicity, we just use a hardcoded pagetable (see `idmap.S`) which "
+"identity maps the first 1\n"
+" GiB of address space for devices, the next 1 GiB for DRAM, and another 1 "
+"GiB higher up for more\n"
+" devices. This matches the memory layout that QEMU uses.\n"
+"* We also set up the exception vector (`vbar_el1`), which we'll see more "
+"about later.\n"
+"* All examples this afternoon assume we will be running at exception level 1 "
+"(EL1). If you need to\n"
+" run at a different exception level you'll need to modify `entry.S` "
+"accordingly."
+msgstr ""
+
#: src/bare-metal/aps/inline-assembly.md:1
#, fuzzy
msgid "# Inline assembly"
@@ -15838,6 +16017,99 @@ msgstr ""
"* Exécutez l'exemple dans QEMU avec `make qemu_logger` sous `src/bare-metal/"
"aps/examples`."
+#: src/bare-metal/aps/exceptions.md:1
+#, fuzzy
+msgid "# Exceptions"
+msgstr "# Les fonctions"
+
+#: src/bare-metal/aps/exceptions.md:3
+msgid ""
+"AArch64 defines an exception vector table with 16 entries, for 4 types of "
+"exceptions (synchronous,\n"
+"IRQ, FIQ, SError) from 4 states (current EL with SP0, current EL with SPx, "
+"lower EL using AArch64,\n"
+"lower EL using AArch32). We implement this in assembly to save volatile "
+"registers to the stack\n"
+"before calling into Rust code:"
+msgstr ""
+
+#: src/bare-metal/aps/exceptions.md:8
+msgid ""
+"```rust,editable,compile_fail\n"
+"use log::error;\n"
+"use smccc::psci::system_off;\n"
+"use smccc::Hvc;\n"
+"\n"
+"#[no_mangle]\n"
+"extern \"C\" fn sync_exception_current(_elr: u64, _spsr: u64) {\n"
+" error!(\"sync_exception_current\");\n"
+" system_off::().unwrap();\n"
+"}\n"
+"\n"
+"#[no_mangle]\n"
+"extern \"C\" fn irq_current(_elr: u64, _spsr: u64) {\n"
+" error!(\"irq_current\");\n"
+" system_off::().unwrap();\n"
+"}\n"
+"\n"
+"#[no_mangle]\n"
+"extern \"C\" fn fiq_current(_elr: u64, _spsr: u64) {\n"
+" error!(\"fiq_current\");\n"
+" system_off::().unwrap();\n"
+"}\n"
+"\n"
+"#[no_mangle]\n"
+"extern \"C\" fn serr_current(_elr: u64, _spsr: u64) {\n"
+" error!(\"serr_current\");\n"
+" system_off::().unwrap();\n"
+"}\n"
+"\n"
+"#[no_mangle]\n"
+"extern \"C\" fn sync_lower(_elr: u64, _spsr: u64) {\n"
+" error!(\"sync_lower\");\n"
+" system_off::().unwrap();\n"
+"}\n"
+"\n"
+"#[no_mangle]\n"
+"extern \"C\" fn irq_lower(_elr: u64, _spsr: u64) {\n"
+" error!(\"irq_lower\");\n"
+" system_off::().unwrap();\n"
+"}\n"
+"\n"
+"#[no_mangle]\n"
+"extern \"C\" fn fiq_lower(_elr: u64, _spsr: u64) {\n"
+" error!(\"fiq_lower\");\n"
+" system_off::().unwrap();\n"
+"}\n"
+"\n"
+"#[no_mangle]\n"
+"extern \"C\" fn serr_lower(_elr: u64, _spsr: u64) {\n"
+" error!(\"serr_lower\");\n"
+" system_off::().unwrap();\n"
+"}\n"
+"```"
+msgstr ""
+
+#: src/bare-metal/aps/exceptions.md:64
+msgid ""
+"* EL is exception level; all our examples this afternoon run in EL1.\n"
+"* For simplicity we aren't distinguishing between SP0 and SPx for the "
+"current EL exceptions, or\n"
+" between AArch32 and AArch64 for the lower EL exceptions.\n"
+"* For this example we just log the exception and power down, as we don't "
+"expect any of them to\n"
+" actually happen.\n"
+"* We can think of exception handlers and our main execution context more or "
+"less like different\n"
+" threads. [`Send` and `Sync`][1] will control what we can share between "
+"them, just like with threads.\n"
+" For example, if we want to share some value between exception handlers and "
+"the rest of the\n"
+" program, and it's `Send` but not `Sync`, then we'll need to wrap it in "
+"something like a `Mutex`\n"
+" and put it in a static."
+msgstr ""
+
#: src/bare-metal/aps/other-projects.md:3
#, fuzzy
msgid ""
@@ -15848,8 +16120,11 @@ msgid ""
" * [Rust RaspberryPi OS tutorial](https://github.com/rust-embedded/rust-"
"raspberrypi-OS-tutorials)\n"
" * Initialisation, UART driver, simple bootloader, JTAG, exception levels, "
-"exception handling, page tables\n"
-" * Not all very well written, so beware.\n"
+"exception handling,\n"
+" page tables\n"
+" * Some dodginess around cache maintenance and initialisation in Rust, not "
+"necessarily a good\n"
+" example to copy for production code.\n"
" * [`cargo-call-stack`](https://crates.io/crates/cargo-call-stack)\n"
" * Static analysis to determine maximum stack usage."
msgstr ""
@@ -15866,6 +16141,29 @@ msgstr ""
" * [`pile-appel-cargo`](https://crates.io/crates/pile-appel-cargo)\n"
" * Analyse statique pour déterminer l'utilisation maximale de la pile."
+#: src/bare-metal/aps/other-projects.md:17
+msgid ""
+"* The RaspberryPi OS tutorial runs Rust code before the MMU and caches are "
+"enabled. This will read\n"
+" and write memory (e.g. the stack). However:\n"
+" * Without the MMU and cache, unaligned accesses will fault. It builds with "
+"`aarch64-unknown-none`\n"
+" which sets `+strict-align` to prevent the compiler generating unaligned "
+"accesses so it should be\n"
+" alright, but this is not necessarily the case in general.\n"
+" * If it were running in a VM, this can lead to cache coherency issues. The "
+"problem is that the VM\n"
+" is accessing memory directly with the cache disabled, while the host has "
+"cachable aliases to the\n"
+" same memory. Even if the host doesn't explicitly access the memory, "
+"speculative accesses can\n"
+" lead to cache fills, and then changes from one or the other will get "
+"lost. Again this is alright\n"
+" in this particular case (running directly on the hardware with no "
+"hypervisor), but isn't a good\n"
+" pattern in general."
+msgstr ""
+
#: src/bare-metal/useful-crates.md:1
#, fuzzy
msgid "# Useful crates"
@@ -17736,7 +18034,8 @@ msgstr "# Canaux limités"
#: src/concurrency/channels/bounded.md:3
#, fuzzy
-msgid "Bounded and synchronous channels make `send` block the current thread:"
+msgid ""
+"With bounded (synchronous) channels, `send` can block the current thread:"
msgstr ""
"Les canaux bornés et synchrones font que \"send\" bloque le thread actuel :"
@@ -17767,6 +18066,19 @@ msgid ""
"```"
msgstr ""
+#: src/concurrency/channels/bounded.md:31
+msgid ""
+"* Calling `send` will block the current thread until there is space in the "
+"channel for the new message. The thread can be blocked indefinitely if there "
+"is nobody who reads from the channel.\n"
+"* A call to `send` will abort with an error (that is why it returns "
+"`Result`) if the channel is closed. A channel is closed when the receiver is "
+"dropped.\n"
+"* A bounded channel with a size of zero is called a \"rendezvous channel\". "
+"Every send will block the current thread until another thread calls `read`.\n"
+" "
+msgstr ""
+
#: src/concurrency/send-sync.md:1
#, fuzzy
msgid "# `Send` and `Sync`"
@@ -18176,7 +18488,8 @@ msgid ""
"* You can get an `&mut T` from an `&Mutex` by taking the lock. The "
"`MutexGuard` ensures that the\n"
" `&mut T` doesn't outlive the lock being held.\n"
-"* `Mutex` implements both `Send` and `Sync` iff `T` implements `Send`.\n"
+"* `Mutex` implements both `Send` and `Sync` iff (if and only if) `T` "
+"implements `Send`.\n"
"* A read-write lock counterpart - `RwLock`.\n"
"* Why does `lock()` return a `Result`? \n"
" * If the thread that held the `Mutex` panicked, the `Mutex` becomes "
@@ -18937,12 +19250,10 @@ msgid "# Tasks"
msgstr "## Tâches"
#: src/async/tasks.md:3
-msgid ""
-"Runtimes have the concept of a \"task\", similar to a thread but much\n"
-"less resource-intensive."
+msgid "Rust has a task system, which is a form of lightweight threading."
msgstr ""
-#: src/async/tasks.md:6
+#: src/async/tasks.md:5
msgid ""
"A task has a single top-level future which the executor polls to make "
"progress.\n"
@@ -18953,7 +19264,7 @@ msgid ""
"polling multiple child futures, such as racing a timer and an I/O operation."
msgstr ""
-#: src/async/tasks.md:11
+#: src/async/tasks.md:10
msgid ""
"```rust,compile_fail\n"
"use tokio::io::{self, AsyncReadExt, AsyncWriteExt};\n"
@@ -18997,12 +19308,12 @@ msgid ""
"```"
msgstr ""
-#: src/async/tasks.md:53 src/async/control-flow/join.md:36
+#: src/async/tasks.md:52 src/async/control-flow/join.md:36
msgid ""
"Copy this example into your prepared `src/main.rs` and run it from there."
msgstr ""
-#: src/async/tasks.md:55
+#: src/async/tasks.md:54
msgid ""
"* Ask students to visualize what the state of the example server would be "
"with a\n"
@@ -19023,8 +19334,7 @@ msgstr "# Chaînes"
#: src/async/channels.md:3
msgid ""
-"Several crates have support for `async`/`await`. For instance `tokio` "
-"channels:"
+"Several crates have support for asynchronous channels. For instance `tokio`:"
msgstr ""
#: src/async/channels.md:5
@@ -19172,14 +19482,16 @@ msgstr ""
#: src/async/control-flow/select.md:8
msgid ""
-"This is usually a macro, similar to match, with each arm of the form "
-"`pattern =\n"
-"future => statement`. When the future is ready, the statement is executed "
-"with the\n"
-"variable bound to the future's result."
+"Similar to a match statement, the body of `select!` has a number of arms, "
+"each\n"
+"of the form `pattern = future => statement`. When the `future` is ready, "
+"the\n"
+"`statement` is executed with the variables in `pattern` bound to the "
+"`future`'s\n"
+"result."
msgstr ""
-#: src/async/control-flow/select.md:12
+#: src/async/control-flow/select.md:13
msgid ""
"```rust,editable,compile_fail\n"
"use tokio::sync::mpsc::{self, Receiver};\n"
@@ -19229,7 +19541,7 @@ msgid ""
"```"
msgstr ""
-#: src/async/control-flow/select.md:61
+#: src/async/control-flow/select.md:62
msgid ""
"* In this example, we have a race between a cat and a dog.\n"
" `first_animal_to_finish_race` listens to both channels and will pick "
@@ -19245,11 +19557,14 @@ msgid ""
"of\n"
" futures.\n"
"\n"
-"* Note that `select!` moves the values it is given. It is easiest to use\n"
-" when every execution of `select!` creates new futures. An alternative is "
-"to\n"
-" pass `&mut future` instead of the future itself, but this can lead to\n"
-" issues, further discussed in the pinning slide."
+"* Note that `select!` drops unmatched branches, which cancels their "
+"futures.\n"
+" It is easiest to use when every execution of `select!` creates new "
+"futures.\n"
+"\n"
+" * An alternative is to pass `&mut future` instead of the future itself, "
+"but\n"
+" this can lead to issues, further discussed in the pinning slide."
msgstr ""
#: src/async/pitfalls.md:1
@@ -19268,7 +19583,8 @@ msgstr ""
msgid ""
"- [Blocking the Executor](pitfalls/blocking-executor.md)\n"
"- [Pin](pitfalls/pin.md)\n"
-"- [Async Traits](pitfall/async-traits.md)"
+"- [Async Traits](pitfalls/async-traits.md)\n"
+"- [Cancellation](pitfalls/cancellation.md)"
msgstr ""
#: src/async/pitfalls/blocking-executor.md:1
@@ -19561,6 +19877,142 @@ msgid ""
" and adding it to the Vec."
msgstr ""
+#: src/async/pitfalls/cancellation.md:1
+#, fuzzy
+msgid "# Cancellation"
+msgstr "# Cancellation"
+
+#: src/async/pitfalls/cancellation.md:3
+msgid ""
+"Dropping a future implies it can never be polled again. This is called "
+"*cancellation*\n"
+"and it can occur at any `await` point. Care is needed to ensure the system "
+"works\n"
+"correctly even when futures are cancelled. For example, it shouldn't "
+"deadlock or\n"
+"lose data."
+msgstr ""
+
+#: src/async/pitfalls/cancellation.md:8
+msgid ""
+"```rust,editable,compile_fail\n"
+"use std::io::{self, ErrorKind};\n"
+"use std::time::Duration;\n"
+"use tokio::io::{AsyncReadExt, AsyncWriteExt, DuplexStream};\n"
+"\n"
+"struct LinesReader {\n"
+" stream: DuplexStream,\n"
+"}\n"
+"\n"
+"impl LinesReader {\n"
+" fn new(stream: DuplexStream) -> Self {\n"
+" Self { stream }\n"
+" }\n"
+"\n"
+" async fn next(&mut self) -> io::Result