Movatterモバイル変換


[0]ホーム

URL:


never

Primitive Typenever 

🔬This is a nightly-only experimental API. (never_type #35121)
Expand description

The! type, also called “never”.

! represents the type of computations which never resolve to any value at all. For example,theexit functionfn exit(code: i32) -> ! exits the process without ever returning, andso returns!.

break,continue andreturn expressions also have type!. For example we are allowed towrite:

#![feature(never_type)]letx: ! = {return123};

Although thelet is pointless here, it illustrates the meaning of!. Sincex is neverassigned a value (becausereturn returns from the entire function),x can be given type!. We could also replacereturn 123 with apanic! or a never-endingloop and this codewould still be valid.

A more realistic usage of! is in this code:

letnum: u32 =matchget_a_number() {Some(num) => num,None=>break,};

Both match arms must produce values of typeu32, but sincebreak never produces a valueat all we know it can never produce a value which isn’t au32. This illustrates anotherbehavior of the! type - expressions with type! will coerce into any other type.

§! and generics

§Infallible errors

The main place you’ll see! used explicitly is in generic code. Consider theFromStrtrait:

traitFromStr: Sized {typeErr;fnfrom_str(s:&str) ->Result<Self,Self::Err>;}

When implementing this trait forString we need to pick a type forErr. And sinceconverting 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 anErr type of!, if we have to callString::from_str for some reason the result will be aResult<String, !> which we can unpack like this:

usestd::str::FromStr;letOk(s) = String::from_str("hello");

Since theErr variant contains a!, it can never occur. This means we can exhaustivelymatch onResult<T, !> by just taking theOk variant. This illustrates another behaviorof! - it can be used to “delete” certain enum variants from generic types likeResult.

§Infinite loops

WhileResult<T, !> is very useful for removing errors,! can also be used to removesuccesses as well. If we think ofResult<T, !> as “if this function returns, it has noterrored,” we get a very intuitive idea ofResult<!, E> as well: if the function returns, ithas errored.

For example, consider the case of a simple web server, which can be simplified to:

loop{let(client, request) = get_request().expect("disconnected");letresponse = request.process();    response.send(client);}

Currently, this isn’t ideal, because we simply panic whenever we fail to get a new connection.Instead, we’d like to keep track of this error, like this:

loop{matchget_request() {Err(err) =>breakerr,Ok((client, request)) => {letresponse = request.process();            response.send(client);        },    }}

Now, when the server disconnects, we exit the loop with an error instead of panicking. While itmight be intuitive to simply return the error, we might want to wrap it in aResult<!, E>instead:

fnserver_loop() ->Result<!, ConnectionError> {loop{let(client, request) = get_request()?;letresponse = request.process();        response.send(client);    }}

Now, we can use? instead ofmatch, and the return type makes a lot more sense: if the loopever stops, it means that an error occurred. We don’t even have to wrap the loop in anOkbecause! coerces toResult<!, ConnectionError> automatically.

§! and traits

When writing your own traits,! should have animpl whenever there is an obviousimplwhich doesn’tpanic!. The reason is that functions returning animpl Trait where!does not have animpl ofTrait cannot diverge as their only possible code path. In otherwords, they can’t return! from every code path. As an example, this code doesn’t compile:

usestd::ops::Add;fnfoo() ->implAdd<u32> {unimplemented!()}

But this code does:

usestd::ops::Add;fnfoo() ->implAdd<u32> {iftrue{unimplemented!()    }else{0}}

The reason is that, in the first example, there are many possible types that! could coerceto, because many types implementAdd<u32>. However, in the second example,theelse branch returns a0, which the compiler infers from the return type to be of typeu32. Sinceu32 is a concrete type,! can and will be coerced to it. See issue#36375for more information on this quirk of!.

As it turns out, though, most traits can have animpl for!. TakeDebugfor example:

#![feature(never_type)]implDebugfor ! {fnfmt(&self, formatter:&mutfmt::Formatter<'_>) -> fmt::Result {*self}}

Once again we’re using!’s ability to coerce into any other type, in this casefmt::Result. Since this method takes a&! as an argument we know that it can never becalled (because there is no value of type! for it to be called with). Writing*selfessentially tells the compiler “We know that this code can never be run, so just treat theentire function body as having typefmt::Result”. This pattern can be used a lot whenimplementing traits for!. Generally, any trait which only has methods which take aselfparameter should have such an impl.

On the other hand, one trait which would not be appropriate to implement isDefault:

traitDefault {fndefault() ->Self;}

Since! has no values, it has no default value either. It’s true that we could write animpl for this which simply panics, but the same is true for any type (we couldimpl Default for (eg.)File by just makingdefault() panic.)

§Never type fallback

When the compiler sees a value of type! in acoercion site, it implicitly inserts acoercion to allow the type checker to infer any type:

// thisletx: u8 =panic!();// is (essentially) turned by the compiler intoletx: u8 = absurd(panic!());// where absurd is a function with the following signature// (it's sound, because `!` always marks unreachable code):fnabsurd<T>(_: !) -> T { ... }

This can lead to compilation errors if the type cannot be inferred:

// this{panic!() };// gets turned into this{ absurd(panic!()) };// error: can't infer the type of `absurd`

To prevent such errors, the compiler remembers where it insertedabsurd calls, andif it can’t infer the type, it uses the fallback type instead:

typeFallback =/* An arbitrarily selected type! */;{ absurd::<Fallback>(panic!()) }

This is what is known as “never type fallback”.

Historically, the fallback type was(), causing confusing behavior where! spontaneouslycoerced to(), even when it would not infer() without the fallback. The fallback was changedto! in the2024 edition, and will be changed in all editions at a later date.

Trait Implementations§

Source§

implClone for!

Source§

fnclone(&self) ->!

Returns a duplicate of the value.Read more
1.0.0 ·Source§

fnclone_from(&mut self, source: &Self)

Performs copy-assignment fromsource.Read more
Source§

implDebug for!

Source§

fnfmt(&self, _: &mutFormatter<'_>) ->Result<(),Error>

Formats the value using the given formatter.Read more
Source§

implDisplay for!

Source§

fnfmt(&self, _: &mutFormatter<'_>) ->Result<(),Error>

Formats the value using the given formatter.Read more
Source§

implError for!

1.30.0 ·Source§

fnsource(&self) ->Option<&(dynError + 'static)>

Returns the lower-level source of this error, if any.Read more
1.0.0 ·Source§

fndescription(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.0.0 ·Source§

fncause(&self) ->Option<&dynError>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
Source§

fnprovide<'a>(&'a self, request: &mutRequest<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access #99301)
Provides type-based access to context intended for error reports.Read more
1.34.0 (const:unstable) ·Source§

implFrom<!> forInfallible

Source§

fnfrom(x:!) ->Infallible

Converts to this type from the input type.
Source§

implFrom<!> forTryFromIntError

Source§

fnfrom(never:!) ->TryFromIntError

Converts to this type from the input type.
1.29.0 ·Source§

implHash for!

Source§

fnhash<H>(&self, _:&mut H)
where H:Hasher,

Feeds this value into the givenHasher.Read more
1.3.0 ·Source§

fnhash_slice<H>(data: &[Self], state:&mut H)
where H:Hasher, Self:Sized,

Feeds a slice of this type into the givenHasher.Read more
1.60.0 (const:unstable) ·Source§

implNot for!

Source§

typeOutput =!

The resulting type after applying the! operator.
Source§

fnnot(self) ->!

Performs the unary! operation.Read more
Source§

implOrd for!

Source§

fncmp(&self, _: &!) ->Ordering

This method returns anOrdering betweenself andother.Read more
1.21.0 ·Source§

fnmax(self, other: Self) -> Self
where Self:Sized,

Compares and returns the maximum of two values.Read more
1.21.0 ·Source§

fnmin(self, other: Self) -> Self
where Self:Sized,

Compares and returns the minimum of two values.Read more
1.50.0 ·Source§

fnclamp(self, min: Self, max: Self) -> Self
where Self:Sized,

Restrict a value to a certain interval.Read more
Source§

implPartialEq for!

Source§

fneq(&self, _: &!) ->bool

Tests forself andother values to be equal, and is used by==.
1.0.0 ·Source§

fnne(&self, other:&Rhs) ->bool

Tests for!=. The default implementation is almost always sufficient,and should not be overridden without very good reason.
Source§

implPartialOrd for!

Source§

fnpartial_cmp(&self, _: &!) ->Option<Ordering>

This method returns an ordering betweenself andother values if one exists.Read more
1.0.0 ·Source§

fnlt(&self, other:&Rhs) ->bool

Tests less than (forself andother) and is used by the< operator.Read more
1.0.0 ·Source§

fnle(&self, other:&Rhs) ->bool

Tests less than or equal to (forself andother) and is used by the<= operator.Read more
1.0.0 ·Source§

fngt(&self, other:&Rhs) ->bool

Tests greater than (forself andother) and is used by the>operator.Read more
1.0.0 ·Source§

fnge(&self, other:&Rhs) ->bool

Tests greater than or equal to (forself andother) and is used bythe>= operator.Read more
1.61.0 ·Source§

implTermination for!

Source§

fnreport(self) ->ExitCode

Is called to get the representation of the value as status code.This status code is returned to the operating system.
Source§

implCopy for!

Source§

implEq for!

Auto Trait Implementations§

§

implFreeze for!

§

implRefUnwindSafe for!

§

implSend for!

§

implSync for!

§

implUnpin for!

§

implUnwindSafe for!

Blanket Implementations§

Source§

impl<T>Any for T
where T: 'static + ?Sized,

Source§

fntype_id(&self) ->TypeId

Gets theTypeId ofself.Read more
Source§

impl<T>Borrow<T> for T
where T: ?Sized,

Source§

fnborrow(&self) ->&T

Immutably borrows from an owned value.Read more
Source§

impl<T>BorrowMut<T> for T
where T: ?Sized,

Source§

fnborrow_mut(&mut self) ->&mut T

Mutably borrows from an owned value.Read more
Source§

impl<T>CloneToUninit for T
where T:Clone,

Source§

unsafe fnclone_to_uninit(&self, dest:*mutu8)

🔬This is a nightly-only experimental API. (clone_to_uninit #126799)
Performs copy-assignment fromself todest.Read more
Source§

impl<T>From<!> for T

Source§

fnfrom(t:!) -> T

Converts to this type from the input type.
Source§

impl<T>From<T> for T

Source§

fnfrom(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U>Into<U> for T
where U:From<T>,

Source§

fninto(self) -> U

CallsU::from(self).

That is, this conversion is whatever the implementation ofFrom<T> for U chooses to do.

Source§

impl<T>ToOwned for T
where T:Clone,

Source§

typeOwned = T

The resulting type after obtaining ownership.
Source§

fnto_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning.Read more
Source§

fnclone_into(&self, target:&mut T)

Uses borrowed data to replace owned data, usually by cloning.Read more
Source§

impl<T>ToString for T
where T:Display + ?Sized,

Source§

fnto_string(&self) ->String

Converts the given value to aString.Read more
Source§

impl<T, U>TryFrom<U> for T
where U:Into<T>,

Source§

typeError =Infallible

The type returned in the event of a conversion error.
Source§

fntry_from(value: U) ->Result<T, <T asTryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U>TryInto<U> for T
where U:TryFrom<T>,

Source§

typeError = <U asTryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fntry_into(self) ->Result<U, <U asTryFrom<T>>::Error>

Performs the conversion.

[8]ページ先頭

©2009-2026 Movatter.jp