From 23b67de1513f412d0df37ece3bd90a3fd653c444 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Fri, 26 Apr 2024 20:48:15 +0200 Subject: [PATCH] Document never type fallback in `!`'s docs --- library/core/src/primitive_docs.rs | 41 ++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index bda1ee6f457..99b132fe399 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -268,6 +268,47 @@ mod prim_bool {} /// [`Debug`]: fmt::Debug /// [`default()`]: Default::default /// +/// # Never type fallback +/// +/// When the compiler sees a value of type `!` it implicitly inserts a coercion (if possible), +/// to allow type check to infer any type: +/// +/// ```rust,ignore (illustrative-and-has-placeholders) +/// // this +/// let x: u8 = panic!(); +/// +/// // is (essentially) turned by the compiler into +/// let x: u8 = absurd(panic!()); +/// +/// // where absurd is a function with the following signature +/// // (it's sound, because `!` always marks unreachable code): +/// fn absurd(_: !) -> T { ... } +// FIXME: use `core::convert::absurd` here instead, once it's merged +/// ``` +/// +/// While it's convenient to be able to use non-diverging code in one of the branches (like +/// `if a { b } else { return }`) this could lead to compilation errors: +/// +/// ```compile_fail +/// // this +/// { panic!() }; +/// +/// // gets turned into this +/// { absurd(panic!()) }; // error: can't infer the type of `absurd` +/// ``` +/// +/// To prevent such errors, compiler remembers where it inserted `absurd` calls, and if it can't +/// infer their type, it sets the type to the fallback type. `{ absurd::(panic!()) };`. +/// This is what is known as "never type fallback". +/// +/// Historically fallback was [`()`], causing confusing behavior where `!` spontaneously coerced +/// to `()`, even though `()` was never mentioned (because of the fallback). There are plans to +/// change it in 2024 edition (and possibly in all editions on a later date), see +/// [Tracking Issue for making `!` fall back to `!`][fallback-ti]. +/// +/// [`()`]: prim@unit +/// [fallback-ti]: https://github.com/rust-lang/rust/issues/123748 +/// #[unstable(feature = "never_type", issue = "35121")] mod prim_never {}