@@ -4249,13 +4249,46 @@ declare_lint! {
4249
4249
/// The `never_type_fallback_flowing_into_unsafe` lint detects cases where never type fallback
4250
4250
/// affects unsafe function calls.
4251
4251
///
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
+ /// ```ignore (illustrative-and-has-placeholders)
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
+ ///
4252
4285
/// ### Example
4253
4286
///
4254
4287
/// ```rust,compile_fail
4255
4288
/// #![deny(never_type_fallback_flowing_into_unsafe)]
4256
4289
/// fn main() {
4257
4290
/// 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
4259
4292
/// return
4260
4293
/// } else {
4261
4294
/// // `zeroed` is an unsafe function, which returns an unbounded type
@@ -4270,7 +4303,7 @@ declare_lint! {
4270
4303
///
4271
4304
/// ### Explanation
4272
4305
///
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
4274
4307
/// coerced to `()`. There are plans to change that, but they may make the code such as above
4275
4308
/// unsound. Instead of depending on the fallback, you should specify the type explicitly:
4276
4309
/// ```
@@ -4283,6 +4316,9 @@ declare_lint! {
4283
4316
/// ```
4284
4317
///
4285
4318
/// 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
4286
4322
pub NEVER_TYPE_FALLBACK_FLOWING_INTO_UNSAFE ,
4287
4323
Warn ,
4288
4324
"never type fallback affecting unsafe function calls"
0 commit comments