@@ -4250,13 +4250,46 @@ declare_lint! {
42504250 /// The `never_type_fallback_flowing_into_unsafe` lint detects cases where never type fallback
42514251 /// affects unsafe function calls.
42524252 ///
4253+ /// ### Never type fallback
4254+ ///
4255+ /// When the compiler sees a value of type [`!`] it implicitly inserts a coercion (if possible),
4256+ /// to allow type check to infer any type:
4257+ ///
4258+ /// ```ignore (illustrative-and-has-placeholders)
4259+ /// // this
4260+ /// let x: u8 = panic!();
4261+ ///
4262+ /// // is (essentially) turned by the compiler into
4263+ /// let x: u8 = absurd(panic!());
4264+ ///
4265+ /// // where absurd is a function with the following signature
4266+ /// // (it's sound, because `!` always marks unreachable code):
4267+ /// fn absurd<T>(_: !) -> T { ... }
4268+ // FIXME: use `core::convert::absurd` here instead, once it's merged
4269+ /// ```
4270+ ///
4271+ /// While it's convenient to be able to use non-diverging code in one of the branches (like
4272+ /// `if a { b } else { return }`) this could lead to compilation errors:
4273+ ///
4274+ /// ```compile_fail
4275+ /// // this
4276+ /// { panic!() };
4277+ ///
4278+ /// // gets turned into this
4279+ /// { absurd(panic!()) }; // error: can't infer the type of `absurd`
4280+ /// ```
4281+ ///
4282+ /// To prevent such errors, compiler remembers where it inserted `absurd` calls, and if it
4283+ /// can't infer their type, it sets the type to fallback. `{ absurd::<Fallback>(panic!()) };`.
4284+ /// This is what is known as "never type fallback".
4285+ ///
42534286 /// ### Example
42544287 ///
42554288 /// ```rust,compile_fail
42564289 /// #![deny(never_type_fallback_flowing_into_unsafe)]
42574290 /// fn main() {
42584291 /// if true {
4259- /// // return has type `!` (never) which, is some cases, causes never type fallback
4292+ /// // return has type `!` which, is some cases, causes never type fallback
42604293 /// return
42614294 /// } else {
42624295 /// // `zeroed` is an unsafe function, which returns an unbounded type
@@ -4271,7 +4304,7 @@ declare_lint! {
42714304 ///
42724305 /// ### Explanation
42734306 ///
4274- /// Due to historic reasons never type fallback were `()`, meaning that `!` got spontaneously
4307+ /// Due to historic reasons never type fallback was `()`, meaning that `!` got spontaneously
42754308 /// coerced to `()`. There are plans to change that, but they may make the code such as above
42764309 /// unsound. Instead of depending on the fallback, you should specify the type explicitly:
42774310 /// ```
@@ -4284,6 +4317,9 @@ declare_lint! {
42844317 /// ```
42854318 ///
42864319 /// See [Tracking Issue for making `!` fall back to `!`](https://github.com/rust-lang/rust/issues/123748).
4320+ ///
4321+ /// [`!`]: https://doc.rust-lang.org/core/primitive.never.html
4322+ /// [`()`]: https://doc.rust-lang.org/core/primitive.unit.html
42874323 pub NEVER_TYPE_FALLBACK_FLOWING_INTO_UNSAFE ,
42884324 Warn ,
42894325 "never type fallback affecting unsafe function calls"
0 commit comments