rewrite never type documentation#158370
Conversation
There was a problem hiding this comment.
Due to the slightly messy diff, I ended up splitting my review up into many small comments, so apologies for the large number of them. Most are copy-edits, with a couple small content changes here and there. Feel free to use them or not as you see fit.
| /// `!` is the canonical uninhabited type. `!` represents the type of diverging computations -- | ||
| /// computations which never resolve to any value. |
There was a problem hiding this comment.
| /// `!` is the canonical uninhabited type. `!` represents the type of diverging computations -- | |
| /// computations which never resolve to any value. | |
| /// `!` represents the type of diverging computations -- computations which never resolve to any | |
| /// value. It the canonical uninhabited type. |
| /// For example, the [`exit`] function is defined as returning `!`, to signify that it doesn't | ||
| /// return normally and exits the process instead. Thus, any code following a call to [`exit`] is | ||
| /// unreachable. ([`panic!`] works the same way.) |
There was a problem hiding this comment.
| /// For example, the [`exit`] function is defined as returning `!`, to signify that it doesn't | |
| /// return normally and exits the process instead. Thus, any code following a call to [`exit`] is | |
| /// unreachable. ([`panic!`] works the same way.) | |
| /// For example, the [`exit`] function is defined as returning `!`, to signify that it exits the | |
| /// process instead of returning normally. Thus, any code following a call to [`exit`] is | |
| /// unreachable. The [`panic!`] macro works the same way. |
There was a problem hiding this comment.
I think your suggestion is misleading here. returning ! doesn't signify that the function exits the process, only that it doesn't return. Now realizing, that my version kind-of struggles from the same issue...
How about the following?
For example, the
exitfunction is defined as returning!, to signify that it doesn't return normally (as it exits the process instead).
| /// Similarly, [`return`], [`break`], [`continue`], [`become`], and infinite [`loop`] expressions | ||
| /// all have type `!`, as the code following them is unreachable. |
There was a problem hiding this comment.
Should become be included here if it is still unstable?
| /// This is because `impl Trait` is not a specific type in and of itself, but instead a marker that | ||
| /// the return type of the function is hidden and the only thing that can be assumed by the caller | ||
| /// is that whatever the type is, it implements `Trait`. |
There was a problem hiding this comment.
| /// This is because `impl Trait` is not a specific type in and of itself, but instead a marker that | |
| /// the return type of the function is hidden and the only thing that can be assumed by the caller | |
| /// is that whatever the type is, it implements `Trait`. | |
| /// Here, never-to-any coercion fails because `impl Trait` is not itself a concrete type, but rather | |
| /// a way to tell the compiler that a function's return type is hidden, and the only thing which can | |
| /// be assumed about this type is that it implements `Trait`. |
There was a problem hiding this comment.
Never-to-any doesn't fail here; the failure is that the hidden type doesn't implement the correct trait.
I rewrote "a specific type in and of itself" though.
There was a problem hiding this comment.
True, there is no actual coercion attempt happening here. What do you think of:
This is because
impl Traitis not a concrete type, but rather a way to tell the compiler that
a function's return type is hidden, and the only thing which can be assumed about the hidden
type is that it implementsTrait.
| /// In case of using `todo!()` the hidden return type is inferred to be `!`, which may not | ||
| /// implement the trait. |
There was a problem hiding this comment.
| /// In case of using `todo!()` the hidden return type is inferred to be `!`, which may not | |
| /// implement the trait. | |
| /// The compiler then attempts to choose such a concrete type, but is unable to do so. In this case, | |
| /// we abandon the coercion and fall back to just the never type itself, which will fail to compile | |
| /// if `!` does not implement `Trait`. |
I think fallback should be explicitly mentioned here.
There was a problem hiding this comment.
The compiler then attempts to choose such a concrete type, but is unable to do so.
This is not true; the compiler chooses ! here.
I think mentioning fallback here only makes it more confusing...
There was a problem hiding this comment.
You're right, I kind of forgot that ! is a concrete type. How about the following (which merges the sentence after as well):
In this case, the hidden return type is inferred to be
!, which does not implementIterator.
A fix to this is to explicitly cast!to a type which implements the trait:
| /// // Enum with no variants is an example of an uninhabited type | ||
| /// enum Void {} |
There was a problem hiding this comment.
| /// // Enum with no variants is an example of an uninhabited type | |
| /// enum Void {} | |
| /// // An enum with no variants is an example of an uninhabited type | |
| /// enum Void {} |
Probably this should be moved up above the definition of Onomatopoeias
There was a problem hiding this comment.
Probably this should be moved up above the definition of
Onomatopoeias
Why?
There was a problem hiding this comment.
When reading the example code for the first time, seeing Mjau(Void) and a mention of "other uninhabited types" without first seeing that Void is user-defined in this example could imply that it's some existing built-in type. Moving the definition of Void up top clears that up.
Also, the sentence right before the example mentions that there are other uninhabited types besides !, and this also immediately answers the question of what exactly those might be.
Co-authored-by: Kevin Reid <kpreid@switchb.org>
Co-authored-by: Kevin Reid <kpreid@switchb.org> Co-authored-by: Michael Krasnitski <42564254+mkrasnitski@users.noreply.github.com> Co-authored-by: waffle <waffle.lapkin@gmail.com>
Co-authored-by: Michael Krasnitski <42564254+mkrasnitski@users.noreply.github.com>
f2dc120 to
cd5b51c
Compare
| /// This is because `impl Trait` is not a specific type in and of itself, but instead a marker that | ||
| /// the return type of the function is hidden and the only thing that can be assumed by the caller | ||
| /// is that whatever the type is, it implements `Trait`. |
There was a problem hiding this comment.
Never-to-any doesn't fail here; the failure is that the hidden type doesn't implement the correct trait.
I rewrote "a specific type in and of itself" though.
| /// At first glance there is no reason to implement any traits for `!`. Most traits take a value | ||
| /// of `Self` as an argument in methods, so you won't be able to call them anyway. |
There was a problem hiding this comment.
Incorporated this into my last commit.
View all comments
With the never type stabilization approaching, I think the documentation could be improved a lot over the status quo ^^'
I intend to merge this after #155499. Split it off into a separate PR for ease of reviewing.