Rust 1.94.0 Is Here – Array Windows, Smarter Cargo Config, and More Stabilized APIs
Rust ships a new stable release every six weeks, and 1.94.0 is no exception. It landed on March 5, 2026, and while it isn’t a “rewrite the language” kind of drop, there are a handful of genuinely useful additions that are worth knowing about. Let’s walk through everything.
TL;DR
array_windowsgives you compile-time-sized slice windows (&[T; N]) — no more dynamic slices when you know the size upfront.- Cargo’s new
includekey lets you split and share config files across workspaces.- Cargo now parses TOML 1.1 — trailing commas in inline tables, new escape sequences, and more.
LazyCell/LazyLockgot new methods, math constantsEULER_GAMMAandGOLDEN_RATIOwere added, andf32/f64::mul_addis nowconst.- Upgrading is a single
rustup updateaway.
How to Upgrade
If you’re on rustup, this is all you need:
rustup update stable
Verify the version:
rustc --version
# rustc 1.94.0 (xxxxxxx 2026-03-05)
Want to try the next release early, or live on the bleeding edge?
rustup default beta # upcoming stable
rustup default nightly # experimental features
array_windows: Fixed-Size Slice Windows
The Problem with windows
The existing windows iterator yields &[T] — a dynamically sized slice. Even when you know at compile time that you want exactly 4 elements, the compiler can’t encode that in the type:
let data = b"abxyyxcd";
for w in data.windows(4) {
// w is &[u8] — length is runtime information only
let a = w[0]; // bounds check needed every time
}
Enter array_windows
array_windows::<N>() yields &[T; N] — a reference to a fixed-size array. The length is part of the type, which means the compiler eliminates bounds checks and you can use array destructuring directly in closures and match arms.
Here’s the ABBA pattern example from the official release notes:
fn has_abba(bytes: &[u8]) -> bool {
bytes
.array_windows::<4>()
.any(|[a, b, c, d]| a != b && a == d && b == c)
}
No indexing, no manual bounds checks. The pattern [a, b, c, d] lets the compiler verify at compile time that the window is exactly 4 bytes wide.
A more general example:
let temperatures: Vec<f64> = vec![20.1, 21.3, 19.8, 22.5, 23.0];
// Detect a run of 3 strictly increasing values
let has_uptrend = temperatures
.array_windows::<3>()
.any(|[a, b, c]| a < b && b < c);
println!("Uptrend detected: {has_uptrend}");
When to Use It
- Protocol parsing — fixed-size headers and magic bytes.
- Signal processing — sliding window averages, FIR filters.
- Pattern detection — any case where you compare a small, constant-size chunk against a known shape.
array_windows lives alongside windows. There’s no pressure to migrate; adopt it where the fixed size is a natural fit.
element_offset: Find Where an Element Lives in a Slice
Also stabilized in 1.94.0 is element_offset, which tells you the index of a reference that points into a slice. This is handy when you have a reference to a slice element but need its position:
let haystack = &[10, 20, 30, 40, 50];
let needle = &haystack[3]; // reference to 40
if let Some(idx) = haystack.element_offset(needle) {
println!("Found at index {idx}"); // Found at index 3
}
The method returns None if the reference doesn’t point into the slice at all, making it safe to use across arbitrary slice/reference pairs.
Cargo Config Gets an include Key
The Problem
.cargo/config.toml is great for per-project overrides — custom registries, build flags, target specs. But in a large workspace with many crates, you end up copy-pasting the same blocks everywhere or maintaining a fragile manual sync.
How include Works
The new include key in .cargo/config.toml lets you pull in other TOML files and merge them into the current config:
# .cargo/config.toml
[build]
target = "x86_64-unknown-linux-gnu"
[include]
paths = ["../shared-cargo-config.toml"]
Files are merged in order. If two files define the same key, the later one wins.
Optional Includes
For settings that only exist on some machines (a local cache path, personal registry credentials), mark them optional:
[include]
paths = [
"../company-defaults.toml",
{ path = "local-overrides.toml", optional = true },
]
If local-overrides.toml doesn’t exist, Cargo skips it silently instead of erroring out. This keeps per-developer tweaks out of version control while still giving everyone an easy place to put them.
Practical Use Cases
- Company-wide Clippy rules — one shared
clippy.tomlincluded by every crate. - Cross-compilation toolchains — centralize embedded target specs.
- CI vs. local differences — a
ci-config.tomlthat enforces stricter warnings, included only in CI pipelines.
Cargo Now Parses TOML 1.1
Cargo switched its TOML parser to TOML 1.1 for both Cargo.toml manifests and .cargo/config.toml files. Here’s what practically changes for you.
Trailing Commas in Inline Tables
The most day-to-day improvement: you can now leave a trailing comma inside an inline table.
# Valid in TOML 1.1 — trailing comma after false
[dependencies]
serde = { version = "1", features = ["derive"], default-features = false, }
This is the same convenience you get in Rust arrays and function calls. No more “remove that trailing comma” mental tax.
New Escape Sequences
TOML 1.1 adds two new escape sequences in strings:
| Sequence | Meaning |
|---|---|
\e |
Escape character (0x1B) |
\xHH |
Arbitrary byte by hex value |
[terminal]
reset = "\e[0m"
tab = "\x09"
Optional Seconds in Time Values
Time literals no longer require the seconds component:
# Both are valid in TOML 1.1
start-time = 09:30
end-time = 17:45:00
MSRV Considerations
If you use any 1.1 syntax in your Cargo.toml, users building with Cargo older than 1.94.0 will get a parse error. Options:
- Stick to TOML 1.0 syntax if you need to support older toolchains.
- Use
cargo publish’s automatic rewrite — Cargo rewrites the manifest to a compatible form before uploading to crates.io, so downstream users with older Cargo can still consume your crate.
Stabilized APIs
LazyCell and LazyLock Get New Methods
LazyCell and LazyLock were stabilized in 1.80.0. In 1.94.0 they gain three new methods:
get()— returnsOption<&T>, checking if the value has already been initialized without triggering initialization.get_mut()— same, but returnsOption<&mut T>when you have unique access.force_mut()— forces initialization and returns&mut T, giving you mutable access to the inner value.
use std::cell::LazyCell;
let cell: LazyCell<String> = LazyCell::new(|| {
println!("initializing...");
String::from("hello")
});
// Check without triggering init
assert!(LazyCell::get(&cell).is_none());
// Now force it
let val = LazyCell::force(&cell);
println!("{val}"); // "initializing..." then "hello"
// get() now returns Some
assert!(LazyCell::get(&cell).is_some());
New Math Constants: EULER_GAMMA and GOLDEN_RATIO
Two widely used mathematical constants join std::f64::consts (and their f32 counterparts):
use std::f64::consts::{EULER_GAMMA, GOLDEN_RATIO};
// Euler–Mascheroni constant γ ≈ 0.5772156649015329
println!("γ = {EULER_GAMMA}");
// Golden ratio φ ≈ 1.618033988749895
println!("φ = {GOLDEN_RATIO}");
// Example: estimate harmonic series using the asymptotic formula
// H(n) ≈ ln(n) + γ
fn harmonic_approx(n: u64) -> f64 {
(n as f64).ln() + EULER_GAMMA
}
f32::mul_add and f64::mul_add Are Now const
mul_add(a, b, c) computes a * b + c as a single fused operation (FMA — fused multiply-add), which is both faster and more numerically precise than doing the multiply and add separately. It’s now usable in const contexts:
const SCALE: f64 = 1.5_f64.mul_add(2.0, 0.5); // 1.5 * 2.0 + 0.5 = 3.5
const fn apply_gain(sample: f32, gain: f32, offset: f32) -> f32 {
sample.mul_add(gain, offset)
}
const PROCESSED: f32 = apply_gain(0.8, 1.25, 0.1); // 0.8 * 1.25 + 0.1 = 1.1
TryFrom<char> for usize
You can now convert a char to usize via TryFrom, which represents the Unicode scalar value of the character. On 32-bit platforms where usize is 16 bits, large code points would fail — hence Try:
let c = 'R';
let code_point = usize::try_from(c).unwrap();
println!("'R' has code point {code_point}"); // 82
Peekable Iterator Methods
The Peekable iterator adapter received additional methods, giving you more control over look-ahead logic without consuming the iterator prematurely.
x86 and AArch64 SIMD Intrinsics
A batch of platform-specific SIMD intrinsics was stabilized for both x86/x86_64 and AArch64. If you’re writing performance-critical code that targets specific hardware, check the full release notes for the complete list.
Beta and Nightly: Should You Jump?
Beta tracks the upcoming stable release (currently Rust 1.95-pre). It’s a good fit for hobby projects where you want early access but still need a reasonably stable toolchain.
Nightly is for experimentation: unstable language features, new macro systems, and things that might change tomorrow.
A workflow that works well in practice:
| Channel | When to use it |
|---|---|
stable |
Production code, CI pipelines |
beta |
Side projects, early-adopter testing |
nightly |
Feature experimentation, isolated in Docker |
# Install beta alongside stable without switching default
rustup toolchain install beta
cargo +beta build
# Or switch globally
rustup default beta
Final Thoughts
Rust 1.94.0 is a solid incremental release. array_windows removes a small but recurring ergonomics pain from slice work. Cargo’s include key finally makes it practical to share config across large workspaces. TOML 1.1 support smooths out some long-standing paper cuts. And the new stabilized APIs — especially LazyLock::get, the math constants, and mul_add in const — keep expanding what you can express at compile time.
None of these changes require you to rewrite existing code, and all of them are backwards-compatible. The safest upgrade path: run rustup update stable, then let CI tell you if anything broke.
Happy coding, and may your borrows be always safe!
Sources
- Rust 1.94.0 Release Announcement – Official Rust blog. https://blog.rust-lang.org/2026/03/05/Rust-1.94.0/
array_windowsdocumentation – Rust standard library reference. https://doc.rust-lang.org/std/primitive.slice.html#method.array_windows- Cargo configuration guide – Cargo Book, config include. https://doc.rust-lang.org/cargo/reference/config.html
- TOML 1.1 Specification – Official TOML language spec. https://toml.io/en/v1.1.0
- Rust GitHub release notes – Full changelog on GitHub. https://github.com/rust-lang/rust/blob/master/RELEASES.md
- Rust Internals Forum – Community discussion on upcoming features. https://internals.rust-lang.org