about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-05-02 11:54:53 +0000
committerbors <bors@rust-lang.org>2024-05-02 11:54:53 +0000
commit80451a485b006bd32732c003a54ee7de457d8266 (patch)
tree2f62f8e019f6c5ead594d33c3405592d2342fb00
parentf5efc3c286a8e625f7932f9e6f52e5812a4b67fc (diff)
parente18b6e819e703a6f66c93e803655b62146f9d018 (diff)
downloadrust-80451a485b006bd32732c003a54ee7de457d8266.tar.gz
rust-80451a485b006bd32732c003a54ee7de457d8266.zip
Auto merge of #124419 - WaffleLapkin:never-type-fallback-docs, r=workingjubilee
Document never type fallback in `!`'s docs

Pulled the documentation I've written for #123939.

I want a single place where never type fallback is explained, which can be referred in all the lints and migration materials.
-rw-r--r--library/core/src/primitive_docs.rs47
1 files changed, 47 insertions, 0 deletions
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index bda1ee6f457..18a9503cfd2 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -268,6 +268,53 @@ mod prim_bool {}
 /// [`Debug`]: fmt::Debug
 /// [`default()`]: Default::default
 ///
+/// # Never type fallback
+///
+/// When the compiler sees a value of type `!` in a [coercion site], it implicitly inserts a
+/// coercion to allow the type checker 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
+/// ```
+///
+/// This can lead to compilation errors if the type cannot be inferred:
+///
+/// ```compile_fail
+/// // this
+/// { panic!() };
+///
+/// // gets turned into this
+/// { absurd(panic!()) }; // error: can't infer the type of `absurd`
+/// ```
+///
+/// To prevent such errors, the compiler remembers where it inserted `absurd` calls, and
+/// if it can't infer the type, it uses the fallback type instead:
+/// ```rust, ignore
+/// type Fallback = /* An arbitrarily selected type! */;
+/// { absurd::<Fallback>(panic!()) }
+/// ```
+///
+/// This is what is known as "never type fallback".
+///
+/// Historically, the fallback type was [`()`], causing confusing behavior where `!` spontaneously
+/// coerced to `()`, even when it would not infer `()` without the fallback. There are plans to
+/// change it in the [2024 edition] (and possibly in all editions on a later date); see
+/// [Tracking Issue for making `!` fall back to `!`][fallback-ti].
+///
+/// [coercion site]: <https://doc.rust-lang.org/reference/type-coercions.html#coercion-sites>
+/// [`()`]: prim@unit
+/// [fallback-ti]: <https://github.com/rust-lang/rust/issues/123748>
+/// [2024 edition]: <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/index.html>
+///
 #[unstable(feature = "never_type", issue = "35121")]
 mod prim_never {}