try_catch

Macro try_catch 

Source
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 catch blocks.
  • catch panic block (optional): Handle non-exception panics.
  • finally block (optional): Executes unconditionally after the try block and any catch blocks.

§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 finally block.

§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 panic block is only invoked for panics unrelated to exceptions handled by the macro.
  • The finally block 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);