Result<T, Infallible>, soon to be equivalent to Result<T, !> has been occurring quite often in recent code. The first instinct is to use unwrap on it, knowing it can never panic, but herein lies a maintainability hazard: if the error parameter type at the use site is later changed to an inhabitable one, the unwrap quietly becomes liable to panic.
Therefore, it would make sense to add a conversion to the standard library that would only be applicable to Result with an uninhabitable error type. In earlier discussion, two solutions were put forward:
I don't have a strong preference for either of the two, but as an extension trait method, unwrap_infallible is already available from a crate I have written. It would be nice to get an equivalent out of the box.
Extending the conversion coverage to E: Into<!> allows crate APIs who feature custom never-types to plug into this without redefining their type as an alias of !, which may break existing code. For the From<Result<T, E>> impl though, the parameterization of E might make it too blanket.
I recall the following working at some point, though I can't find the feature to get it working on the playground right now:
let res: Result<_, !> = f();
let Ok(ok) = res;
For the Err=! case, this feels like the correct solution. I also think that this worked for any uninhabitable Err variant, though I can't recall. If it doesn't, the conversion to the standard Result<T, !> seems like it should come down to the library to provide.
This takes a let statement to write, so f().unwrap() would still be tempting ergonomics-wise. The problem is not that it's impossible to unwrap with statically proven infallibility, because in stable you've been always able to do f().unwrap_or_else(|never| match never {}). It just should be almost as convenient as .unwrap().
I should probably rename the method to unwrap_always to make it 4 characters shorter and spare the coders from remembering obscure adjectives (though Infallible is sort of Rust legacy by now).
This does not completely eliminate the refactoring hazard, while making part of it more removed from the call site. If any type satisfies From<!>, the return type of g() can be changed to Result compatibly with the call site. Then if f() is made fallible and its error type happens to be convertible to that of g(), you've got a failure path you may not have intended to have.
The usual semantics of ? meaning "can return an error early here" would obscure the intent to make use of infallibility.