@@ -268,6 +268,47 @@ mod prim_bool {}
268268/// [`Debug`]: fmt::Debug
269269/// [`default()`]: Default::default
270270///
271+ /// # Never type fallback
272+ ///
273+ /// When the compiler sees a value of type `!` it implicitly inserts a coercion (if possible),
274+ /// to allow type check to infer any type:
275+ ///
276+ /// ```rust,ignore (illustrative-and-has-placeholders)
277+ /// // this
278+ /// let x: u8 = panic!();
279+ ///
280+ /// // is (essentially) turned by the compiler into
281+ /// let x: u8 = absurd(panic!());
282+ ///
283+ /// // where absurd is a function with the following signature
284+ /// // (it's sound, because `!` always marks unreachable code):
285+ /// fn absurd<T>(_: !) -> T { ... }
286+ // FIXME: use `core::convert::absurd` here instead, once it's merged
287+ /// ```
288+ ///
289+ /// While it's convenient to be able to use non-diverging code in one of the branches (like
290+ /// `if a { b } else { return }`) this could lead to compilation errors:
291+ ///
292+ /// ```compile_fail
293+ /// // this
294+ /// { panic!() };
295+ ///
296+ /// // gets turned into this
297+ /// { absurd(panic!()) }; // error: can't infer the type of `absurd`
298+ /// ```
299+ ///
300+ /// To prevent such errors, compiler remembers where it inserted `absurd` calls, and if it can't
301+ /// infer their type, it sets the type to the fallback type. `{ absurd::<Fallback>(panic!()) };`.
302+ /// This is what is known as "never type fallback".
303+ ///
304+ /// Historically fallback was [`()`], causing confusing behavior where `!` spontaneously coerced
305+ /// to `()`, even though `()` was never mentioned (because of the fallback). There are plans to
306+ /// change it in 2024 edition (and possibly in all editions on a later date), see
307+ /// [Tracking Issue for making `!` fall back to `!`][fallback-ti].
308+ ///
309+ /// [`()`]: prim@unit
310+ /// [fallback-ti]: https://github.com/rust-lang/rust/issues/123748
311+ ///
271312#[ unstable( feature = "never_type" , issue = "35121" ) ]
272313mod prim_never { }
273314
0 commit comments