Ten years and five failed attempts later, the never type (!) is stable. Rust 1.100, released on November 12, 2026, ships it alongside the core of the allocator API, and Cargo gets two changes you'll feel day to day: it flags dependencies you don't use, and it can refuse to resolve crate versions younger than a window you choose.
The never type, finally usable anywhere
! is the type of things that never produce a value: return, break, std::process::exit. Until now you could only write it as a return type (-> !). From 1.100 you can name it anywhere, which makes types that can't fail readable:
fn infallible_unwrap<T>(res: Result<T, !>) -> T {
let Ok(v) = res;
v
}Infallible also becomes an alias for !, so APIs built on it work with the never type out of the box.
That's where the release's one breaking change comes in: never-type fallback switches from () to ! in editions 2015, 2018 and 2021 too (2024 already had it). The Rust team expects it to go mostly unnoticed, but it can break code in rare cases, such as ignoring the result of a function that returns a generic parameter, and the compiler may flag more code as unreachable. If a dependency stops compiling over this, update it first: affected public crates have already been patched.
Custom allocators and DropGuard
The other big stabilization is the core of allocator_api: the Allocator trait, Global, System, and constructors such as Vec::new_in and Box::new_in. For now only Vec and Box take a custom allocator; the other collections come later. This is what arena and per-request allocator users have been waiting for without moving to nightly.
For application code, the most useful addition is core::mem::DropGuard: it wraps a value and runs a closure when it goes out of scope, on any path (return, ? or panic), unless you call dismiss. It's a natural fit for all-or-nothing operations:
use std::mem::DropGuard;
use std::num::ParseIntError;
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));
for s in strings {
nums.push(s.parse()?); // an error rolls the Vec back
}
DropGuard::dismiss(nums);
Ok(())
}Rounding it out: std::mem::conjure_zst, the official (and unsafe) way to create zero-sized types, plus small helpers like bool::toggle, Vec::from_fn, str::trim_prefix and str::trim_suffix.
Cargo: a cooldown for new versions
Malicious package versions tend to be caught within hours or days. With min-publish-age, Cargo can sit out that window before resolving them. Turn it on in .cargo/config.toml:
[registry]
global-min-publish-age = "3 days"cargo update then skips anything newer than the window and tells you what it held back. When you need an urgent fix, you can override it for a single update:
CARGO_RESOLVER_INCOMPATIBLE_PUBLISH_AGE=allow cargo update clap --precise 4.6.9Two limits matter. cargo install ignores the cooldown for both the crate and its dependencies, so pin versions there (cargo install [email protected]). And versions with no publish time in the index are never held back.
pnpm applies the same idea with minimumReleaseAge, but made a different call: it's on by default with a one-day wait (1,440 minutes) and covers every dependency, transitive ones included. In Cargo it's opt-in; if you want that protection, you have to ask for it.
Cargo: unused dependencies and a reorganized build-dir
Cargo now warns about declared dependencies that no target uses (cargo::unused_dependencies, warn by default). It only fires when you build every target that could use them, so cargo check --bin foo won't show it, and it never fires for dev-dependencies.
The riskiest change for CI is internal: the build-dir is now organized by build step, and the configuration hash moves from file names to the parent directory. That fixes extra or missed rebuilds when switching --features or sharing the directory across worktrees, but it can break scripts and tests that relied on the old paths. Workarounds and discussion live in cargo#17287.
Upgrading
With rustup:
rustup update stable
rustc --version # rustc 1.100.0Before it hits production
- Build and test on editions 2015–2021, watching for new inference errors or unreachable-code warnings; if a dependency breaks, update it before digging in.
- Audit CI scripts that read artifacts inside
target/by path: thebuild-dirlayout has changed. - Build every target (
cargo build --all-targets) and drop the dependencies Cargo flags as unused. - Pick a
global-min-publish-agewindow and decide how you'll bypass it when a security fix lands.
Sources
- Announcing Rust 1.100.0, The Rust Release Team, November 12, 2026.
- Settings: dependency resolution, minimumReleaseAge, pnpm docs.