Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add core::convert::absurd #124311

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions library/core/src/convert/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,64 @@ pub const fn identity<T>(x: T) -> T {
x
}

/// Converts [`!`] (the never type) to any type.
///
/// This is possible because `!` is uninhabited (has no values), so this function can't actually
/// be ever called at runtime.
///
/// Even though `!` can be coerced to any type implicitly anyway (and indeed this function
/// implemented by just "returning" the argument), this is still useful, as this prevents the
/// fallback from happening during typechecking.
///
/// For example, this snippet type checks:
///
/// ```rust
/// let x: Result<_, ()> = Err(());
/// let y = match x {
/// Ok(v) => v,
/// Err(()) => return,
/// };
/// ```
///
/// This is a bit unexpected, because the type of `y` is seemingly unbound (indeed, it can be any
/// type). However, the `match` unifies type of `v` with type of `return` (which is `!`), so `y`
/// becomes `!` (or `()`, because of backwards compatibility shenanigans).
///
/// This can be avoided by adding `absurd`;
///
/// ```compile_fail,E0282
/// use core::convert::absurd;
///
/// let x: Result<_, ()> = Err(());
/// let y = match x { //~ error[E0282]: type annotations needed
/// Ok(v) => v,
///
/// // the call to `absurd` *is* unreachable, but it's still important for type check reasons
/// #[allow(unreachable_code)]
/// Err(()) => absurd(return),
/// };
/// ```
///
/// This might be handy when writing macros.
///
/// `absurd` can also be passed to higher order functions, just like any other function:
///
/// ```
/// #![feature(never_type, convert_absurd)]
/// use core::convert::absurd;
///
/// let x: Result<_, !> = Ok(1);
/// let x: u32 = x.unwrap_or_else(absurd);
/// ```
///
/// [`!`]: ../../std/primitive.never.html
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// [`!`]: ../../std/primitive.never.html
/// [`!`]: prim@never

#[inline(always)]
#[unstable(feature = "convert_absurd", issue = "124310")]
#[rustc_const_unstable(feature = "convert_absurd", issue = "124310")]
pub const fn absurd<T>(x: !) -> T {
x
}

/// Used to do a cheap reference-to-reference conversion.
///
/// This trait is similar to [`AsMut`] which is used for converting between mutable references.
Expand Down
Loading