Skip to content

Commit e7d8671

Browse files
committed
Add core::convert::absurd
1 parent 40dcd79 commit e7d8671

File tree

1 file changed

+58
-0
lines changed
  • library/core/src/convert

1 file changed

+58
-0
lines changed

library/core/src/convert/mod.rs

+58
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,64 @@ pub const fn identity<T>(x: T) -> T {
105105
x
106106
}
107107

108+
/// Converts [`!`] (the never type) to any type.
109+
///
110+
/// This is possible because `!` is uninhabited (has no values), so this function can't actually
111+
/// be ever called at runtime.
112+
///
113+
/// Even though `!` can be coerced to any type implicitly anyway (and indeed this function
114+
/// implemented by just "returning" the argument), this is still useful, as this prevents the
115+
/// fallback from happening during typechecking.
116+
///
117+
/// For example, this snippet type checks:
118+
///
119+
/// ```rust
120+
/// let x: Result<_, ()> = Err(());
121+
/// let y = match x {
122+
/// Ok(v) => v,
123+
/// Err(()) => return,
124+
/// };
125+
/// ```
126+
///
127+
/// This is a bit unexpected, because the type of `y` is seemingly unbound (indeed, it can be any
128+
/// type). However, the `match` unifies type of `v` with type of `return` (which is `!`), so `y`
129+
/// becomes `!` (or `()`, because of backwards compatibility shenanigans).
130+
///
131+
/// This can be avoided by adding `absurd`;
132+
///
133+
/// ```compile_fail,E0282
134+
/// use core::convert::absurd;
135+
///
136+
/// let x: Result<_, ()> = Err(());
137+
/// let y = match x { //~ error[E0282]: type annotations needed
138+
/// Ok(v) => v,
139+
///
140+
/// // the call to `absurd` *is* unreachable, but it's still important for type check reasons
141+
/// #[allow(unreachable_code)]
142+
/// Err(()) => absurd(return),
143+
/// };
144+
/// ```
145+
///
146+
/// This might be handy when writing macros.
147+
///
148+
/// `absurd` can also be passed to higher order functions, just like any other function:
149+
///
150+
/// ```
151+
/// #![feature(never_type, convert_absurd)]
152+
/// use core::convert::absurd;
153+
///
154+
/// let x: Result<_, !> = Ok(1);
155+
/// let x: u32 = x.unwrap_or_else(absurd);
156+
/// ```
157+
///
158+
/// [`!`]: ../../primitive.never.html
159+
#[inline(always)]
160+
#[unstable(feature = "convert_absurd", issue = "124310")]
161+
#[rustc_const_unstable(feature = "convert_absurd", issue = "124310")]
162+
pub const fn absurd<T>(x: !) -> T {
163+
x
164+
}
165+
108166
/// Used to do a cheap reference-to-reference conversion.
109167
///
110168
/// This trait is similar to [`AsMut`] which is used for converting between mutable references.

0 commit comments

Comments
 (0)