Skip to content
chornous.dev

Type two or more letters. Esc closes.

Index of sheets
Theme

Sheet 03 · Writing

All notes

Rust 1.100: the never type is stable, Infallible becomes !, and Cargo can hold back fresh crates

The Rust Release Team shipped Rust 1.100.0 on November 12, 2026. The never type is stable after 10 years, older editions now fall back to ! instead of (), the core Allocator API works with Vec and Box, and Cargo gains a min-publish-age setting for dependency cooldowns.

Pl. 27 · section drawing generated from the slug “rust-1-100-never-type-allocator-api”

The Rust Release Team published Rust 1.100.0 on November 12, 2026. The headline item took a decade: the never type, written !, is stable after five failed stabilization attempts. The release also stabilizes the core of the allocator API, adds DropGuard, and gives Cargo two features you will notice on your next cargo update.

rustup update stable

The never type, and the one breaking change

You could already write -> ! on a function that never returns, and return or panic! already had type !. Rust 1.100 lets you name ! anywhere a type goes:

fn infallible_unwrap<T>(res: Result<T, !>) -> T {
    let Ok(v) = res;
    v
}

The team also turned std::convert::Infallible into an alias for !. Any API written against Infallible now works with ! as well.

That alias forced a language change. In editions 2015, 2018 and 2021, the compiler used () as the never type fallback when inference had nothing better. Rust 1.100 switches those editions to !, which edition 2024 did already. The release notes call the effect unnoticeable in most code, but you can hit it in rare cases, such as discarding the result of a function that returns a generic parameter. The compiler may also flag more code as unreachable.

If a dependency fails to build after the upgrade with a never-type error, update that crate first. The team says it shipped fixes to public crates that the change broke.

Allocators and DropGuard

The Allocator trait is stable, along with Global, System and the _in constructors on Vec and Box: Vec::new_in, Vec::with_capacity_in, Box::new_in and their siblings. Library authors can now write an arena or bump allocator and hand it to a standard Vec on stable. Other collections still don't accept a custom allocator. The team calls this the foundation of its Allocators 1.0 goal and expects more to follow.

core::mem::DropGuard wraps a value and a closure. The closure runs when the guard drops, on a normal return, on ?, or on a panic. DropGuard::dismiss hands the value back and skips the closure. The release post uses it for rollback:

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()?);
    }
    DropGuard::dismiss(nums);
    Ok(())
}

dismiss is an associated function and not a method, so it can't collide with methods on the wrapped type through DerefMut.

Cargo: cooldowns, unused dependencies, a new build-dir layout

Dependency cooldowns are the change I'd turn on today. You set a minimum age in .cargo/config.toml, and the resolver skips any version younger than that:

[registry]
global-min-publish-age = "3 days"

cargo update then reports what it held back, for example cc v1.11.0 (available: v1.18.0, published 3 hours ago). To take a fresh release on purpose, set CARGO_RESOLVER_INCOMPATIBLE_PUBLISH_AGE=allow for one cargo update --precise run. Cargo writes that version to Cargo.lock and keeps it.

Cargo also warns about unused dependencies now, through a new cargo::unused_dependencies lint set to warn by default. The warning appears when you build every target that could use the dependency, so cargo check --bin foo stays quiet. dev-dependencies get no warning at all. You control the lint in a [lints.cargo] table in Cargo.toml.

The build directory changed shape. Cargo now groups output by build step and puts the build-configuration hash in the parent directory name, not the file name. That fixes extra and missed rebuilds, which got worse when you shared a build-dir across git worktrees. Scripts or tests that reach into target/ for a specific artifact path may break. The team tracks those cases in cargo#17287.

Smaller stabilizations

Selected APIs stabilized in Rust 1.100.0
APIUse
std::mem::conjure_zstUnsafe, sanctioned way to create a zero-sized value
str::trim_prefix, str::trim_suffixAlso on slices; Path gets trim_prefix
Vec::from_fnBuild a vector from a closure
Rc::map, Arc::map, Box::mapMap the contents of a smart pointer
bool::toggle, Box::takeSmall conveniences

This week

  1. Run rustup update stable and build your workspace on a pre-2024 edition crate first. Fix any new never-type errors by updating the dependency that fails.
  2. Add global-min-publish-age to .cargo/config.toml in CI and on your machine. Three days matches the example in the release post.
  3. Grep your scripts and CI for hard-coded paths under target/debug/deps or target/release/build, and check them against the new layout.
  4. Read the unused-dependency warnings from a full cargo build --all-targets and delete what you don't need.

Volodymyr Chornous