Rust currently uses a trait called Try (the name coming from calling ? ‘try’ after the try!(...) macro). It really only abstracts over success and failure, with the compiler generating the necessary control flow. It could probably be called “check” if that was what we decided to call ?.
Member macros is an interesting idea, though problematic since it requires type resolution to happen before code generation, which might in turn affect type resolution etc… Another approach would be to have a return type which encapsulates imperative effects, like return, break, etc… So you could escape a block of code and return it (pseudocode):
impl<T, E> Check<T> for Result<T, E> {
fn check<C, RT, RE>(self) -> impl Command<T, C>
where
C: ImperativeContext<Return=Result<RT, RE>>,
E: Into<RE>,
{
escape {
match self {
Err(e) => return Err(e.into()),
Ok(v) => v
}
}
}
}
and then run it in a caller. The names and overall design are obviously just placeholders to communicate the idea.