macro_rules! try_catch {
{
try {
$($try_body: tt)*
} $(catch ($exception_name: pat => $exception_ty:ty) {
$($catch_body: tt)*
})* $(catch exception ($catch_all_exception_name: pat) {
$($catch_all_exception_body: tt)*
})? $(catch panic ($catch_panic_exception_name: pat) {
$($catch_panic_exception_body: tt)*
})? $(finally {
$($finally_body: tt)*
})?
} => { ... };
}Expand description
A flexible try_catch macro that provides structured error and panic handling
with an optional finally block for cleanup.
§Description
The try_catch! macro allows you to define a try block for executing code, followed by multiple catch
blocks for handling exceptions or panics. Additionally, a finally block can be specified for cleanup actions.
§Syntax
try_catch! {
try {
<try_block>
} catch (<exception_pattern> => <exception_type>) {
<catch_block>
} catch exception (<catch_all_pattern>) {
<catch_all_block>
} catch panic (<panic_pattern>) {
<catch_panic_block>
} finally {
<finally_block>
}
}- try block: The primary code to execute.
- catch blocks: Handle exceptions matching specific types.
- catch exception block (optional): A generic handler for exceptions not caught by specific
catchblocks. - catch panic block (optional): Handle non-exception panics.
- finally block (optional): Executes unconditionally after the
tryblock and anycatchblocks.
§Notes
- at least 2 blocks have to be defined you cannot have a bare try {} expression
- the try and catch blocks should both return the same type
- the finally block should return () aka “unit”
§Features
- Matches exceptions based on type.
- Catches generic exceptions with
catch exception. - Handles panics using
catch panic. - Ensures cleanup via an optional
finallyblock.
§Usage
§Handling specific exceptions
#[derive(Debug)]
struct MyErrorType;
fn some_function() -> Result<i32, MyErrorType> {
Err(MyErrorType)
}
let result = rust_try_catch::try_catch! {
try {
rust_try_catch::tri!(some_function())
} catch (e => MyErrorType) {
println!("Caught MyErrorType: {e:?}");
-1
}
};
assert_eq!(result, -1);§Catching all exceptions
let result = rust_try_catch::try_catch! {
try {
// Code that might throw.
another_function();
0
} catch exception (e) {
println!("Caught an exception: {:?}", e);
-2
}
};
assert_eq!(result, -2);§Handling panics
let result = rust_try_catch::try_catch! {
try {
// Code that might panic.
panic!("Unexpected error");
0
} catch panic (e) {
println!("Caught a panic: {:?}", e);
-101
}
};
assert_eq!(result, -101);§Using a finally block
let mut cleanup = false;
let result = rust_try_catch::try_catch! {
try {
// Code execution.
42
} finally {
cleanup = true;
}
};
assert_eq!(result, 42);
assert!(cleanup);§Combining handlers
let result = rust_try_catch::try_catch! {
try {
// Code execution.
risky_operation();
0
} catch (e => SpecificError) {
println!("Caught SpecificError: {e:?}");
-1
} catch exception (e) {
println!("Caught general exception: {e:?}");
-2
} catch panic (e) {
println!("Caught a panic: {e:?}");
-3
} finally {
println!("Cleanup actions here.");
}
};§Notes
- The
catch panicblock is only invoked for panics unrelated to exceptions handled by the macro. - The
finallyblock runs regardless of whether an exception or panic occurred. - Unhandled exceptions or panics will propagate out of the macro.
§Examples
§No exception or panic (doesn’t compile)
ⓘ
let result = rust_try_catch::try_catch! {
try {
100
}
};
assert_eq!(result, 100);§Exception without panic
let result = rust_try_catch::try_catch! {
try {
throw("An error occurred");
} catch (e => &'static str) {
println!("Handled error: {}", e);
0
}
};
assert_eq!(result, 0);§Panic recovery
let result = rust_try_catch::try_catch! {
try {
panic!("Something went wrong!");
} catch panic (e) {
println!("Recovered from panic: {:?}", e);
1
}
};
assert_eq!(result, 1);