cex 0.5.2

Checked exception simulation.
Documentation
#![cfg_attr( feature = "unstable", feature( proc_macro_hygiene, stmt_expr_attributes, try_blocks ))]

macro_rules! define_tests {
    () => {
        mod function {
            use super::*;

            #[cex] fn throws_never() -> Result!(()) { ret!(); }

            #[cex] fn throws_void() -> Result!( () throws () ) { throw!(); }

            #[cex] fn throws_str() -> Result!( i32 throws &'static str ) { throw!( "oops" ); ret!(0); }

            #[cex] fn throws_string() -> Result!( i32 throws String ) { throw!( String::from( "oops" )); ret!(0); }

            #[cex] fn throws_i32() -> Result!( i32 throws i32 ) { throw!( 0xbadbeef ); ret!(0); }

            struct UnitError;
            #[cex] fn throws_unit_error() -> Result!( i32 throws UnitError ) { throw!( UnitError ); ret!(0); }

            struct ErrorCode( i32 );
            #[cex] fn throws_error_code() -> Result!( i32 throws ErrorCode ) { throw!( ErrorCode( 0xbadbeef )); ret!(0); }

            struct A;
            #[cex] fn throws_a() -> Result!( () throws A ) { throw!(A); }

            struct B;
            #[cex] fn throws_ab() -> Result!( () throws A,B ) { throw!(A); throw!(B); }

            struct C;
            #[cex] fn throws_abc() -> Result!( () throws A,B,C ) { throw!(A); throw!(B); throw!(C); }

            #[cex] fn throws_ba_call_ab() -> Result!( () throws B,A ) { ret!( throws_ab()? ); }

            #[cex] fn throws_bca_call_ab() -> Result!( () throws B,C,A ) { throws_ab()?; throw!(C); }

            #[cex] fn throws_ab_call_bca() -> Result!( () throws A,B ) {
                throws_bca_call_ab().or_else( |err| #[ty_pat] match err {
                    B(b) => throw!(b),
                    A(a) => throw!(a),
                    C(_) => ret!(),
                })
            }

            #[cex] fn throws_ab_call_bca_v2() -> Result!( () throws A,B ) {
                throws_bca_call_ab().or_else( |err| #[ty_pat(gen_throws)] match err {
                    C(_) => ret!(),
                })
            }

            #[cex] fn throws_ab_call_bca_v3() -> Result!( () throws A,B ) {
                throws_bca_call_ab().or_else( |err| #[ty_pat(gen B)] match err {
                    C(_) => ret!(),
                    A(a) => throw!(a),
                })
            }

            #[cex] fn throws_ab_call_bca_v4() -> Result!( () throws A,B ) {
                throws_bca_call_ab().or_else( |err| #[ty_pat(gen B,A)] match err {
                    C(_) => ret!(),
                })
            }

            #[cfg( feature = "unstable" )]
            fn closure_throws_abc() {
                let _f = #[cex] || -> Result!( i32 throws A,B,C ) { throw!(A); throw!(B); throw!(C); ret!(0); };
            }

            #[cfg( feature = "unstable" )]
            fn try_throws_abc_v2() {
                #[cex] let _result: Result!( () throws A,B,C ) = try{ throws_abc()? };
            }

            #[cex] fn nested_results() -> Result!( Result!( () throws C ) throws A,B ) {
                throw!( A );
                throw!( B );
                // throw!( C ); // compile error
            }
        }
    };
}

#[allow( dead_code, unreachable_code )]
mod test {
    use enumx::export::*;
    use enumx::predefined::*;
    use cex_derive::cex;
    use cex::*;

    define_tests!();
}

#[allow( dead_code, unreachable_code )]
mod test_log {
    use enumx::export::*;
    use enumx::predefined::*;
    use cex_derive::cex_log as cex;
    use cex::*;

    define_tests!();
}

#[allow( dead_code, unreachable_code )]
mod test_env_log {
    use enumx::export::*;
    use enumx::predefined::*;
    use cex_derive::cex_env_log as cex;
    use cex::*;

    define_tests!();
}