Skip to content

Remove From<!> for T *reservation* impl - #160705

Open
WaffleLapkin wants to merge 2 commits into
rust-lang:mainfrom
WaffleLapkin:unreserve_Fromᐸǃᐳ

Hidden character warning

The head ref may contain hidden characters: "unreserve_From\u1438\u01c3\u1433"
Open

Remove From<!> for T *reservation* impl#160705
WaffleLapkin wants to merge 2 commits into
rust-lang:mainfrom
WaffleLapkin:unreserve_Fromᐸǃᐳ

Conversation

@WaffleLapkin

Copy link
Copy Markdown
Member

This PR removes the <T> From<!> for T reservation implementation added in #62661 and tracked in #64715 and #64631.

The reservation impl in question was added in order to reserve some space for adding the following impl:

impl<T> From<!> for T {
    fn from(never: !) -> T { never }
}

It is meant to prevent users from writing some impls that would overlap if the From<!> for T impl is to be added.

This requires T-types FCP. Below is my proposal and necessary context:

The reservation impl is not sufficient

The reservation impl prevents one from assuming that From<!> for T is not implemented making the following not compile:

struct LocalType;
trait SomeTrait { }
impl<T: From<!>> SomeTrait for T { }
impl SomeTrait for LocalType { }

However, it does not prevent all implementation that would overlap given From<!> for T. Namely, From<!> for T would overlap with the following impls, all of which are currently permitted (and exist):

// T for T identity impl in `core`
impl<T> From<T> for T { ... }

// Various T->wrapper of T impls present in both the standard library,
// and in external crates
impl<T> From<T> for W<T> { ... }

// !->Local is also allowed
impl From<!> for Local {}

Also note that the reservation impl only exists for From<!>, but not for From<Infallible>, so even the impls that the reservation impl is meant to forbid, are currently allowed through Infallible anyway (we are planning to make Infallible a type alias to ! at the same time as stabilizing !).

Motivation for From<!> for T impl

It is surprisingly hard to find the original motivation for From<!> for T impl or the reservation impl, other than "people vaguely think that all types should implement From<!>, since there is never-to-any coercion".

One use-case seems to be "calling infallible function in a fallible one, and unwrapping Result<_, !> with ?". However, nowdays it is trivial to unwrap the result safely without ?:

let Ok(owo) = infallible_function();  

Another use-case that I've seen mentioned is "fallible function with a set error, taking an infallible function":

fn try_from<T>(t: T) -> Result<Meow, MyError>
where
    Meow: TryFrom<T>,
    <Meow as TryFrom<T>>::Error: Into<MyError>
{ ... }

With such definition, you can't pass Meow into try_from, because MyError: From<Infallible> doesn't hold.

This is more unfortunate, but it's not clear how widespread this problem is and how bad the workarounds would be. If a function expects impl FnOnce(...) -> Result<...>, it should be trivial to coerce the ! error to an appropriate type. With other trait bounds (like in the example above) it could be solved by adding a custom impl for your specific error type (annoying, but workable). Certaintly this doesn't feel like a big roadblock to me.

(let me know if you know more prior art on this)

There is no clear path for adding From<!> for T impl

Adding From<!> for T seems... hard... and hard to argue for.

It would require ignoring overlap with a bunch of impls (as described above) and would also require low priority impls (to avoid inference failures in cases where previously the only applicable impl was the identity one, so adding From<!> makes "one impl rule" not apply).

The tracking issue says:

The precise mechanism to permit us to add the From<!> for T impl is not yet clear. The current "plan of record" is to extend the "marker trait mechanism" to accommodate the idea of impls whose entire body consists of unreachable methods and to permit overlap.

Considering "traits with all methods having arguments of uninhabited types" as marker traits is technically possible (I think?), but feels like a bit of a stretch. Making overlap check consider if all trait functions take arguments which are uninhabited (known to be uninhabited in the current context) seems like a big complication, especially considering how From<T> would not be a marker trait in the general case — only From<!>/From<OtherUninhabitedTypes> would be (also that requires attaching the overlap check to some context from which we can check if a type is publically uninhabited, which can also lead to situations where impl A overlaps with impl B, but impl B doesn't overlap with impl A1). Allowing overlap with arbitrary user impls also is likely to cause unforcene issues in my opinion.

The reservation impl causes problems for the never type stabilization

Because the reservation impl reserves space for From<!> for T, but not for From<Infallible> for T, making Infallible an alias for ! makes some code fail to compile. See #155924:

  1. standard library contains a reservation impl, which forbids certain From<!> impls. After making Infallible = !, this reservation impl can conflict with existing implementations for Infallible - This breaks 14 crates total (including reverse-dependencies of broken crates)

Given that both keeping the reservation impl (while making Infallible = !) and making the reservation a proper impl break code, we should decide which path we want to pursue before stabilizing the never type (and making Infallible = !).

Proposal

After trying to add From<!> for T as a proper impl, I'm not convinced that it's worth the complexity and messiness of allowing such widespread overlap (with user defined impls too!). As such, I propose to remove the reservation impl, to prevent unnecessary breakage from its combination with making Infallible = !, as described above.

Alternatives

  • Add proper impl<T> From<!> for T, accepting the breakage, overlap, and the complexity.
    • I'm not sure how feasible this is, after trying to do this approach, it doesn't feel right
  • Keep the reservation impl / add the reservation impl From<Infallible> for T formally accepting the breakage of that, with the hopes that we can still add impl<T> From<!> for T in the future
    • This is the most breaking of the option, as it breaks code that depends on From<Infallible> for T not existing, and expects future breakage when adding impl<T> From<!> for T
    • It is unlikely that adding impl<T> From<!> for T in the future will be much easier than right now

Closes #64715
r? types

I'll remove the rustc_reservation_impl attribute in a separate PR (cc #64631).

Footnotes

  1. i.e. in the context of impl A a certain type is not known to be uninhabited, and thus the overlap between impls should not be allowed. at the same time in the context of impl B same type might be known to be uninhabited, allowing the overlap.

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Aug 7, 2026
@WaffleLapkin WaffleLapkin added needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. T-types Relevant to the types team, which will review and decide on the PR/issue. and removed T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Aug 7, 2026
@rust-log-analyzer

This comment has been minimized.

@WaffleLapkin
WaffleLapkin force-pushed the unreserve_Fromᐸǃᐳ branch from b367736 to 7c94b9a Compare August 7, 2026 14:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-types Relevant to the types team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tracking issue for reserved impl impl<T> From<!> for T

4 participants