diff options
| author | Camelid <37223377+camelid@users.noreply.github.com> | 2020-08-29 19:53:06 -0700 |
|---|---|---|
| committer | Camelid <camelidcamel@gmail.com> | 2020-08-29 19:59:22 -0700 |
| commit | 4aae7814075ffe94486e2cc04ff5d08351eb8fd3 (patch) | |
| tree | b27a359f976e77e061b043179d68c3ad3ff3d75c | |
| parent | 62850d882b1f546783d064ca3b51d1f85b92eeb7 (diff) | |
| download | rust-4aae7814075ffe94486e2cc04ff5d08351eb8fd3.tar.gz rust-4aae7814075ffe94486e2cc04ff5d08351eb8fd3.zip | |
Add info about `!` and `impl Trait`
| -rw-r--r-- | library/std/src/primitive_docs.rs | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 2339ca527bd..d88a9cbd0ac 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -194,14 +194,47 @@ mod prim_bool {} /// # `!` and traits /// /// When writing your own traits, `!` should have an `impl` whenever there is an obvious `impl` -/// which doesn't `panic!`. As it turns out, most traits can have an `impl` for `!`. Take [`Debug`] +/// which doesn't `panic!`. The reason is that functions returning an `impl Trait` cannot have +/// divergence, i.e., returning `!`, as their only possible code path. As an example, this code +/// doesn't compile: +/// +/// ```compile_fail +/// use core::ops::Add; +/// +/// fn foo() -> impl Add<u32> { +/// unimplemented!() +/// } +/// ``` +/// +/// While this code does: +/// +/// ``` +/// use core::ops::Add; +/// +/// fn foo() -> impl Add<u32> { +/// if true { +/// unimplemented!() +/// } else { +/// 0 +/// } +/// } +/// ``` +/// +/// The reason is that, in the first example, there are many possible types for `!` to coerce +/// to, because the function's return value is polymorphic. However, in the second example, the +/// other branch returns `0` which has a concrete type that `!` can be coerced to. See issue +/// [#36375] for more information on this quirk of `!`. +/// +/// [#36375]: https://github.com/rust-lang/rust/issues/36375 +/// +/// As it turns out, though, most traits can have an `impl` for `!`. Take [`Debug`] /// for example: /// /// ``` /// #![feature(never_type)] /// # use std::fmt; /// # trait Debug { -/// # fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result; +/// # fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result; /// # } /// impl Debug for ! { /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { |
