
The Rust project has shipped Rust 1.99.0. The headline feature is long awaited by anyone who writes code that talks to C: you can now define C-style variadic functions in Rust itself, on stable. The release also brings a set of smaller standard library additions that tidy up everyday code around Vec, Box, String and file timestamps. Here is what changed, who benefits, and how to upgrade your toolchains and CI.
Defining C variadic functions in Rust
Variadic functions are the ones that take a variable number of arguments, like printf in C. Rust has long been able to call such functions through FFI, but defining one in Rust that C code could call required nightly features. Rust 1.99.0 stabilises this for the "C" and "C-unwind" ABIs.
A minimal example, adapted from the release announcement:
unsafe extern "C" fn sum(mut args: ...) -> i32 {
let a = unsafe { args.next_arg::<i32>() };
let b = unsafe { args.next_arg::<i32>() };
a + b
}
Alongside this, several supporting pieces are now stable:
core::ffi::VaList, a type that is ABI-compatible with C’sva_list, so you can pass argument lists between Rust and C.- The
VaArgSafetrait, which limits which types may be read out of aVaList, closing off a class of mistakes. - Naked variadic functions with non-C ABIs, written using inline assembly, for the low-level cases that need them.
Why it matters: projects that replace C components piece by piece, such as plugin hosts, logging shims, system libraries and drivers, can now implement C interfaces that use variadic signatures directly in Rust, without a C wrapper file in the build. Reading arguments is still unsafe, because Rust cannot check what the caller actually passed, so treat these functions with the same care as any FFI boundary.
Layout information from raw pointers
Three functions for getting the size and alignment of a value through a raw pointer are now stable:
Layout::for_value_rawmem::size_of_val_rawmem::align_of_val_raw
They work for both sized and unsized types. This is mainly useful for authors of allocators, smart pointers and other low-level data structures, who previously had to create a reference just to ask how large something was, which is not always valid.
New standard library APIs
The release stabilises a useful batch of everyday APIs:
| API | What it gives you |
|---|---|
Vec::into_parts / Vec::from_parts |
Take a vector apart into its pointer, length and capacity and rebuild it |
Box::into_non_null / Box::from_non_null |
Convert a box to and from a NonNull pointer |
String::from_utf8_lossy_owned |
Build a String from owned bytes, replacing invalid UTF-8 |
FromUtf8Error::into_utf8_lossy |
Recover a lossy string from a failed UTF-8 conversion |
VecDeque::retain_back |
Retain elements, working from the back of the deque |
IntoIterator for Box<[T; N]> |
Iterate a boxed array by value, by reference or mutably |
FusedIterator for StepBy<I> |
Stronger guarantees when chaining step_by |
std::fs::set_times / set_times_nofollow |
Set file timestamps by path, with or without following symlinks |
The file timestamp functions will be welcome in deployment tools, backup utilities and build scripts that previously needed an extra crate or a file handle just to adjust modification times.
A note on Box::leak
The documentation for Box::leak now advises against leaking a box and later turning it back into a box, because that pattern interacts badly with compiler optimisations. If you need to hand a heap allocation off and reclaim it later, prefer Box::into_raw or the new Box::into_non_null. It is worth searching your codebase for this pattern during the upgrade.
How to upgrade
If you installed Rust with rustup, upgrading is one command:
rustup update stable
rustc --version
For teams and build servers, a short checklist:
- Update pinned toolchains. If your projects use a
rust-toolchain.tomlfile, change the channel to1.99.0in a branch first. - Run the full test suite and Clippy.
cargo testandcargo clippy --all-targetscatch most surprises early. - Update CI images. Docker images and runners that cache a toolchain will not pick up the new release on their own.
- Review FFI code. If you kept small C files only to implement variadic callbacks, you can now consider moving them into Rust.
- Set MSRV deliberately. If you publish crates and adopt the new APIs, raise your minimum supported Rust version and note it in the changelog.
How TechProvidence can help
We build and maintain CI/CD pipelines, build servers and container images for development teams, including Rust toolchains on Linux. If you would like help standardising toolchain versions across developers and servers, or automating builds and deployments, contact us.
Summary
Rust 1.99.0 is a solid release for systems programmers: stable C variadic definitions make FFI work cleaner, raw-pointer layout helpers help low-level library authors, and the new standard library APIs remove small but common annoyances. Upgrade with rustup, run your tests, and update your CI images.
Source: Rust Blog


