unwrap_infallible/
lib.rs

1//! Conversion method for infallible results
2//!
3//! This crate provides a convenience trait `UnwrapInfallible`,
4//! adding method `unwrap_infallible` to `Result` types where an `Err` variant
5//! is statically known to never occur.
6//!
7//! # Example
8//!
9//! ```
10//! # #![cfg_attr(feature = "never_type", feature(never_type))]
11//! #
12//! use unwrap_infallible::UnwrapInfallible;
13//! # #[cfg(not(feature = "blanket_impl"))]
14//! use std::convert::Infallible;
15//! # #[cfg(feature = "blanket_impl")]
16//! # type Infallible = !;
17//!
18//! fn always_sunny() -> Result<String, Infallible> {
19//!     Ok("it's always sunny!".into())
20//! }
21//!
22//! fn main() {
23//!     println!("{}", always_sunny().unwrap_infallible());
24//! }
25//! ```
26
27#![warn(rust_2018_idioms)]
28#![warn(clippy::all)]
29#![warn(missing_docs)]
30#![no_std]
31#![cfg_attr(feature = "never_type", feature(never_type))]
32
33#[cfg(not(feature = "blanket_impl"))]
34use core::convert::Infallible;
35
36/// Unwrapping an infallible result into its success value.
37pub trait UnwrapInfallible {
38    /// Type of the `Ok` variant of the result.
39    type Ok;
40
41    /// Unwraps a result, returning the content of an `Ok`.
42    ///
43    /// Unlike `Result::unwrap`, this method is known to never panic
44    /// on the result types it is implemented for. Therefore, it can be used
45    /// instead of `unwrap` as a maintainability safeguard that will fail
46    /// to compile if the error type of the `Result` is later changed
47    /// to an error that can actually occur.
48    fn unwrap_infallible(self) -> Self::Ok;
49}
50
51#[cfg(feature = "blanket_impl")]
52impl<T, E: Into<!>> UnwrapInfallible for Result<T, E> {
53    type Ok = T;
54    fn unwrap_infallible(self) -> T {
55        match self {
56            Ok(v) => v,
57            Err(e) => e.into(),
58        }
59    }
60}
61
62#[cfg(all(feature = "never_type", not(feature = "blanket_impl")))]
63impl<T> UnwrapInfallible for Result<T, !> {
64    type Ok = T;
65    fn unwrap_infallible(self) -> T {
66        self.unwrap_or_else(|never| never)
67    }
68}
69
70#[cfg(not(feature = "blanket_impl"))]
71impl<T> UnwrapInfallible for Result<T, Infallible> {
72    type Ok = T;
73    fn unwrap_infallible(self) -> T {
74        self.unwrap_or_else(|never| match never {})
75    }
76}
77
78#[cfg(test)]
79mod tests {
80    use super::UnwrapInfallible;
81
82    // Hmm, Infallible is not Into<!> yet
83    #[cfg(not(feature = "blanket_impl"))]
84    #[test]
85    fn with_infallible() {
86        use core::convert::TryFrom;
87
88        let a = 42u8;
89        let a = u64::try_from(a).unwrap_infallible();
90        assert_eq!(a, 42u64);
91    }
92
93    #[cfg(feature = "never_type")]
94    #[test]
95    fn with_never_type() {
96        let r: Result<bool, !> = Ok(true);
97        assert!(r.unwrap_infallible());
98    }
99}