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(primitive = "bool")]
|
||||||
#[doc(alias = "true")]
|
#[doc(alias = "true")]
|
||||||
#[doc(alias = "false")]
|
#[doc(alias = "false")]
|
||||||
//
|
|
||||||
/// The boolean type.
|
/// The boolean type.
|
||||||
///
|
///
|
||||||
/// The `bool` represents a value, which could only be either `true` or `false`. If you cast
|
/// 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.,
|
/// `bool` implements various traits, such as [`BitAnd`], [`BitOr`], [`Not`], etc.,
|
||||||
/// which allow us to perform boolean operations using `&`, `|` and `!`.
|
/// which allow us to perform boolean operations using `&`, `|` and `!`.
|
||||||
///
|
///
|
||||||
/// `if` always demands a `bool` value. [`assert!`], being an important macro in testing,
|
/// `if` always demands a `bool` value. [`assert!`], which is an important macro in testing,
|
||||||
/// checks whether an expression returns `true`.
|
/// checks whether an expression returns `true` and panics if it isn't.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let bool_val = true & false | false;
|
/// let bool_val = true & false | false;
|
||||||
@ -194,14 +193,48 @@ mod prim_bool {}
|
|||||||
/// # `!` and traits
|
/// # `!` and traits
|
||||||
///
|
///
|
||||||
/// When writing your own traits, `!` should have an `impl` whenever there is an obvious `impl`
|
/// 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:
|
/// for example:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(never_type)]
|
/// #![feature(never_type)]
|
||||||
/// # use std::fmt;
|
/// # use std::fmt;
|
||||||
/// # trait Debug {
|
/// # trait Debug {
|
||||||
/// # fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result;
|
/// # fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result;
|
||||||
/// # }
|
/// # }
|
||||||
/// impl Debug for ! {
|
/// impl Debug for ! {
|
||||||
/// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
/// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
Loading…
Reference in New Issue
Block a user