upvote
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.

reply
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).
reply
deleted
reply
Also called top and bottom types, for this reason.
reply
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.
reply
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?
reply
I am speaking about Rust specifically, yes.
reply
Comprehensive yet succinct, and appreciate you tying it to math - that helped solidify the idea.
reply
reply
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.
reply
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 …
reply
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();`.
reply
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.
reply
If you have a variable x: ! in scope, your code can never be reached.
reply
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.
reply
noreturn, basically
reply