binary_layout/utils/
infallible.rs

1use core::convert::Infallible;
2
3pub(crate) trait IsInfallible {}
4
5impl IsInfallible for Infallible {}
6
7/// This extension trait adds [InfallibleResultExt::infallible_unwrap] to [Result] types
8/// that use [core::convert::Infallible] as error type.
9pub trait InfallibleResultExt<T> {
10    /// This function does the same as [Result::unwrap], but it only exists on types where the error type
11    /// of the [Result] is [core::convert::Infallible]. This way, we can guarantee that this function
12    /// will always be a no-op and will never panic. This is great for when your code style says that
13    /// [Result::unwrap] is a code smell because it could cause runtime panics, but you need a safe
14    /// alternative for it for when you know it can't fail.
15    fn infallible_unwrap(self) -> T;
16}
17
18impl<T, E> InfallibleResultExt<T> for Result<T, E>
19where
20    E: IsInfallible,
21{
22    fn infallible_unwrap(self) -> T {
23        match self {
24            Ok(value) => value,
25            Err(_) => unreachable!(),
26        }
27    }
28}
29
30#[cfg(test)]
31mod tests {
32    use super::*;
33
34    #[test]
35    fn infallible_unwrap() {
36        let value: Result<u32, Infallible> = Ok(2);
37        assert_eq!(2, value.infallible_unwrap());
38    }
39
40    struct AlternativeInfallible {}
41    impl IsInfallible for AlternativeInfallible {}
42
43    #[test]
44    fn alternative_infallible_unwrap() {
45        let value: Result<u32, AlternativeInfallible> = Ok(2);
46        assert_eq!(2, value.infallible_unwrap());
47    }
48}