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