|
1 | 1 | #[doc(primitive = "bool")]
|
2 | 2 | #[doc(alias = "true")]
|
3 | 3 | #[doc(alias = "false")]
|
4 |
| -// |
5 | 4 | /// The boolean type.
|
6 | 5 | ///
|
7 | 6 | /// The `bool` represents a value, which could only be either `true` or `false`. If you cast
|
|
12 | 11 | /// `bool` implements various traits, such as [`BitAnd`], [`BitOr`], [`Not`], etc.,
|
13 | 12 | /// which allow us to perform boolean operations using `&`, `|` and `!`.
|
14 | 13 | ///
|
15 |
| -/// `if` always demands a `bool` value. [`assert!`], being an important macro in testing, |
16 |
| -/// checks whether an expression returns `true`. |
| 14 | +/// `if` always demands a `bool` value. [`assert!`], which is an important macro in testing, |
| 15 | +/// checks whether an expression returns `true` and panics if it isn't. |
17 | 16 | ///
|
18 | 17 | /// ```
|
19 | 18 | /// let bool_val = true & false | false;
|
@@ -194,14 +193,48 @@ mod prim_bool {}
|
194 | 193 | /// # `!` and traits
|
195 | 194 | ///
|
196 | 195 | /// When writing your own traits, `!` should have an `impl` whenever there is an obvious `impl`
|
197 |
| -/// which doesn't `panic!`. As it turns out, most traits can have an `impl` for `!`. Take [`Debug`] |
| 196 | +/// which doesn't `panic!`. The reason is that functions returning an `impl Trait` where `!` |
| 197 | +/// does not have an `impl` of `Trait` cannot diverge as their only possible code path. In other |
| 198 | +/// words, they can't return `!` from every code path. As an example, this code doesn't compile: |
| 199 | +/// |
| 200 | +/// ```compile_fail |
| 201 | +/// use core::ops::Add; |
| 202 | +/// |
| 203 | +/// fn foo() -> impl Add<u32> { |
| 204 | +/// unimplemented!() |
| 205 | +/// } |
| 206 | +/// ``` |
| 207 | +/// |
| 208 | +/// But this code does: |
| 209 | +/// |
| 210 | +/// ``` |
| 211 | +/// use core::ops::Add; |
| 212 | +/// |
| 213 | +/// fn foo() -> impl Add<u32> { |
| 214 | +/// if true { |
| 215 | +/// unimplemented!() |
| 216 | +/// } else { |
| 217 | +/// 0 |
| 218 | +/// } |
| 219 | +/// } |
| 220 | +/// ``` |
| 221 | +/// |
| 222 | +/// The reason is that, in the first example, there are many possible types that `!` could coerce |
| 223 | +/// to, because many types implement `Add<u32>`. However, in the second example, |
| 224 | +/// the `else` branch returns a `0`, which the compiler infers from the return type to be of type |
| 225 | +/// `u32`. Since `u32` is a concrete type, `!` can and will be coerced to it. See issue [#36375] |
| 226 | +/// for more information on this quirk of `!`. |
| 227 | +/// |
| 228 | +/// [#36375]: https://github.com/rust-lang/rust/issues/36375 |
| 229 | +/// |
| 230 | +/// As it turns out, though, most traits can have an `impl` for `!`. Take [`Debug`] |
198 | 231 | /// for example:
|
199 | 232 | ///
|
200 | 233 | /// ```
|
201 | 234 | /// #![feature(never_type)]
|
202 | 235 | /// # use std::fmt;
|
203 | 236 | /// # trait Debug {
|
204 |
| -/// # fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result; |
| 237 | +/// # fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result; |
205 | 238 | /// # }
|
206 | 239 | /// impl Debug for ! {
|
207 | 240 | /// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
0 commit comments