mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-03 02:23:20 +00:00
Rollup merge of #76099 - camelid:patch-8, r=jyn514
Add info about `!` and `impl Trait` Fixes #76094. @rustbot modify labels: T-doc C-enhancement
This commit is contained in:
commit
34c8b7a92c
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user