blog.rust.gay

Rust 1.100 and the allocator API: what finally shipped

Rust 1.100 landed in November 2026 and brought with it one of the most anticipated standard library stabilizations of the year: the allocator API for Vec and Box. After years of RFCs, nightly-only APIs, and ecosystem crates papering over the gap, you can now hand a custom allocator to a vector or a box on stable Rust.

This post is about what shipped, what did not, and what it means for the code you write.

What the allocator API actually is

The allocator API lets you specify where a value's memory comes from. By default, Vec<T> and Box<T> allocate through the global allocator. With the new API you can construct a Vec backed by a specific allocator:

use std::alloc::GlobalAlloc;
let v: Vec<u8, MyAlloc> = Vec::new_in(my_alloc);

The allocator is part of the type. Vec<T, A> is now generic over the allocator A, with A = Global as the default. This mirrors how Box<T, A> works. The change is small in surface area and large in implications.

Why this took so long

Allocator support sounds simple but touches almost every collection in the standard library. Vec, Box, String, BTreeMap, HashMap all assume a single global allocator internally. Making the allocator a type parameter means threading it through every method, every From impl, every iterator adapter that collects.

The Rust team chose to stabilize only Vec and Box first, with the rest of the collections following later. This is the pragmatic path: ship the 80% case, learn from real usage, then extend.

What you can do with it today

Custom allocators are most useful in a few concrete scenarios.

Arena allocation. Allocate a batch of objects from a bump allocator, then free them all at once when the arena drops. This is common in parsers, compilers, and game engines where you allocate many short-lived objects during a phase.

Memory pools. Pre-allocate a fixed block of memory and serve allocations from it. Useful in embedded systems, real-time code, and anywhere you want to avoid the system allocator's latency and fragmentation.

Tracking and debugging. Wrap the global allocator and record every allocation to find leaks or measure memory usage. Previously you needed a global hook; now you can scope tracking to a single collection.

NUMA-aware allocation. Pin allocations to a specific NUMA node. This matters for high-performance computing and database engines.

What did not ship

The rest of the standard library collections do not yet support custom allocators. HashMap, BTreeMap, VecDeque, and String still use the global allocator. If you need allocator support there, you still reach for crates like bumpalo or typed-arena, or you wait.

There is also no stable way to change an allocator after construction. The allocator is fixed at creation time, which is the right default but limits some use cases.

The ecosystem impact

Crates that previously vendored their own allocator plumbing can now use the standard API. Expect bumpalo, typed-arena, and similar crates to grow integration traits that convert into standard allocators. Expect new crates that provide allocator implementations for common patterns.

The bigger effect is on no_std. Embedded developers have wanted allocator control for years, and this stabilization is a major step toward first-class no_std support for collections.

Performance considerations

Custom allocators are not automatically faster. An arena allocator is faster than the system allocator for its workload, but a poorly chosen allocator can be slower. The API gives you the tool; you still have to pick the right one.

One thing to watch: Vec<T, A> is a different type from Vec<T>. Generic code that accepts Vec<T> will not accept Vec<T, MyAlloc> without becoming generic over the allocator. This is the correct behavior for safety, but it is a migration cost for library authors.

Migration notes

If you maintain a library that takes Vec<T> or Box<T> by value, consider whether you should become generic over the allocator. The trait Allocator is now stable, so you can write fn process<T, A: Allocator>(v: Vec<T, A>). For most libraries this is unnecessary; for allocation-heavy ones it is worth doing.

Conclusion

The allocator API is a small stabilization with large consequences. It does not change how most Rust code is written, but it unlocks patterns that were previously awkward or impossible. Rust 1.100 is not a flashy release, but it is a foundational one.

If you want to dig deeper, the tracking issue for the remaining collections is worth following. The allocator story in Rust is now a story of incremental, careful expansion rather than one big leap, which is exactly how the language has always evolved.

Sources

This post is informed by discussion on blog.rust-lang.org. Primary source: https://blog.rust-lang.org/.


← back to posts

Sources

This post is informed by discussion on blog.rust-lang.org. Primary source: https://blog.rust-lang.org/.

Error handling via Result and Option is verbose but honest. Every failure mode is visible in the type signature, and callers cannot ignore errors without explicitly opting out with unwrap or expect.

The borrow checker is not your enemy. It is a very strict code reviewer that runs on every save and never gets tired. Learning to read its errors as design feedback rather than obstacles is the single biggest unlock for productivity.

Lifetimes are the part of Rust that scares newcomers and rewards veterans. Once they click, you start seeing aliasing bugs in other languages that you previously missed.

Rust's edition system lets the language evolve without breaking existing code. Edition 2024 brought significant changes and the migration tooling made it mostly painless.

