diff options
| author | Tyler Mandry <tmandry@gmail.com> | 2020-09-01 18:24:29 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-09-01 18:24:29 -0700 |
| commit | 34c8b7a92cd2ced1b4aee960a84f69f6b3a56bb6 (patch) | |
| tree | 5509c1ab83cd8759faf9602c3feb5a6c0f94a05e | |
| parent | 7c1c7de85f47cd527d1935295e68218857d2d969 (diff) | |
| parent | 55637f566993e2f8659aa09288bfc00b9965c524 (diff) | |
| download | rust-34c8b7a92cd2ced1b4aee960a84f69f6b3a56bb6.tar.gz rust-34c8b7a92cd2ced1b4aee960a84f69f6b3a56bb6.zip | |
Rollup merge of #76099 - camelid:patch-8, r=jyn514
Add info about `!` and `impl Trait` Fixes #76094. @rustbot modify labels: T-doc C-enhancement
| -rw-r--r-- | library/std/src/primitive_docs.rs | 43 |
1 files changed, 38 insertions, 5 deletions
diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 2339ca527bd..d00824cfb3e 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -1,7 +1,6 @@ #[doc(primitive = "bool")] #[doc(alias = "true")] #[doc(alias = "false")] -// /// The boolean type. /// /// The `bool` represents a value, which could only be either `true` or `false`. If you cast @@ -12,8 +11,8 @@ /// `bool` implements various traits, such as [`BitAnd`], [`BitOr`], [`Not`], etc., /// which allow us to perform boolean operations using `&`, `|` and `!`. /// -/// `if` always demands a `bool` value. [`assert!`], being an important macro in testing, -/// checks whether an expression returns `true`. +/// `if` always demands a `bool` value. [`assert!`], which is an important macro in testing, +/// checks whether an expression returns `true` and panics if it isn't. /// /// ``` /// let bool_val = true & false | false; @@ -194,14 +193,48 @@ 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` where `!` +/// does not have an `impl` of `Trait` cannot diverge as their only possible code path. In other +/// words, they can't return `!` from every code path. As an example, this code doesn't compile: +/// +/// ```compile_fail +/// use core::ops::Add; +/// +/// fn foo() -> impl Add<u32> { +/// unimplemented!() +/// } +/// ``` +/// +/// But 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 that `!` could coerce +/// to, because many types implement `Add<u32>`. However, in the second example, +/// the `else` branch returns a `0`, which the compiler infers from the return type to be of type +/// `u32`. Since `u32` is a concrete type, `!` can and will be coerced to it. 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 { |
