⏱️ Reading time: 6 min

Rust’s never type, written as the ! symbol, needed ten years and five failed stabilization attempts before reaching stable. Rust 1.100.0, released on November 12, 2026, finally gets there, closing out a project goal the team had carried for years (Rust Blog).

📑 En este artículo
  1. What Rust’s never type is, and why it exists
  2. The real problem: ten years of trying not to break anything
  3. What this means if you maintain a Rust crate
  4. The never type isn’t unique to Rust
  5. What else ships: the Allocator API and Cargo limits
  6. Limitations and when this can bite you
  7. References

What Rust’s never type is, and why it exists

The never type is Rust’s canonical uninhabited type: no value of that type can exist, because it represents a computation that never resolves to a value (std documentation, Rust Blog). Expressions like return, break, or std::process::exit have this type, as does a loop with no exit. Because a never value is impossible to hold, the compiler allows it to coerce into any other type: a match arm that does return can coexist with another arm that returns a u32, without breaking type checking.

Before this release, never could already be used and observed this way, even as an explicit return type, but it couldn’t be named in every generic position. Rust 1.100.0 lets you write it wherever needed, for example in Result<T, !> for a function that can never fail, something that didn’t compile before this version (Rust Blog).

The real problem: ten years of trying not to break anything

What delayed stabilization wasn’t the type itself, but a side effect: std::convert::Infallible, the type the standard library had used for years to mark an operation that cannot fail. Rust 1.100.0 turns Infallible into an alias for never, so that all existing code using Infallible becomes automatically compatible with the native never type (Rust Blog).

To pull this off without breaking a large part of the ecosystem, the team had to change the so-called never type fallback: in the 2015, 2018, and 2021 editions, an unused never-typed expression used to be inferred as (); now it’s inferred as never, matching what already happened in the 2024 edition (Rust Blog). The announcement itself acknowledges that this change can make the compiler flag more code as unreachable than it used to, and that one of the compiler engineers, known as waffle, gave an entire talk on the concrete difficulties of this stabilization.

Five stabilization attempts failed before this one, according to the official announcement. Foto de Burnell Yow en Unsplash

What this means if you maintain a Rust crate

If you maintain a library that exposes Result<T, Infallible>, common in parsers, TryFrom conversions, or builders, you don’t need to change anything: the alias is backward compatible. But if your CI compiles with #![deny(warnings)] on a 2015, 2018, or 2021 edition, run a build as soon as you update the toolchain. The fallback change can make the compiler flag branches as dead code that used to pass silently, because it now infers never where it used to infer () (Rust Blog).

The Rust team flagged this change with future-compatibility warnings well in advance, and patches already shipped for public crates that broke under the new behavior, according to the announcement. If a dependency fails right after updating to 1.100.0, check first whether a newer version of that dependency already exists before looking for the bug in your own code.

The never type isn’t unique to Rust

The idea of an uninhabited type that coerces into anything else didn’t start with Rust. Several languages with strong type systems have their own version, with different nuances in how it coerces and where it’s used:

LanguageEquivalent typeAutomatic coercionTypical use
Rustnever (!)Yes, to any typereturn, break, process::exit, Result<T, !>
TypeScriptneverNo implicit coercion; the compiler uses it for exhaustiveness checksFunctions that never return, discriminated unions
HaskellVoidYes, via the absurd functionError types the program declares impossible
KotlinNothingYes, a subtype of every typeFunctions that always throw, TODO()

In the Hacker News thread about the release, one comment ties this kind of guarantee to the broader value of Rust’s type system: user IshKebab argued that a strong type system “helps catch bugs at compile time” and enables the typestate pattern to “make invalid states unrepresentable” (comment on Hacker News). The never type is, in that sense, the most extreme version of the same idea: a state the type itself declares impossible to inhabit, instead of leaving it as a case the program has to check at runtime.

What else ships: the Allocator API and Cargo limits

The never type isn’t traveling alone in this release. Rust 1.100.0 also stabilizes the core of the Allocator API (Allocator trait in std, Rust Blog): for now only Vec and Box can use a custom memory allocator through that trait, with more collections and pointer types promised for future versions.

core::mem::DropGuard also arrives, a type that runs a closure on scope exit without hand-implementing Drop, with a dismiss method that lets you build all-or-nothing operations with rollback, for example in a parser that must leave a Vec untouched if it fails partway through. And for publishing to crates.io, Cargo adds min-publish-age, a minimum required age before a version can be published, meant to slow down supply-chain attacks that rely on freshly created packages, on top of reporting unused dependencies and reducing cache collisions (Rust Blog).

Limitations and when this can bite you

The stabilized Allocator API covers only the trait and two collections. If you need custom allocators in HashMap, BTreeMap, or Rc, they’re not supported yet, and you’ll have to wait for further stabilizations (Rust Blog).

The never type fallback change is, by design, nearly imperceptible, but the announcement itself warns it can affect code in rare cases, for example when the result of a generic function is ignored. If your build fails right after updating and the error mentions type inference or unreachable code, that change is the first suspect, not a new compiler bug.

References

Featured image: Foto de Jakub Żerdzicki en Unsplash

📬 Get new articles by email

We only email about big articles (1-2 a month).

How each article is made (sources, testing and editorial criteria): How we work.

Did it work for you? Got a different error? Say so below: questions get answered and help the next reader.

Leave a comment
Categories: Programming

El Solitario Editorial

Article prepared by the El Solitario editorial team from cited sources, under the editorial responsibility of Luis Navarro. More details in "How we work".

0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *

You can include code inside <code>…</code> or, for several lines, <pre><code>…</code></pre>.

This site uses Akismet to reduce spam. Learn how your comment data is processed.