Skip to content

Make Infallible = ! #155924

@WaffleLapkin

Description

@WaffleLapkin

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:

  1. 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) 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
  2. 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 (in allocative this is gated on nightly, so this potentially only affects nightly users).
  3. 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)
    • 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
  4. There is some weirdness with how coercions work, which I don't yet understand

Questions to the library team

  1. Do we still want to make Infallible = !?
  2. 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)?

My personal opinion

My personal opinion is that most of these breaking changes are relatively minor.

  • The issue with anyhow is the most annoying, both in the size of breakage, and in trying to fix it in the language.
  • Implementations for ! conflicting with implementations for Infallible fall 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-discussionCategory: Discussion or questions that doesn't represent real issues.F-never_type`#![feature(never_type)]`I-libs-api-nominatedNominated for discussion during a libs-api team meeting.T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions