Skip to content

Latest commit

 

History

History
327 lines (265 loc) · 7.42 KB

File metadata and controls

327 lines (265 loc) · 7.42 KB
title Panicking
slug panicking
  • Panicking immediately terminates the current thread.

    • panic!: Mainly used with unrecoverable errors.
      • Default panic message: explicit panic
    • todo!: Mainly used with unfinished code.
      • Default panic message/prefix: not yet implemented
    • unimplemented!: Mainly used with unimplemented code.
      • Default panic message/prefix: not implemented
    • unreachable!: Mainly used with code routes that the program should not trigger.
      • Default panic message/prefix: internal error: entered unreachable code
    • Assertions
      • assert!/ debug_assert!: Ensures a condition is true.
        • Default panic message: assertion failed
      • assert_eq!/ debug_assert_eq! and assert_ne!/ debug_assert_ne!: Ensures two expressions are equal or not equal.
        • Default panic message/prefix: assertion `left != right` failed
      • assert_matches!/ debug_assert_matches!: Ensures an expression matches a given pattern.
        • Default panic message/prefix: assertion `left matches right` failed
  • Rust cleans up memory by destroying variables on the stack in reverse order after a panic occurs. This process is called Unwinding.

panic!

  • Mainly used with unrecoverable errors.
  • In single threaded applications, the program will print an error message, clean up its memory with unwinding, and crash at runtime. In multithreaded applications, a panic affects only on the thread that occurred.

Default Message

fn main() {
    // some code

    panic!();
}

[!Caution] Crash at Runtime

thread 'main' (123456) panicked at foo/src/main.rs:4:5:
explicit panic

Custom Message

fn main() {
    // some code

    panic!("custom message");
}

[!Caution] Crash at Runtime

thread 'main' (123456) panicked at bar/src/main.rs:4:5:
custom message

Custom Message & Value

fn main() {
    // some code
    let max = i128::MAX;

    panic!("custom message: {max}");
}

[!Caution] Crash at Runtime

thread 'main' (123456) panicked at buzz/src/main.rs:5:5:
custom message: 170141183460469231731687303715884105727

Tip

Use dbg macro for debugging. This will not trigger a panic.

#[derive(Debug)]
struct Color(u8, u8, u8);

fn main() {
    let white = Color(255, 255, 255);
    dbg!("custom message", &white);

    println!("RGB({} {} {})", white.0, white.1, white.2);
}
[foo/src/main.rs:6:5] "custom message" = "custom message"
[foo/src/main.rs:6:5] &white = Color(
    255,
    255,
    255,
)
RGB(255 255 255)

todo! and unimplemented!

The difference is quite semantic,
todo! indicates that we plan to add the code later, while unimplemented! only means the code is unimplemented.

fn main() {
    todo!();
}

[!Caution] Crash at Runtime

thread 'main' (123456) panicked at foo/src/main.rs:2:5:
not yet implemented
fn main() {
    unimplemented!();
}

[!Caution] Crash at Runtime

thread 'main' (123456) panicked at foo/src/main.rs:2:5:
not implemented

Similar to the panic!, these also support custom messages and values. However, their default messages are always prepended to the panic message.

fn main() {
    // some code
    let max = i128::MAX;

    todo!("custom message: {max}"); // or unimplemented!
}

[!Caution] Crash at Runtime

thread 'main' (123456) panicked at buzz/src/main.rs:5:5:
not yet implemented: custom message: 170141183460469231731687303715884105727
thread 'main' (123456) panicked at buzz/src/main.rs:5:5:
not implemented: custom message: 170141183460469231731687303715884105727

unreachable!

Mainly used with code routes that the program should not trigger.

fn main() {
    unreachable!();
}

[!Caution] Crash at Runtime

thread 'main' (123456) panicked at foo/src/main.rs:2:5:
internal error: entered unreachable code

Similar to the panic!, this also support custom messages and values. Like todo! and unimplemented!, the default message of unreachable! is always prepended to the panic message.

fn main() {
    // some code
    let max = i128::MAX;

    unreachable!("custom message: {max}");
}

[!Caution] Crash at Runtime

thread 'main' (123456) panicked at buzz/src/main.rs:5:5:
internal error: entered unreachable code: custom message: 170141183460469231731687303715884105727

Assertions

  • Mainly used with test assertions and ensure runtime conditions true.
    • assert*: Standard runtime assertions evaluated in both debug and release builds.
    • debug_assert*: Mirrors to standard assertions that run only in debug builds and are omitted from release builds.
  • Similar to the panic!, these also support custom messages and values.

assert! & debug_assert!

Ensures a condition is true.

fn main() {
    let a = 10;
    assert!(a < 10); // or debug_assert!
}

[!Caution] Crash at Runtime

thread 'main' (123456) panicked at foo/src/main.rs:3:5:
assertion failed: a < 10
fn main() {
    let a = 10;
    assert!(a < 10, "custom message: {a}"); // or debug_assert!
}

[!Caution] Crash at Runtime

thread 'main' (123456) panicked at foo/src/main.rs:3:5:
custom message: 10

assert_eq! & debug_assert_eq!

Ensures two expressions are equal.

fn main() {
    let (a, b) = (10, 20);
    assert_eq!(a, b); // or debug_assert_eq!
}

[!Caution] Crash at Runtime

thread 'main' (123456) panicked at foo/src/main.rs:3:5:
assertion `left == right` failed
  left: 10
 right: 20
fn main() {
    let (a, b) = (10, 20);
    assert_eq!(a, b, "custom message: {a}, {b}"); // or debug_assert_eq!
}

[!Caution] Crash at Runtime

thread 'main' (123456) panicked at foo/src/main.rs:3:5:
assertion `left == right` failed: custom message: 10, 20
  left: 10
 right: 20

assert_ne! & debug_assert_ne!

Ensures two expressions are not equal.

fn main() {
    let (a, b) = (10, 10);
    assert_ne!(a, b); // or debug_assert_ne!
}

[!Caution] Crash at Runtime

thread 'main' (123456) panicked at foo/src/main.rs:3:5:
assertion `left != right` failed
  left: 10
 right: 10
fn main() {
    let (a, b) = (10, 10);
    assert_ne!(a, b, "custom message: {a}, {b}"); // or debug_assert_ne!
}

[!Caution] Crash at Runtime

thread 'main' (123456) panicked at foo/src/main.rs:3:5:
assertion `left != right` failed: custom message: 10, 10
  left: 10
 right: 10

assert_matches! & debug_assert_matches!

Ensures an expression matches a given pattern.

Tip

Non-prelude assertions to replace assert!(matches!(value, pattern))

fn main() {
    let a = Some(10);
    std::assert_matches!(a, Some(x) if x > 20); // or debug_assert_matches!
}

[!Caution] Crash at Runtime

thread 'main' (123456) panicked at foo/src/main.rs:3:5:
assertion `left matches right` failed
  left: Some(10)
 right: Some(x) if x > 20
fn main() {
    let a = Some(10);
    std::assert_matches!(a, Some(x) if x > 20, "custom message: {a:?}"); // or debug_assert_matches!
}

[!Caution] Crash at Runtime

thread 'main' (123456) panicked at foo/src/main.rs:3:5:
assertion `left matches right` failed: custom message: Some(10)
  left: Some(10)
 right: Some(x) if x > 20