Skip to content
Tech AI Wire
CodingExplainer

Rust's never type, explained

Rust's never type, written !, is the type of code that never produces a value. It is stable in Rust 1.100 after ten years, and it changes type fallback.

By Tech AI Wire Team

5 min read

XLinkedIn
Five dark gray squares in a row that lighten from left to right, ending in a single solid red square.

By the numbers

RFC 1216 proposed making ! a real type
2015
crates crater compiled against the stabilization
9,024
of them flagged as regressions
3,277

Rust's never type is the type of an expression that never produces a value. It is written as a single exclamation mark, !. A function that always panics, loops forever, or returns early has this type, because it never hands a value back to the code that follows it. After ten years as an unstable feature, the never type is now stable. The pull request that did it merged on August 24, 2026, and it carries one breaking change with it.

This matters beyond compiler trivia. The never type decides what happens at the dead ends in your code, and the new fallback rule can change what a generic function infers. The Rust Reference defines ! as a type with no values, representing computations that never complete.

How it works

A type is a set of possible values. The type bool has two of them. The never type has none. RFC 1216, the 2015 proposal that started all this, calls such a type an empty type, "a type for which there is nothing of that type." Nothing of type ! can exist while a program runs, so a value of that type has no machine-level representation at all.

That emptiness gives ! its one special power. According to the Rust standard library documentation, an expression of type ! can be coerced into any other type. The compiler can promise that safely, because the coercion never has to run. If the code after a panic!() expects a String, the panic expression fits, since no String will ever be needed there. That is why return, break, continue, and panic!() can all sit in a position that expects some other type.

The standard library documents that ! implements Clone, Copy, Debug, Display, Eq, Hash, Ord, PartialEq, PartialOrd, and Error. The same documentation names one trait it should never implement: Default. Default has to produce a value, and ! cannot.

Before this stabilization, stable Rust let you write ! in only one place, as a function's return type, per the Reference. Developers who needed an empty type elsewhere wrote their own, usually enum Never {}, a pattern RFC 1216 describes. The standard library's own version is std::convert::Infallible, an enum with no variants that has been in the library since Rust 1.34.0. Its documentation describes it as the error type for errors that can never happen. A Result<T, Infallible> tells the reader the result is always Ok.

What changed and when

Three things landed together in pull request 155499, according to the PR. First, ! is stable as a full type, which is what RFC 1216 asked for in 2015. Second, Infallible becomes a type alias for !, so the two names now mean the same type. Third, and this is the breaking part, type fallback now resolves to ! in every Rust edition.

Fallback is the rule for one corner case. Sometimes the compiler reaches a spot where an expression diverges and nothing around it pins down a type. Historically it picked the unit type (), the empty tuple, in that spot. In the 2024 edition and later, the standard library documentation already describes the fallback as ! instead. The stabilization PR makes that the rule everywhere, including older editions.

The Rust project measured the change before merging it. The PR reports a crater run over 9,024 crates. Crater compiles a large sample of published crates against a proposed compiler and reports what breaks. It flagged 3,277 regressions and no fixes. The PR is milestoned for Rust 1.100.0, as Tech AI Wire's report on the stabilization noted when it merged.

One regression report is instructive. A contributor flagged that cargo-semver-checks, a tool that checks crates for breaking API changes, reported the Infallible change as breaking. The PR discussion calls that a false positive. As contributor JonathanBrouwer put it, "The type is still there, it just turned from a pub enum into a pub type."

MilestoneWhenWhat happened
RFC 1216July 19, 2015Proposed promoting ! to a full type
Tracking issue 35121July 29, 2016Opened to track the RFC; PR 35162 was the first implementation
PR 65355Rust 1.41.0First stabilization, reverted in PR 67224 after regressions
Rust 2024 edition2024 editionFallback changed to ! inside the new edition first
PR 155499August 24, 2026! stable, fallback universal, Infallible aliased

Why it took ten years

The tracking issue tells the story of the delay. Issue 35121 opened on July 29, 2016. A first stabilization shipped in Rust 1.41.0 and was then pulled back out, because real crates broke. The issue records the trigger: an Error conversion from Infallible stopped compiling, filed as issue 66757. The author of the final PR writes on their blog that there were five failed attempts in all. This last push took them more than two years.

The way out was staging. The tracking issue lays out a three-phase plan. Change the fallback to ! inside the 2024 edition only. Stabilize that edition. Then, once the ecosystem had absorbed the new rule, make the breaking changes universal and set Infallible equal to !. The August 2026 PR is that final phase. Rust's other big compiler change this year, the next-generation trait solver, is going through nightly first in the same cautious way, with stabilization planned for later.

What this means for developers

Check generic code on nightly before Rust 1.100.0 reaches stable. The fallback change matters where a type parameter is pinned down only by an expression that panics or returns early. In those spots the compiler used to choose () for you and now chooses !. Most code will not notice. Code that relied on the old choice can fail to compile, or pick a different trait implementation. The 3,277 crater hits show that is not hypothetical.

Grep for Infallible. If your crate implements a trait for both Infallible and !, those two implementations now collide, because they name one type. The Infallible documentation also notes that function pointer types like fn() -> ! and fn() -> Infallible could carry different trait implementations. Those now match too. A library that exposes Infallible in its public API does not break its users, whatever a semver tool says. The type is still there under both names.

Use ! on purpose from now on. A function that can only succeed can return Result<T, !>, which RFC 1216 lists as a motivating use case, and callers can match on the Ok arm alone. A handler that never returns can be passed to generic code expecting a Fn() -> T, another RFC use case, without a wrapper type. Drop the homemade enum Never {} once your minimum supported Rust version allows it.

Ten years is a long time for a one-character type. The reverted first attempt, the edition-first rollout, and the crater number explain most of it. They are also why this is a change you can prepare for on nightly today, before it reaches stable.

Sources

  1. Never type - The Rust Reference - The Rust Reference
  2. Primitive type ! - Rust standard library documentation - Rust standard library docs
  3. RFC 1216: Promote ! to a type - Rust RFCs
  4. stabilize never type (PR #155499) - GitHub - rust-lang/rust
  5. Tracking issue for RFC 1216 (promoting ! to a type) - GitHub - rust-lang/rust
  6. Enum std::convert::Infallible - Rust standard library documentation - Rust standard library docs

Related articles

The daily brief

Three to five stories a day, and what each one means for the people who build software. Free, no spam.