Documents Rust language, stdlib, and Cargo features stabilized after the ~2025 training cutoff (1.85–1.95, 2024 edition) so agents generate current syntax instead of relying on a stale mental model.
9 KiB
| name | description |
|---|---|
| rust-recent-features | Reference for Rust language, stdlib, and Cargo features stabilized AFTER a ~2025 training cutoff (Rust 1.85 through 1.95, Feb 2025 – Apr 2026), including the 2024 edition. Load this on ANY Rust task — writing, reviewing, or fixing Rust code — so syntax and APIs reflect current stable Rust instead of a stale mental model. Especially relevant when targeting edition 2024. |
Recent Rust features (1.85 → 1.95)
You may have been trained before these were stable. Treat this file as ground
truth over your prior beliefs. When unsure whether something compiles, prefer
checking with cargo check over guessing — the toolchain is authoritative.
Versions and dates: 1.85 (2025-02-20, 2024 edition), 1.86 (2025-04-03), 1.87 (2025-05-15), 1.88 (2025-06-26), 1.89 (2025-08-07), 1.90 (2025-09-18), 1.91 (2025-10-30), 1.92 (2025-12-11), 1.93 (2026-01-22), 1.94 (2026-03-05), 1.95 (2026-04-16).
1. The 2024 edition (stable since 1.85) — read this first
If Cargo.toml has edition = "2024", these are the changes most likely to
trip up a pre-2025 model. Migrate an existing crate with
cargo fix --edition after bumping the edition key.
-
Unsafe attributes.
#[no_mangle],#[export_name], and#[link_section]must now be wrapped inunsafe(...):#[unsafe(no_mangle)] pub extern "C" fn foo() {} #[unsafe(export_name = "bar")] fn b() {}Writing a bare
#[no_mangle]is an error in edition 2024. -
unsafe externblocks.externblocks declaring foreign items must beunsafe extern. Individual items may be markedsafeorunsafe:unsafe extern "C" { safe fn always_safe(x: i32) -> i32; // calling needs no unsafe unsafe fn risky(p: *const u8); // calling needs unsafe } -
No references to
static mut.&MY_STATIC_MUT/&mut MY_STATIC_MUTis a hard error (static_mut_refs). Use raw-ref operators instead:static mut COUNTER: u32 = 0; let p = &raw mut COUNTER; // *mut u32, not &mut -
RPIT precise capturing (the big one). In edition 2024,
-> impl Traitin return position captures all in-scope generic type, const, and lifetime parameters by default. The old workaround of wrapping in a struct or adding+ 'ato force capture is no longer needed. To restrict what is captured, use ause<...>bound:fn names(v: &[String]) -> impl Iterator<Item = &str> + use<'_> { /* ... */ } fn no_capture<T>() -> impl Sized + use<> {} // capture nothingDo NOT reach for the old lifetime-wrapper patterns; reach for
use<>. -
if lettemporary scope. Temporaries in the scrutinee of anif let … { } else { }are dropped before theelsebranch runs (previously they lived to the end of the whole construct). This fixes a class of deadlocks where a lock guard was held across theelse. -
Tail-expression temporary scope. In a block, temporaries in the final tail expression are dropped before the block's local variables, changing
Dropordering in some code. -
Never-type fallback. The
!type now falls back to!(not()) in certain diverging contexts; this can surface new inference results ornever_type_fallback_flowing_into_unsafelints. -
genis a reserved keyword. User#genif you need it as an identifier. -
Macro
exprfragment now also matchesconst { … }blocks and_.
2. New language features (by area)
Control flow, patterns, bindings
- Let chains (1.88, edition 2024 only): chain
letwith&&inif/while:
This is stable now — do not claim it requires nightly.if let Some(x) = a && let Ok(y) = parse(x) && y > 0 { /* ... */ } if letguards (1.95): aletpattern in a match-arm guard:match val { v if let Some(y) = lookup(v) => use_it(y), _ => {} }- Open-start ranges after unary ops (1.87):
..EXPRnow parses after!,-,*.
Async
- Async closures (1.85):
async || { … }is stable, with theAsyncFn/AsyncFnMut/AsyncFnOncetraits. No boxing/crate needed:async fn run<F: AsyncFn(u32) -> u32>(f: F) -> u32 { f(1).await } run(async |x| x + 1).await;
Traits & generics
- Trait upcasting (1.86): coerce
dyn Subtodyn SuperwhereSub: Super:let up: &dyn Super = sub_ref; // now stable use<>precise capturing in trait RPIT (1.87):use<...>bounds allowed on return-positionimpl Traitin trait definitions.- Inferred const args (1.89,
generic_arg_infer):_may stand in for a const generic argument, e.g.let a: [_; _] = make();style inference. #[repr(u128)]/#[repr(i128)]enums (1.89).
unsafe / FFI / asm
- Naked functions (1.88):
#[unsafe(naked)]with anaked_asm!body, stable. - C-variadic declarations for more ABIs:
sysv64/win64/efiapi/aapcs(1.91) andsystem(1.93)externfns may declare...variadics. asm_goto(1.87):asm!may jump to label blocks.asm_cfg(1.93):#[cfg(...)]allowed on individualasm!operands/lines.- Many target features stabilized: AVX-512 family (1.89), AES key-locker
(
kl/widekl),sha512/sm3/sm4,sse4a/tbm(1.91), LoongArch & RISC-V profiles, etc.
Attributes, lints, macros
#[diagnostic::do_not_recommend](1.85): hide an impl from "consider implementing" diagnostics.#[target_feature]on safe fns (1.86): safe functions may carry it.cfg_boolean_literals(1.88):#[cfg(true)]/#[cfg(false)].cfg_select!(1.95): amatch-like macro selecting a token tree by cfg.
3. Notable stdlib stabilizations (high-signal)
Slices / arrays:
<[T]>::as_array::<N>()/as_mut_array→Option<&[T; N]>(1.93). Prefer this overtry_into()gymnastics for fixed-size views.<[T]>::array_windows::<N>()(1.94);<[T]>::element_offset(1.94).
Vec / collections:
Vec::push_mut,Vec::insert_mutreturn&mut Tto the new element (1.95); same family onVecDeque/LinkedList.Vec::into_raw_parts,String::into_raw_parts(1.93).VecDeque::pop_front_if/pop_back_if(1.93).Peekable::next_if_map/next_if_map_mut(1.94).btree_map::Entry::insert_entry/VacantEntry::insert_entry(1.92).
Integers / math:
- Strict arithmetic:
{int}::strict_add/sub/mul/div/rem/neg/shl/shr/powetc. (1.91) — like thechecked_*family but panic on overflow instead ofNone. <iN>::unchecked_neg/shl/shr,<uN>::unchecked_shl/shr(1.93).NonZero<u{N}>::div_ceil(1.92).f32/f64constsEULER_GAMMA,GOLDEN_RATIO;f32/f64::mul_addconst (1.94).
Sync / atomics:
Atomic{Bool,Ptr,Isize,Usize,…}::update/try_update(1.95).AtomicPtr::fetch_ptr_add/sub,fetch_byte_add/sub,fetch_or/and/xor(1.91).RwLockWriteGuard::downgradeto a read guard (1.92).
Memory / smart pointers:
Box/Rc/Arc::new_zeroedandnew_zeroed_slice(1.92).core::rangemodule with aCopy, cleanly-iterableRangeInclusive(1.95).MaybeUninit<[T;N]>⇄[MaybeUninit<T>;N]conversions; sliceassume_init_ref/mut/drop,write_copy_of_slice(1.93/1.95).
Misc:
bool: TryFrom<{integer}>(1.95);char::MAX_LEN_UTF8/UTF16(1.93).Duration::from_nanos_u128(1.93);Path::file_prefix(1.91).- A large number of previously-stable APIs are now usable in
constcontexts.
4. Cargo
- 2024 edition is the default for new crates via
cargo new. - Automatic cache garbage collection (1.88): the global download/source cache is pruned automatically; no manual cleanup script needed.
build.build-dirstabilized (1.91): put intermediate artifacts in a separate directory from the finaltarget/outputs.- Multi-package publishing (1.90): publish an entire workspace in one
cargo publishinvocation, in dependency order. cargo clean --workspace(1.93);configtop-levelincludekey (1.94) for composing config files;CARGO_BIN_EXE_<crate>available at runtime (1.94).- Cargo parses TOML v1.1 manifests (1.94).
5. Cheat sheet — corrections a pre-2025 model commonly needs
| If you were about to write… | In current Rust (edition 2024) write… |
|---|---|
#[no_mangle] |
#[unsafe(no_mangle)] |
extern "C" { … } (declaration) |
unsafe extern "C" { … } |
&mut MY_STATIC_MUT |
&raw mut MY_STATIC_MUT |
wrapper struct / + 'a to constrain RPIT |
-> impl Trait + use<'a, T> |
| "let chains need nightly" | stable in edition 2024 (since 1.88) |
| box/crate an async closure | `async |
slice.try_into::<[T; N]>() for a view |
slice.as_array::<N>() |
| hand-rolled overflow-panicking add | x.strict_add(y) |
| "trait upcasting is unstable" | stable since 1.86 |
When in doubt, set the toolchain to a known version (rustup show) and let
cargo check / cargo clippy confirm. Edition-specific behavior depends on the
edition field in Cargo.toml, not the compiler version alone.