diff --git a/errors.md b/errors.md index faa13649787a3f57d3b22c5856814b2084c2b67c..6f7faa8fc24be69f8f747118f64aa538411d3157 100644 --- a/errors.md +++ b/errors.md @@ -7,5 +7,119 @@ sansfont: Sans Serif # Gestion d'erreurs -Under construction +- Il est important de pouvoir gérer trois cas: + - La panique totale (erreur fatale du programme). + - L'erreur dont on peut se remettre. + - Un résultat qui peut contenir une valeur ou pas. + +# Options + +- Un type énuméré particulièrement utile est le type `Option`{.rust} + + ```{.lang-rust} + enum Option<T> { // <T> est une notation pour un type générique + Some(T), + None, + } + ``` +- Type utilisé lorsque une valeur peut être "quelque chose" ou "rien". +- Exmple: la division + + <pre><code data-trim="hljs rust" class="lang-rust"> + fn main() { + let num = 1; + let denum = 4; + + let div = + if denum == 0 { + None + } else { + Some(num / denum) + }; + + match div { + Some(d) => println!("{} divisé par {} donne {}", num, denum, d), + None => println!("Cette division n'existe pas."), + } + } + </code></pre> + +- Typiquement vos fonctions doivent retourner des `Option`{.rust}. + + +# Panique! + +## `panic!()`{.rust} + +- Nous avons vu la macro `panic!("texte")`{.rust}. +- Le programme s'arrête et affiche le `"texte"`{.rust}. +- Utilisation: + - Le programme ne **doit pas** continuer quoi qu'il arrive. + <pre><code data-trim="hljs rust" class="lang-rust"> + fn elem(v: &[i32], i: usize) -> i32 { + if i >= v.len() { + panic!("Erreur fatale!"); + } + // assert!(i < v.len(), "Erreur fatale!"); // ceci est équivalent + v[i] + } + + fn main() { + let v = [1, 2, 3, 4]; + elem(&v, 100); + } + </code></pre> + - Avec l'appel `RUST_BACKTRACE=1` on peut remonter la pile d'appels (debugging). + + ``` + $ RUST_BACKTRACE=1 cargo run + Finished dev [unoptimized + debuginfo] target(s) in 0.01s + Running `target/debug/ma_librairie` + thread 'main' panicked at 'Erreur fatale!', src/main.rs:5:3 + stack backtrace: + 0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace + at libstd/sys/unix/backtrace/tracing/gcc_s.rs:49 + 1: std::sys_common::backtrace::print + at libstd/sys_common/backtrace.rs:71 + at libstd/sys_common/backtrace.rs:59 + 2: std::panicking::default_hook::{{closure}} + at libstd/panicking.rs:211 + 3: std::panicking::default_hook + at libstd/panicking.rs:227 + 4: std::panicking::rust_panic_with_hook + at libstd/panicking.rs:477 + 5: std::panicking::begin_panic + at /checkout/src/libstd/panicking.rs:411 + 6: ma_librairie::elem + at src/main.rs:5 + 7: ma_librairie::main + at src/main.rs:12 + 8: std::rt::lang_start::{{closure}} + at /checkout/src/libstd/rt.rs:74 + 9: std::panicking::try::do_call + at libstd/rt.rs:59 + at libstd/panicking.rs:310 + 10: __rust_maybe_catch_panic + at libpanic_unwind/lib.rs:102 + 11: std::rt::lang_start_internal + at libstd/panicking.rs:289 + at libstd/panic.rs:392 + at libstd/rt.rs:58 + 12: std::rt::lang_start + at /checkout/src/libstd/rt.rs:74 + 13: main + 14: __libc_start_main + 15: _start + ``` + +## `assert!()`{.rust} + +- On peut utiliser deux macros forts utiles. +- `assert!(cond, "Texte");`{.rust} + - N'importe quelle condition booléenne. +} +- `assert_eq!(lhs, rhs, "Texte");`{.rust} + - On ne teste que l'égalité. + +# Résultat