Katherine oversees editorial operations across all six brands. Before joining The Meridan Group, she spent 14 years at the Minneapolis Star Tribune, where she led the metro desk through its digital transformation. She holds a Master's in Journalism from Northwestern's Medill School.
Nov. 12, 2026 · The Rust Release Team
The Rust team is happy to announce a new version of Rust, 1.100.0. Rust is a programming language empowering everyone to build reliable and efficient software.
If you have a previous version of Rust installed via
rustup
, you can get 1.100.0 with:
$
rustup update stable
If you don't have it already, you can get
rustup
from the appropriate page on our website, and check out the
detailed release notes for 1.100.0
.
If you'd like to help us out by testing future releases, you might consider updating locally to use the beta channel (
rustup default beta
) or the nightly channel (
rustup default nightly
). Please
report
any bugs you might come across!
What's in 1.100.0 stable
Never type
Allocator
API
DropGuard
API
Conjuring zero-sized types
Reporting unused dependencies in Cargo
Reducing Cargo cache collisions
Cargo min-publish-age
Stabilized APIs
Never type
After 10 years and 5 failed stabilization attempts,
the
never type
is finally stable
! This also completes the
project goal
for this work.
The never type, spelled
!
in code, is the canonical uninhabited type. It represents the type of diverging computations – computations which never resolve to any value – where any code that follows is unreachable. Expressions that terminate control flow, such as
return
,
break
, and
std::process::exit
, also have the type
!
.
Since having a value of the never type is impossible, Rust permits a never-to-any coercion, allowing to turn
!
into any other type (this is what distinguishes it from any other uninhabited types). This can be used, for example, to not return a value from one of the branches of a
match
or an
if
:
fn
mrrrow
(
option
:
Option
<
u32
>
)
{
let
value
=
match
option
{
//
`x` has type `u32`
Some
(
x
)
=>
x
,
//
`return` has type `!`, which is then coerced to `u32`,
//
allowing the `match` to pass type checking.
None
=>
return
,
}
;
//
...
}
While the never type could already be used and observed this way, and even named in the return type of functions (
-> !
), this release allows naming the never type anywhere:
fn
infallible_unwrap
<
T
>
(
res
:
Result
<
T
,
!
>
)
->
T
{
//
^^ writing `Result<_, !>` was not allowed before
let
Ok
(
v
)
=
res
;
v
}
Additionally this release changes
Infallible
to be an alias to the never type. That makes all old APIs that used
Infallible
be compatible with using
!
. This was the plan ever since the introduction of
Infallible
and is one of the reasons why the never type stabilization was so hard (waffle gave a
talk
about some of the troubles of the stabilization).
Unfortunately, to allow changing
Infallible
, we had to introduce a breaking change. This release changes the "never type fallback" from
()
to
!
in editions
before
2024 (i.e. 2015, 2018, and 2021), similarly to what has
already been done in edition 2024
. This should largely be unnoticeable, but can affect code in some rare cases (for example when ignoring a result of a function returning a generic parameter). Note that this change might also make the compiler detect more code as unreachable.
We tried to minimize the impact of this breaking change as much as possible, by providing future compatibility warnings far in advance and releasing fixes to public crates that have been broken by this. If a dependency is failing due to issues with the never type, consider updating it, as a fix might have already been released for it.
Allocator
API
This release brings about the stabilization of the core parts of
allocator_api
, enabling library authors to define custom allocators that can be used together with certain standard library types - currently
Vec
and
Box
. These are enabled through the newly-stabilized
Allocator
trait.
This is the foundation of the
Allocators 1.0 project goal
. A lot remains to be done still, including expanding the API surface usable with custom allocators and stabilizing their use on more collections and pointer types; with the core trait and design out of the way though, expect to see more being stabilized soon!
DropGuard
: run a closure on every exit path
The
Drop
trait in Rust makes it possible to run code when a variable goes out of scope, regardless of whether we
return
,
?
, or panic.
Drop
being a part of types means that
in Rust you never have to close a socket
.
Implementing
Drop
can however feel a little inconvenient when all you want is to run some code unconditionally when a function exits. This is why we’re introducing
core::mem::DropGuard
: a new helper type that runs a closure when dropped.
DropGuard
takes two arguments: a variable and a closure. It implements
Deref
and
DerefMut
so you can keep working with the variable as normal. But when dropped it runs the closure and consumes the variable.
DropGuard
also implements a
dismiss
method which returns the variable from the guard without running the destructor. This makes it possible to quickly implement all-or-nothing transaction-like APIs with a rollback. Here is an example implementing a parser which uses a guard to roll back mutations in case of failure:
use
std
::
mem
::
DropGuard
;
use
std
::
num
::
ParseIntError
;
///
Attempt to parse all `strings` and push them into `nums`.
///
If parsing any of them fails, `nums` remains unchanged.
fn
parse_all
(
nums
:
&
mut
Vec
<
u32
>
,
strings
:
&
[
&
str
]
)
->
Result
<
(
)
,
ParseIntError
>
{
let
len
=
nums
.
len
(
)
;
let
mut
nums
=
DropGuard
::
new
(
nums
,
move
|
nums
|
{
nums
.
truncate
(
len
)
;
//
← 1. Reset the vec on failure
}
)
;
for
s
in
strings
{
nums
.
push
(
s
.
parse
(
)
?
)
;
//
← 2. If `?` returns an error, roll back
}
DropGuard
::
dismiss
(
nums
)
;
//
← 3. Parsing successful, dismiss the guard
Ok
(
(
)
)
}
Conjuring zero-sized types
As Rust's
unsafe code guidelines
are still being decided, it became clear that it would be very useful to decide what exactly it means to create zero-sized types in an unsafe way, and what we should recommend for people to do this.
This question is answered in Rust 1.100 with a single function:
std::mem::conjure_zst
.
Instead of transmuting
()
,
MaybeUninit::uninit().assume_init()
, or various other incantations, this is the dedicated way to create a value of a zero-sized type when you know that doing so is safe to do. If an inhabited type has no size, we know exactly what value it must be: nothing.
Of course, APIs often rely on the inability to construct such types for safety, and that's why this function is unsafe. For example, PyO3's
Python<'py>
is a zero-sized marker token that represents holding the Python GIL (global interpreter lock). Many of Python's APIs require holding this lock to be safe, but conjuring a token from thin air would allow safe PyO3 calls to violate that precondition.
Reporting unused dependencies in Cargo
Building dependencies that are no longer used or are only needed for specific platforms can slow down builds.
Rustc has the
unused_crate_dependencies
lint for this but it has false positives when used with Cargo because dependencies may be shared between multiple build targets, e.g.
dependencies.tracing-subscriber
being available for every
bin
in a package when only some may use it.
Cargo now reports unused dependencies to users, e.g.
warning: unused dependency `tracing-subscriber`
--> Cargo.toml:23:1
|
23 | tracing-subscriber.workspace = true
| ^^^^^^^^^^^^^^^^^^
|
= note: `cargo::unused_dependencies` is set to `warn` by default
help: consider removing the dependency on `tracing-subscriber`
A limitation of this warning is that it will only appear when building every build target that may use an entry in a dependencies table.
For example, running
cargo check --bin foo
won't show warni