You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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 !:
typeInfallible = !;
This intention is even documented in Infallible docs.
Breakage considerations
Unfortunately, making Infallible incurs a few small breakages:
This is an issue because anyhow::anyhow!(e) passes e through 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
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
This affects 9 crates directly, one of them (allocative) has ~38 reverse dependencies (in allocative this is gated on nightly, so this potentially only affects nightly users).
standard library contains a reservation impl, which forbids certainFrom<!> 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)
The reservation impl exists to allow impl<T> From<!> for T blanket 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
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 with e: Infallible):
let source = Box::new(e);let _:Box<dynSend> = source;
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
Infallibleunchanged, 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 (Infallibleis 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
Infalliblea type alias to!:This intention is even documented in
Infallibledocs.Breakage considerations
Unfortunately, making
Infallibleincurs a few small breakages:anyhow::anyhow!(e)passesethrough a coercion site (match e { error => ... }) and then calls a method on it ((&error).anyhow_kind().new(error))result_with_infallible_error.map_err(|e| anyhow::anyhow!(e)).map_err(|e| match e {} as anyhow::Error)which is hard to come up withInfallible = !this can be simplified to.map_err(|e| e as anyhow::Error)or.map_err(|e| e)in case the type can be inferredInfallible(or also crates which enable the nightly feature).allocative) has ~38 reverse dependencies (inallocativethis is gated on nightly, so this potentially only affects nightly users).From<!>impls. After makingInfallible = !, this reservation impl can conflict with existing implementations forInfallible- This breaks 14 crates total (including reverse-dependencies of broken crates)impl<T> From<!> for Tblanket impl, in case specialization becomes good enough to allow itFrom<!> 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 imple: !, but does withe: Infallible):sqlite-tiny-0.7.8let(???)Questions to the library team
Infallible = !?My personal opinion
My personal opinion is that most of these breaking changes are relatively minor.
anyhowis the most annoying, both in the size of breakage, and in trying to fix it in the language.!conflicting with implementations forInfalliblefall outside of our stability guaranteesLinks and related work
Infallible = !breaks (ignoring reservation impl): [experiment][2] meow mrrrumph #155501 (comment)Infallible = !breaks (specifically the reservation impl ones): [experiment][1] mew #155500 (comment)