"Type as Pattern" makes sense for narrowing

Suppose two functions which returns "checked exceptions":


#![allow(unused)]
fn main() {
#[cex] fn foo() -> Result!( () throws A,B );

#[cex] fn bar() -> Result!( () throws A,B,C );
}

If we call foo() in bar(), the errors in foo() may be collected into bar()'s error type Enum!(A,B,C), which is "wider" than foo()'s error type Enum!(A,B). Usually ? could be used for convenience, propagating errors without the need of writing a match expression to handle.

In the contrast, if we call bar() in foo(), it is not possible for ?to propagate the errors from bar() because foo()'s error type is "narrower" than bar()'s. We must write some match expression and will meet the issues.

The #[ty_pat] attribute is enabled inside a #[cex] tagged function or closure, to address these issues and make propagating convenient again.

Use #[ty_pat] match

to map errors returned by #[cex] functions or closures:


#![allow(unused)]
fn main() {
#[cex] fn foo() -> Result!( () throws String, SomeError ) {/**/}

#[cex] fn bar() {
    if let Err( err ) = foo() {
        #[ty_pat] match err {
            String( s ) => println!( "foo's error:{}", s ),
            SomeError => println!( "foo's error: SomeError" ),
        }
    }
}
}

Use TyPat

to wrap types that are not paths, e.g. references, (), in a #[ty_pat] match's arm:


#![allow(unused)]
fn main() {
#[cex] fn foo() -> Result!( i32 throws &'static str, SomeError ) {/**/}

#[cex] fn bar() {
    if let Err( err ) = foo() {
        #[ty_pat] match err {
            TyPat::<&'static str>( s ) => println!( "foo's error:{}", s ),
            SomeError => println!( "foo's error: SomeError" ),
        }
    }
}
}

Use #[ty_pat(gen_throws)] match

to automatically propagate errors enumerated in throws:


#![allow(unused)]
fn main() {
#[cex] fn foo() -> Result!( i32 throws String, SomeError ) {/**/}

#[cex] fn bar() -> Result!( i32 throws String ) {
    foo().or_else( |err| #[ty_pat(gen_throws)] match err {
        SomeError => ret!(0),
        // generated arm: String(s) => throw!(s),
    })
}
}

Use #[ty_pat(gen A,B,..)] match

to automatically propagate errors A,B,.. enumerated in the attribute:


#![allow(unused)]
fn main() {
#[cex] fn foo() -> Result!( i32 throws String, SomeError ) {/**/}

#[cex] fn bar() -> Result!( i32 throws String ) {
    foo().or_else( |err| #[ty_pat(gen String)] match err {
        SomeError => ret!(0),
        // generated arm: String(s) => throw!(s),
    })
}
}