rust / intermediate
Snippet
Panic Handling with std::panic::catch_unwind
catch_unwind captures panics and converts them into Result values, enabling recovery from panic states. This is essential when interfacing Rust with environments that cannot tolerate panics, such as when implementing plugins, foreign function interfaces, or async runtimes. AssertUnwindSafe is a helper for closures that the programmer guarantees are safe to unwind across.
snippet.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
use std::panic::{catch_unwind, AssertUnwindSafe};fn risky_operation(divisor: i32) -> i32 {100 / divisor // Will panic if divisor is 0}fn main() {// Successful caselet result = catch_unwind(|| {risky_operation(10)});match result {Ok(value) => println!("Calculation succeeded: {}", value),Err(e) => println!("Panic occurred: {:?}", e),}// Panic case - divisor is 0let panic_result = catch_unwind(|| {risky_operation(0)});if panic_result.is_err() {println!("Caught panic from division by zero!");}// Using AssertUnwindSafe for shared referenceslet shared_data = vec![1, 2, 3];let safe_result = catch_unwind(AssertUnwindSafe(|| {println!("Processing: {:?}", shared_data);42}));println!("Safe result: {:?}", safe_result);// Practical example: recoverable parsinglet numbers = vec!["10", "20", "oops", "40"];for num_str in numbers {let parsed = catch_unwind(|| num_str.parse::<i32>().unwrap());match parsed {Ok(n) => println!("Parsed: {}", n),Err(_) => println!("Failed to parse '{}', continuing...", num_str),}}}
Breakdown
1
catch_unwind(|| risky_operation(10))
Executes closure and catches any panic, returning Result<T, Box<dyn Any + Send>>
2
AssertUnwindSafe(|| ... )
Marker type asserting closure is safe to unwind through - use when you know the closure won't violate invariants
3
Ok(value) => println!("{}", value)
Normal completion - no panic occurred in the closure
4
Err(e) => println!("{:?}", e)
Panic was caught - e contains panic payload information