Primitive Type never [−]
The !
type, also called "never".
!
represents the type of computations which never resolve to any value at all. For example,
the exit
function fn exit(code: i32) -> !
exits the process without ever returning, and
so returns !
.
break
, continue
and return
expressions also have type !
. For example we are allowed to
write:
#![feature(never_type)] let x: ! = { return 123 };Run
Although the let
is pointless here, it illustrates the meaning of !
. Since x
is never
assigned a value (because return
returns from the entire function), x
can be given type
!
. We could also replace return 123
with a panic!
or a never-ending loop
and this code
would still be valid.
A more realistic usage of !
is in this code:
let num: u32 = match get_a_number() { Some(num) => num, None => break, };Run
Both match arms must produce values of type u32
, but since break
never produces a value
at all we know it can never produce a value which isn't a u32
. This illustrates another
behaviour of the !
type - expressions with type !
will coerce into any other type.
!
and generics
The main place you'll see !
used explicitly is in generic code. Consider the FromStr
trait:
trait FromStr: Sized { type Err; fn from_str(s: &str) -> Result<Self, Self::Err>; }Run
When implementing this trait for String
we need to pick a type for Err
. And since
converting a string into a string will never result in an error, the appropriate type is !
.
(Currently the type actually used is an enum with no variants, though this is only because !
was added to Rust at a later date and it may change in the future). With an Err
type of
!
, if we have to call String::from_str
for some reason the result will be a
Result<String, !>
which we can unpack like this:
#[feature(exhaustive_patterns)] // NOTE: This does not work today! let Ok(s) = String::from_str("hello");Run
Since the Err
variant contains a !
, it can never occur. If the exhaustive_patterns
feature is present this means we can exhaustively match on Result<T, !>
by just taking the
Ok
variant. This illustrates another behaviour of !
- it can be used to "delete" certain
enum variants from generic types like Result
.
!
and traits
When writing your own traits, !
should have an impl
whenever there is an obvious impl
which doesn't panic!
. As is turns out, most traits can have an impl
for !
. Take Debug
for example:
#![feature(never_type)] impl Debug for ! { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { *self } }Run
Once again we're using !
's ability to coerce into any other type, in this case
fmt::Result
. Since this method takes a &!
as an argument we know that it can never be
called (because there is no value of type !
for it to be called with). Writing *self
essentially tells the compiler "We know that this code can never be run, so just treat the
entire function body has having type fmt::Result
". This pattern can be used a lot when
implementing traits for !
. Generally, any trait which only has methods which take a self
parameter should have such as impl.
On the other hand, one trait which would not be appropriate to implement is Default
:
trait Default { fn default() -> Self; }Run
Since !
has no values, it has no default value either. It's true that we could write an
impl
for this which simply panics, but the same is true for any type (we could impl Default
for (eg.) File
by just making default()
panic.)
Trait Implementations
impl Debug for !
[src]
impl Debug for !
fn fmt(&self, &mut Formatter) -> Result<(), Error>
[src]
fn fmt(&self, &mut Formatter) -> Result<(), Error>
Formats the value using the given formatter. Read more
impl Ord for !
[src]
impl Ord for !
fn cmp(&self, &!) -> Ordering
[src]
fn cmp(&self, &!) -> Ordering
This method returns an Ordering
between self
and other
. Read more
fn max(self, other: Self) -> Self
1.21.0[src]
fn max(self, other: Self) -> Self
Compares and returns the maximum of two values. Read more
fn min(self, other: Self) -> Self
1.21.0[src]
fn min(self, other: Self) -> Self
Compares and returns the minimum of two values. Read more
impl PartialEq<!> for !
[src]
impl PartialEq<!> for !
fn eq(&self, &!) -> bool
[src]
fn eq(&self, &!) -> bool
This method tests for self
and other
values to be equal, and is used by ==
. Read more
fn ne(&self, other: &Rhs) -> bool
1.0.0[src]
fn ne(&self, other: &Rhs) -> bool
This method tests for !=
.
impl Display for !
[src]
impl Display for !
fn fmt(&self, &mut Formatter) -> Result<(), Error>
[src]
fn fmt(&self, &mut Formatter) -> Result<(), Error>
Formats the value using the given formatter. Read more
impl PartialOrd<!> for !
[src]
impl PartialOrd<!> for !
fn partial_cmp(&self, &!) -> Option<Ordering>
[src]
fn partial_cmp(&self, &!) -> Option<Ordering>
This method returns an ordering between self
and other
values if one exists. Read more
fn lt(&self, other: &Rhs) -> bool
1.0.0[src]
fn lt(&self, other: &Rhs) -> bool
This method tests less than (for self
and other
) and is used by the <
operator. Read more
fn le(&self, other: &Rhs) -> bool
1.0.0[src]
fn le(&self, other: &Rhs) -> bool
This method tests less than or equal to (for self
and other
) and is used by the <=
operator. Read more
fn gt(&self, other: &Rhs) -> bool
1.0.0[src]
fn gt(&self, other: &Rhs) -> bool
This method tests greater than (for self
and other
) and is used by the >
operator. Read more
fn ge(&self, other: &Rhs) -> bool
1.0.0[src]
fn ge(&self, other: &Rhs) -> bool
This method tests greater than or equal to (for self
and other
) and is used by the >=
operator. Read more
impl Eq for !
[src]
impl Eq for !
impl Error for !
[src]
impl Error for !
fn description(&self) -> &str
[src]
fn description(&self) -> &str
A short description of the error. Read more
fn cause(&self) -> Option<&Error>
1.0.0[src]
fn cause(&self) -> Option<&Error>
The lower-level cause of this error, if any. Read more
impl Termination for !
[src]
impl Termination for !