While I appreciate the attempt to be generic, I don’t think that you would want to “desugar” to -> impl Try<..>
. I don’t even think it makes sense, actually. Consider:
-> impl Try
implies that the callee chooses the type that is returned. But on what basis are we making this decision? Consider this simple example:
fn foo() -> u32 catches Foo {
22
}
If this were to desugar to -> impl Try<u32, Foo>
, there would be no constraint on what type we use. The source only specifies the ok and error types, but not the “carrier”.
One might imagine desugaring to a generic type parameter T: Try<u32, Foo>
, in which case you could sort of desugar to:
fn foo<T: Try<u32, Foo>>() -> T {
T::from_ok(22)
}
But this seems like a poor choice. It’s not clear that the caller wants to be involved in this choice, to begin with, but also this will result in extra monomorphiations and complexity.
I would much rather we just specify a concrete type. I still feel like there is some meaning to that choice, in any case – e.g., returning Result
vs Option
carries (to me) a subtle distinction in intended usage. (Of course we can return T catches NoneError
or whatever, but that’s kind of verbose for no purpose.)
The more I think about it, the more I like something where you write -> catches Result<T, E>
– that is, you write the actual type the caller will receive. I’m not sure if the catches
keyword is the right one, but it’s not the worst one, I suppose.