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}