diff options
| author | Waffle Lapkin <waffle.lapkin@gmail.com> | 2024-04-26 20:48:15 +0200 |
|---|---|---|
| committer | Waffle Lapkin <waffle.lapkin@gmail.com> | 2024-04-26 20:49:34 +0200 |
| commit | 23b67de1513f412d0df37ece3bd90a3fd653c444 (patch) | |
| tree | d2a4cd62c68014e3cb4df05176d0344cdf8f1caa | |
| parent | 6a9758d4f38d4763bd437c48fa7e5246cecf8d04 (diff) | |
| download | rust-23b67de1513f412d0df37ece3bd90a3fd653c444.tar.gz rust-23b67de1513f412d0df37ece3bd90a3fd653c444.zip | |
Document never type fallback in `!`'s docs
| -rw-r--r-- | library/core/src/primitive_docs.rs | 41 |
1 files changed, 41 insertions, 0 deletions
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>(_: !) -> 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::<Fallback>(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 {} |
