Remix.run Logo
▲ ustad a day ago

“Never type” - Feel like I’m stupid for not having a clue what that means.

▲Xirdus a day ago | parent | next [-]

Mathematically, types are sets of possible values.

Any type (like in TypeScript; Rust doesn't have one) is a set of every possible value; a supertype of all types. Every expression regardless of type can be assigned to a variable of type any.

The opposite is the never type, which is an empty set; no value is of type never. Per set theory, an empty set is a subset of every set, which makes the never type a subtype of all types. An expression of type never can be assigned to every variable regardless of type.

If never type has no values, then how can an expression have never type? Easy: it must never evaluate. Infinite loops, unconditional panics/exceptions, process exit/abort, etc. Also, generics - you can have Vec<!> that's always empty, Result<T,!> that can never be an error, etc.

▲rcxdude a day ago | parent | next [-]

Rust does have https://doc.rust-lang.org/std/any/trait.Any.html but it's not quite the same thing (for one thing, it's not actually all types).

▲ a day ago | parent [-]
[deleted]
▲afdbcreid a day ago | parent | prev | next [-]

Also called top and bottom types, for this reason.

▲steveklabnik a day ago | parent [-]

Any is not a top type and ! is not a bottom type, actually. They are sort of similar from a lay perspective if you squint, though.

▲afdbcreid a day ago | parent [-]

Why not? I mean if you refer to Rust specifically, yes, because there is no subtyping except for lifetimes, only coercion (and `Any` also cannot contain any type). But in general, why not?

▲steveklabnik a day ago | parent [-]

I am speaking about Rust specifically, yes.

▲boston_clone a day ago | parent | prev [-]

Comprehensive yet succinct, and appreciate you tying it to math - that helped solidify the idea.

▲anamexis a day ago | parent | prev | next [-]

The explanation in OP seems pretty solid.

https://blog.rust-lang.org/2026/11/12/Rust-1.100.0/#never-ty...

▲pkulak a day ago | parent | prev | next [-]

A few other langs have it too. It's just something to return when no return is actually possible. And then it can propagate, so it makes some nice things possible that weren't before.

▲igravious a day ago | parent [-]

Without looking up the Rust implementation I would hazard a guess that it is loose language to say "something to return when no return is actually possible" because if it is anything like the Bottom Type then there is no something that is being returned which is what this function signature indicates. Generally used for exception handling or intentional infinite loops (in both cases the function does not return from whence it came) … please correct me if I'm wrong here …

▲kibwen a day ago | parent [-]

Basic use cases like that have always been possible in Rust, either via defining your own enum with zero variants (`enum Foo {}`), or by using a function return type of `!` which was hardcoded to work for certain things, e.g. infinite loops. What this release does is generalizes it so that `!` can participate in types in general, and the coolest part is that pattern matching is aware of this, so for example if you have a `Result<u8, !>` where the error variant is impossible, a `match` over this would allow you to omit the impossible error arm, and furthermore because this enum now effectively only has a single variant, it would allow you to use the pleasant irrefutable destructuring assignment syntax `let Ok(foo) = blah();`.

▲afdbcreid a day ago | parent [-]

It has existed as a real type for a very long time (I believe in the beginning it really wasn't a real type but that's a long time ago), you just weren't allowed to name it. There was also an (unsupported) hack that allowed you to use it on stable.

▲saghm a day ago | parent | prev | next [-]

It's the type of what you get back from a `panic!` (a value you never actually get back).

▲yccs27 a day ago | parent | prev | next [-]

If you have a variable x: ! in scope, your code can never be reached.

▲LoganDark a day ago | parent | prev | next [-]

It's the type called "!", or the return value of diverging control flow, such as infinite loops, returns or function calls that panic or abort. It's an uninhabited type, meaning no values of it can actually exist, and that any code that would encounter such a value is unreachable.

▲NooneAtAll5 a day ago | parent | prev [-]

noreturn, basically

▲sixthDot 17 hours ago | parent [-]

yeah aka the bottom type , but "never return" is inisde the type system (a bit like D handles that) while "noreturn" is an attribute. That's basically the two known possible ways of expressing that a call will never return.