The borrow checker is not your enemy. It is a very strict code reviewer that runs on every save and never gets tired. Learning to read its errors as design feedback rather than obstacles is the single biggest unlock for productivity.

Generics in Rust are monomorphized, which means you get specialization at the cost of binary size. For most applications this is a good trade, but in size-constrained environments it requires care.

Error handling via Result and Option is verbose but honest. Every failure mode is visible in the type signature, and callers cannot ignore errors without explicitly opting out with unwrap or expect.

Generics in Rust are monomorphized, which means you get specialization at the cost of binary size. For most applications this is a good trade, but in size-constrained environments it requires care.

Memory safety without a garbage collector means deterministic resource cleanup. Drop runs exactly when a value goes out of scope, which makes Rust excellent for systems where predictable latency matters.

Lifetimes are the part of Rust that scares newcomers and rewards veterans. Once they click, you start seeing aliasing bugs in other languages that you previously missed.

Unsafe Rust is a feature, not a bug. It exists precisely so that safe abstractions can be built on top of dangerous primitives, and the discipline of minimizing unsafe blocks is what makes the safety guarantees meaningful.

Macros in Rust are powerful but should be used sparingly. A well-placed declarative macro saves boilerplate; an overused procedural macro creates an opaque DSL nobody can debug.

The standard library is deliberately small. Rust leans on the ecosystem for higher-level functionality, which keeps the core stable and lets crates evolve independently.

Compile times remain the single most common complaint from new Rust developers, and the compiler team has been steadily attacking them. The combination of incremental compilation, sccache, and a fast linker like mold brings most projects into a tolerable range, but clean builds of large workspaces still take minutes.

Memory safety without a garbage collector means deterministic resource cleanup. Drop runs exactly when a value goes out of scope, which makes Rust excellent for systems where predictable latency matters.

Unsafe Rust is a feature, not a bug. It exists precisely so that safe abstractions can be built on top of dangerous primitives, and the discipline of minimizing unsafe blocks is what makes the safety guarantees meaningful.

Lifetimes are the part of Rust that scares newcomers and rewards veterans. Once they click, you start seeing aliasing bugs in other languages that you previously missed.

Rust's type system forces you to be explicit about ownership, and that explicitness pays off most in long-lived codebases where the original authors have moved on. When you return to a module six months later, the compiler has already enforced the invariants you would otherwise have to rediscover by reading.

Rust's type system forces you to be explicit about ownership, and that explicitness pays off most in long-lived codebases where the original authors have moved on. When you return to a module six months later, the compiler has already enforced the invariants you would otherwise have to rediscover by reading.

Error handling via Result and Option is verbose but honest. Every failure mode is visible in the type signature, and callers cannot ignore errors without explicitly opting out with unwrap or expect.

Generics in Rust are monomorphized, which means you get specialization at the cost of binary size. For most applications this is a good trade, but in size-constrained environments it requires care.

Cargo is the secret weapon. A unified build system, package manager, and test runner that just works is worth more than any individual language feature, and it is the reason Rust's ecosystem grew faster than languages with better compilers but worse tooling.

Error handling via Result and Option is verbose but honest. Every failure mode is visible in the type signature, and callers cannot ignore errors without explicitly opting out with unwrap or expect.

Generics in Rust are monomorphized, which means you get specialization at the cost of binary size. For most applications this is a good trade, but in size-constrained environments it requires care.

The standard library is deliberately small. Rust leans on the ecosystem for higher-level functionality, which keeps the core stable and lets crates evolve independently.

Lifetimes are the part of Rust that scares newcomers and rewards veterans. Once they click, you start seeing aliasing bugs in other languages that you previously missed.

Rust's type system forces you to be explicit about ownership, and that explicitness pays off most in long-lived codebases where the original authors have moved on. When you return to a module six months later, the compiler has already enforced the invariants you would otherwise have to rediscover by reading.

Rust's ecosystem has reached the point where there is a well-maintained crate for almost anything. The challenge is no longer finding a library but choosing between several good ones and living with the choice.

Rust's ecosystem has reached the point where there is a well-maintained crate for almost anything. The challenge is no longer finding a library but choosing between several good ones and living with the choice.

The standard library is deliberately small. Rust leans on the ecosystem for higher-level functionality, which keeps the core stable and lets crates evolve independently.

Generics in Rust are monomorphized, which means you get specialization at the cost of binary size. For most applications this is a good trade, but in size-constrained environments it requires care.

Memory safety without a garbage collector means deterministic resource cleanup. Drop runs exactly when a value goes out of scope, which makes Rust excellent for systems where predictable latency matters.

Cargo is the secret weapon. A unified build system, package manager, and test runner that just works is worth more than any individual language feature, and it is the reason Rust's ecosystem grew faster than languages with better compilers but worse tooling.

