Repository navigation
Description
With the never type stabilization on the horizon, I think we need to evaluate the plan to make Infallible = !.
Motivation
If we stabilize the never type (which we hopefully will soon!) while keeping Infallible unchanged, the standard library will have two different types for marking unreachable code / impossible enum variants / etc. This is especially annoying as one of them will be used more (Infallible is currently used throughout the standard library) while the other one is nicer to use (the never type is special in some regards, for example being able to coerce to any type).
Solution
We can make Infallible a type alias to !:
type Infallible = !;This intention is even documented in Infallible docs.
Breakage considerations
Unfortunately, making Infallible incurs a few small breakages:
- Calling a method on a result from a coercion of never to any currently results in an error (see Inconsistent method lookup on never type #143349)
- This is an issue because
anyhow::anyhow!(e)passesethrough a coercion site (match e { error => ... }) and then calls a method on it ((&error).anyhow_kind().new(error)) - This affects 20 crates, which all do something like
result_with_infallible_error.map_err(|e| anyhow::anyhow!(e)) - Crates can fix this by doing
.map_err(|e| match e {} as anyhow::Error)which is hard to come up with- After making
Infallible = !this can be simplified to.map_err(|e| e as anyhow::Error)or.map_err(|e| e)in case the type can be inferred
- After making
- This is an issue because
- It is possible to use hacks to avoid stability checking for the never type, thus being able to use it on stable. There are a few crates which do this and implement the same trait for both never and
Infallible(or also crates which enable the nightly feature).- As this is a case of intentionally avoiding stability checks, this falls outside of our stability guarantees
- crater run (report)
- This affects 9 crates directly, one of them (
allocative) has ~38 reverse dependencies (inallocativethis is gated on nightly, so this potentially only affects nightly users).
- standard library contains a reservation impl, which forbids certain
From<!>impls. After makingInfallible = !, this reservation impl can conflict with existing implementations forInfallible- This breaks 14 crates total (including reverse-dependencies of broken crates)- The reservation impl exists to allow
impl<T> From<!> for Tblanket impl, in case specialization becomes good enough to allow it - I'm not convinced the reservation impl is useful; note that it still allows
From<!> for Local, so even with it, adding the blanket impl is non-trivial. Additionally I'm not sure specialization will ever (or anytime soon) be good enough to allow such a blanket impl
- The reservation impl exists to allow
- There is some weirdness with how coercions work, which I don't yet understand
- Specifically it happens with code like this (this doesn't compile with
e: !, but does withe: Infallible):I'm investigating what might be causing thislet source = Box::new(e); let _: Box<dyn Send> = source;
- The only crate that is failing with this is
sqlite-tiny-0.7.8 - One possible fix (for the crate) is to specify the type in the first
let(???) - I think this should have been fixed by Do not use non-wf input expectations from fudge when checking function calls #150316, but apparently it wasn't...
- Specifically it happens with code like this (this doesn't compile with
Questions to the library team
- Do we still want to make
Infallible = !? - What to do with the breakage?
- Which (if any) of the issues feels serious enough to warrant trying to fix it in the language/compiler?
- for example, should we keep the reservation impl?
- Which (if any) of the issues should we try to fix in the broken crates (or notify authors)?
- Which (if any) of the issues feels serious enough to warrant trying to fix it in the language/compiler?
My personal opinion
My personal opinion is that most of these breaking changes are relatively minor.
- The issue with
anyhowis the most annoying, both in the size of breakage, and in trying to fix it in the language. - Implementations for
!conflicting with implementations forInfalliblefall outside of our stability guarantees - Reservation impl could be removed, as I don't see it being very useful
- 4-th issue needs additional investigation, but could be fixed asynchronously (it only affects a single crate...)
Links and related work
- stabilize never type #155499 (the PR description has more links)
- crater run for
Infallible = !breaks (ignoring reservation impl): [experiment][2] meow mrrrumph #155501 (comment) - crater run for
Infallible = !breaks (specifically the reservation impl ones): [experiment][1] mew #155500 (comment)
Activity
the8472 commentedon Apr 28, 2026
As discussed in the libs-api meeting:
Making
Infalliable = !has always been the plan, so it primarily depends on whether this is still feasible without significant breakage.@WaffleLapkin or anyone who has time: We'd like some additional information on the blast radius (number of crates, download counts, dependents, are only tests affected? ...).
The preliminary impression we got it's only few crates without dependents or nightly-only ones that are affected, if that holds then those present where in favor of going forward with this change.
We also discussed whether this should be FCP'd as part of the stabilization PR or be done here ahead-of-time. Waffle requested that this should be done ahead of time since it's the stabilization big task.
We'll discuss this again next week if we have new information on impact.
The possibility of making any of the existing breakages a FCW was also mentioned, but I'm not sure if there was consensus that it's actually needed or whether we ping the affected crates individually.
WaffleLapkin commentedon May 1, 2026
I've talked with @lcnr yesterday and we think that:
impl<T> From<!> for Twith hacks in type check (making fixing the code as easy as removing the offending impl) or we can remove the reservation impl (if we can't introduce the impl, there is no reason to reserve it)the8472 commentedon May 5, 2026
We discussed this during today's libs-api meeting. We went over the regressions and the blast radius seems acceptable. We'll give a headsup to active, affected crates but otherwise it doesn't seem blocking.
@rfcbot fcp merge libs-api
rust-rfcbot commentedon May 5, 2026
Team member @the8472 has proposed to merge this. The next step is review by the rest of the tagged team members:
No concerns currently listed.
Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!
See this document for info about what commands tagged team members can give me.
rust-rfcbot commentedon May 6, 2026
🔔 This is now entering its final comment period, as per the review above. 🔔
13 remaining items
Rollup merge of rust-lang#160705 - WaffleLapkin:unreserve_Fromᐸǃᐳ, r=…
Rollup merge of rust-lang#160705 - WaffleLapkin:unreserve_Fromᐸǃᐳ, r=…
Unrolled build for #160705 in rollup 161672
Rollup merge of rust-lang#155499 - WaffleLapkin:stabilize-never-type,…
Rollup merge of rust-lang#155499 - WaffleLapkin:stabilize-never-type,…
Rollup merge of rust-lang#155499 - WaffleLapkin:stabilize-never-type,…
Auto merge of #155499 - WaffleLapkin:stabilize-never-type, r=Jonathan…
Rollup merge of rust-lang#155499 - WaffleLapkin:stabilize-never-type,…
Auto merge of #155499 - WaffleLapkin:stabilize-never-type, r=Jonathan…
Auto merge of #155499 - WaffleLapkin:stabilize-never-type, r=Jonathan…
tbu- commentedon Aug 27, 2026
type Infallible = !now, so this can be closed.fmease commentedon Aug 27, 2026
Fixed in cfc82eb.
Auto merge of #155499 - WaffleLapkin:stabilize-never-type, r=Jonathan…
Rollup merge of #160705 - WaffleLapkin:unreserve_Fromᐸǃᐳ, r=JonathanB…