"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), }) } }