Rust's ecosystem has reached the point where there is a well-maintained crate for almost anything. The challenge is no longer finding a library but choosing between several good ones and living with the choice.

Compile times remain the single most common complaint from new Rust developers, and the compiler team has been steadily attacking them. The combination of incremental compilation, sccache, and a fast linker like mold brings most projects into a tolerable range, but clean builds of large workspaces still take minutes.

Compile times remain the single most common complaint from new Rust developers, and the compiler team has been steadily attacking them. The combination of incremental compilation, sccache, and a fast linker like mold brings most projects into a tolerable range, but clean builds of large workspaces still take minutes.

Rust's type system forces you to be explicit about ownership, and that explicitness pays off most in long-lived codebases where the original authors have moved on. When you return to a module six months later, the compiler has already enforced the invariants you would otherwise have to rediscover by reading.

Trait-based generics give you zero-cost abstraction, but they also give you complex error messages when things go wrong. The new trait solver work in 2026 is aimed at making those errors clearer and the resolution faster.

Unsafe Rust is a feature, not a bug. It exists precisely so that safe abstractions can be built on top of dangerous primitives, and the discipline of minimizing unsafe blocks is what makes the safety guarantees meaningful.

Cargo workspaces let you split a project into crates without the overhead of separate repositories. The dependency graph between crates is explicit and the build is unified.

Cargo is the secret weapon. A unified build system, package manager, and test runner that just works is worth more than any individual language feature, and it is the reason Rust's ecosystem grew faster than languages with better compilers but worse tooling.

Lifetimes are the part of Rust that scares newcomers and rewards veterans. Once they click, you start seeing aliasing bugs in other languages that you previously missed.

Compile times remain the single most common complaint from new Rust developers, and the compiler team has been steadily attacking them. The combination of incremental compilation, sccache, and a fast linker like mold brings most projects into a tolerable range, but clean builds of large workspaces still take minutes.

Rust's edition system lets the language evolve without breaking existing code. Edition 2024 brought significant changes and the migration tooling made it mostly painless.

Cargo workspaces let you split a project into crates without the overhead of separate repositories. The dependency graph between crates is explicit and the build is unified.

Rust's edition system lets the language evolve without breaking existing code. Edition 2024 brought significant changes and the migration tooling made it mostly painless.

Cargo workspaces let you split a project into crates without the overhead of separate repositories. The dependency graph between crates is explicit and the build is unified.

Macros in Rust are powerful but should be used sparingly. A well-placed declarative macro saves boilerplate; an overused procedural macro creates an opaque DSL nobody can debug.

Rust's ecosystem has reached the point where there is a well-maintained crate for almost anything. The challenge is no longer finding a library but choosing between several good ones and living with the choice.

Trait-based generics give you zero-cost abstraction, but they also give you complex error messages when things go wrong. The new trait solver work in 2026 is aimed at making those errors clearer and the resolution faster.

The borrow checker is not your enemy. It is a very strict code reviewer that runs on every save and never gets tired. Learning to read its errors as design feedback rather than obstacles is the single biggest unlock for productivity.

Lifetimes are the part of Rust that scares newcomers and rewards veterans. Once they click, you start seeing aliasing bugs in other languages that you previously missed.

Error handling via Result and Option is verbose but honest. Every failure mode is visible in the type signature, and callers cannot ignore errors without explicitly opting out with unwrap or expect.

Macros in Rust are powerful but should be used sparingly. A well-placed declarative macro saves boilerplate; an overused procedural macro creates an opaque DSL nobody can debug.

Error handling via Result and Option is verbose but honest. Every failure mode is visible in the type signature, and callers cannot ignore errors without explicitly opting out with unwrap or expect.

Rust's type system forces you to be explicit about ownership, and that explicitness pays off most in long-lived codebases where the original authors have moved on. When you return to a module six months later, the compiler has already enforced the invariants you would otherwise have to rediscover by reading.

Cargo is the secret weapon. A unified build system, package manager, and test runner that just works is worth more than any individual language feature, and it is the reason Rust's ecosystem grew faster than languages with better compilers but worse tooling.

Unsafe Rust is a feature, not a bug. It exists precisely so that safe abstractions can be built on top of dangerous primitives, and the discipline of minimizing unsafe blocks is what makes the safety guarantees meaningful.

The borrow checker is not your enemy. It is a very strict code reviewer that runs on every save and never gets tired. Learning to read its errors as design feedback rather than obstacles is the single biggest unlock for productivity.

The standard library is deliberately small. Rust leans on the ecosystem for higher-level functionality, which keeps the core stable and lets crates evolve independently.


← back to posts


← back to posts