A feature can spend years on Rust’s unstable channel while maintainers work through subtle interactions with type inference, traits, and existing code. Rust 1.100, announced on November 12, 2026, closes one of the language’s longest-running stabilization efforts while delivering practical improvements to memory management, cleanup, and dependency security.
Besides marking the programming language’s 100th stable version, the Rust 1.100.0 release stabilizes the never type in generic positions after a decade of development and five unsuccessful stabilization attempts. It also makes the core Allocator API available on stable Rust, introduces DropGuard, and gives Cargo users a dependency cooldown that can reduce exposure to newly published malicious crates.
What Is New in Rust 1.100?
The headline Rust 1.100 features address several different layers of development:
- The never type,
!: Developers can now use it in generic types such asResult<T, !>, not only as a function’s return type. - The Allocator API: Collections and owning pointers such as
VecandBoxcan use custom allocators on stable Rust. - Cargo dependency cooldowns: The
min-publish-agesetting prevents newly published package versions from being selected until they reach a configured age. - DropGuard: Programs gain a standard RAII-oriented mechanism for cleanup or rollback when a scope exits early or unwinds because of a panic.
- Cargo diagnostics and caching: Unused dependency warnings and better-organized build-cache data make manifests and repeated builds easier to manage.
Developers should read the official Rust 1.100.0 announcement before updating production toolchains, especially if their projects rely on never-type inference, custom build tooling, or Cargo’s internal cache layout.
Why Did the Never Type Take 10 Years to Stabilize?
The Rust never type represents a computation that cannot produce a value. It is written as !. A function that loops forever, exits the process, or always panics can return ! because normal execution never reaches its caller.
fn run_forever() -> ! {
loop {
perform_background_work();
}
}
fn stop(message: &str) -> ! {
panic!("{message}");
}
Rust has supported uses like these for years. Rust never type stabilization was difficult because using ! as a full type affects coercion, type inference, fallback behavior, trait resolution, and compatibility with existing generic code. Earlier attempts exposed unresolved edge cases, leading to five failed stabilization efforts over approximately a decade.
Rust 1.100 completes the work by allowing the never type wherever an ordinary type can appear, including generic arguments:
fn infallible_lookup(id: u64) -> Result<String, !> {
Ok(format!("record-{id}"))
}
fn print_record(id: u64) {
match infallible_lookup(id) {
Ok(record) => println!("{record}"),
Err(impossible) => match impossible {},
}
}
Result<T, !> precisely communicates that an operation returns T and cannot produce an error. The empty match is exhaustive because no value of type ! can exist. Generic APIs can therefore express infallibility without defining an artificial error type.
The standard library’s std::convert::Infallible becomes an alias for !. That unifies two previously separate ways to model impossible values, but it also deserves attention during upgrades. Code that defines overlapping trait implementations for Infallible and ! may no longer compile once the names refer to the same type. Libraries with advanced conversion or coherence patterns should test this change carefully.
How Does Rust’s New Allocator API Work?
Most Rust programs can continue using the global allocator without modification. Specialized systems, however, may need arena allocation, region-specific memory, allocation accounting, shared-memory placement, or a strategy tuned for predictable latency. The stabilized Rust Allocator API allows those choices to be attached to individual values rather than imposed on an entire process.
An allocator implements core::alloc::Allocator. Types that accept an allocator parameter can then request and release memory through that implementation. The following condensed example wraps the system allocator and counts allocation requests:
use std::alloc::{AllocError, Allocator, Layout, System};
use std::ptr::NonNull;
use std::sync::atomic::{AtomicUsize, Ordering};
static ALLOCATIONS: AtomicUsize = AtomicUsize::new(0);
#[derive(Clone, Copy)]
struct CountingAllocator;
unsafe impl Allocator for CountingAllocator {
fn allocate(
&self,
layout: Layout,
) -> Result<NonNull<[u8]>, AllocError> {
ALLOCATIONS.fetch_add(1, Ordering::Relaxed);
System.allocate(layout)
}
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
unsafe { System.deallocate(ptr, layout) }
}
}
fn main() {
let allocator = CountingAllocator;
let mut values = Vec::new_in(allocator);
values.extend([10, 20, 30]);
let answer = Box::new_in(42, allocator);
println!("{} {}", values.len(), answer);
}
This example delegates the actual Rust memory management to System, but it shows how Vec and Box can carry an allocator. A production allocator must honor the API’s alignment, allocation, deallocation, and pointer-validity contracts. Because violating those contracts can cause undefined behavior, custom allocator implementations require the same level of review as other unsafe infrastructure.
The practical benefit is choice. A server can allocate request-scoped objects from an arena, an embedded application can use a fixed memory region, and diagnostic builds can track selected allocations without replacing the global allocator.
Can Cargo Dependency Cooldowns Prevent Supply Chain Attacks?
Cargo’s new dependency cooldown is one of the most immediately useful Rust supply chain security additions. With Cargo min-publish-age, a team can require a package version to have been available for a minimum period before Cargo’s resolver selects it.
A project or organization can configure the resolver in Cargo configuration:
[resolver]
min-publish-age = "7 days"
With this setting, a version published less than seven days ago is excluded from normal dependency resolution. The delay creates time for maintainers, registries, security researchers, and downstream users to identify suspicious releases before an automated update introduces them into a build.
This can help with attacks involving a compromised maintainer account, malicious ownership transfer, or an unexpected release from a trusted package. It is especially relevant to automated dependency-update pipelines that would otherwise adopt a new compatible version soon after publication.
However, Cargo dependency cooldowns are an optional defense, not a complete security system. They do not prove that an older crate is trustworthy, inspect source code, validate maintainer intent, or replace lockfiles and review. The setting also does not apply to cargo install. Teams should combine it with committed Cargo.lock files where appropriate, controlled updates, reproducible CI, dependency auditing, and review of newly introduced packages.
What Does DropGuard Do?
Rust’s ownership model already runs destructors when values leave scope, including during unwinding from most panics. DropGuard packages that RAII principle into a convenient cleanup or rollback mechanism. A guard remains armed while work is in progress. If the function returns early or panics, dropping the guard performs its registered action. After a successful commit, the program disarms the guard.
The underlying behavior can be illustrated with this compact guard pattern:
struct Rollback<F: FnOnce()>(Option<F>);
impl<F: FnOnce()> Rollback<F> {
fn new(action: F) -> Self {
Self(Some(action))
}
fn disarm(mut self) {
self.0 = None;
}
}
impl<F: FnOnce()> Drop for Rollback<F> {
fn drop(&mut self) {
if let Some(action) = self.0.take() {
action();
}
}
}
fn update_files() -> Result<(), std::io::Error> {
create_temporary_files()?;
let guard = Rollback::new(|| remove_temporary_files());
publish_files()?;
guard.disarm();
Ok(())
}
The stabilized DropGuard facility provides this cleanup model without every project needing to hand-roll the pattern. Typical uses include deleting temporary files, rolling back partially completed operations, resetting state, releasing external resources, or restoring an invariant.
Cleanup during a panic depends on unwinding. A process configured to abort on panic does not unwind its stack, so no drop-based guard can promise panic cleanup in that mode. Guards also should not be treated as a substitute for durable database transactions when recovery must survive process termination or power loss.
How Does Rust 1.100 Affect Existing Projects?
Most applications should update without source changes, but maintainers should watch several areas:
- Never-type compatibility: Check inference-sensitive code and trait implementations involving both
!andInfallible. - Unused Cargo dependencies: New warnings can reveal stale normal, development, or build dependencies. Verify feature-gated and target-specific uses before removing anything.
- Build-cache organization: Cargo’s improved cache structure may cause a one-time rebuild or affect scripts that improperly inspect internal cache paths. Treat Cargo’s cache layout as an implementation detail.
- Minimum supported Rust version: Libraries adopting these APIs should raise and document their MSRV rather than accidentally breaking users on older compilers.
- Unsafe allocator code: Audit custom allocators with tools and tests appropriate for unsafe memory-management components.
Cargo unused dependency warnings are particularly helpful for long-lived workspaces. Removing genuinely unused crates reduces compilation work and narrows the project’s dependency surface. Warnings should still be reviewed in context because build scripts, generated code, optional features, and platform-specific modules may make a dependency appear unused in a particular build.
How to Install or Update to Rust 1.100.0
Developers using rustup can update the default stable toolchain with:
rustup update stable
rustc --version
cargo --version
To pin this release for a specific repository, run:
rustup override set 1.100.0
Run the complete test suite, Clippy, documentation tests, all-feature builds, and supported target builds after updating. Workspace maintainers should also test the oldest compiler promised by their MSRV policy. A detailed inventory of changes is available in the Rust 1.100.0 release documentation.
Frequently Asked Questions
Is the Rust never type now fully stable?
Yes. Rust 1.100 allows ! to appear as a type in generic positions, including Result<T, !>. Functions returning ! remain useful for diverging operations such as infinite loops, panics, and process termination.
Do existing projects need a custom allocator?
No. The default global allocator remains appropriate for most software. Rust custom allocators are intended for applications with specific placement, lifetime, accounting, performance, or platform requirements.
Does min-publish-age affect cargo install?
No. The dependency cooldown does not apply to cargo install. Users should explicitly review and select versions when installing command-line programs from a registry.
Does a Cargo cooldown guarantee dependency safety?
No. It only delays the selection of recently published versions. It can provide time for detection, but it cannot identify hidden malicious code or guarantee that an older release is safe.
A Milestone Focused on Practical Reliability
Rust 1.100 is more than a symbolic version number. The never type finally becomes a complete part of the type system, the Allocator API opens stable Rust to specialized allocation strategies, and DropGuard makes reliable cleanup easier. Meanwhile, Cargo’s dependency cooldowns, warnings, and cache improvements strengthen everyday development workflows without forcing projects to adopt them all at once.