Unwrap Infallible Results With All Convenience And No Fear

Result sometimes occurs parameterized with an error type that has no possible values, such as std::convert::Infallible. Consequently, calling the unwrap method on a Result value of such a type will never panic.

Therein lies a maintainability hazard: if the error parameter type is later changed to one that can represent actually occurring errors, those uses of unwrap that could previously be relied upon to be infallible, quietly become liable to panic.

To help prevent this from happening without a compile-time safeguard, crate unwrap-infallible provides an alternative method unwrap_infallible that shall only be available for Result values with a known-impossible Err variant.

2 Likes

FWIW you can repalce unsafe { unreachable_unchecked() } with safe code.

impl<T> UnwrapInfallible for Result<T, Infallible> {
    type Ok = T;
    fn unwrap_infallible(self) -> T {
        match self {
            Ok(val) => val,
            Err(never) => match never {},
        }
    }
}

The blanket_impl feature seem incorrect. E: From<!> does not necessary mean E is infallible error type, as they might implement From<!> just so that you can use ? on Result<_, !>. There's even the plan to add impl<T> From<!> for T in the standard library: https://github.com/rust-lang/rust/issues/64715

5 Likes

Thank you for the quick feedback. I was suspicious about From<!> as indeed it's possible to safely implement for any type, but thought there will be a convention for tagging never-types with it. As you point out it's decidedly not the case, so I will remove the blanket impl altogether reverse the bound to <!>: From<E> and make sure the From impl is actually invoked, just in case the implementer is trying to do something clever.