Rust Cargo 4 min read

Rust 1.99.0 Stabilizes C-Variadic Functions and Updates Cargo Profiles

The latest Rust release introduces C-variadic function stabilization, new library APIs, and significant Cargo improvements including a dedicated debug profile.

Rust 1.99.0 is out. It stabilizes C-variadic function definitions, adds new Vec and Box APIs, and makes several compatibility changes, including a new hard error and an Edition 2024 Cargo change. The release was published on October 1 and updates the compiler to LLVM 23.

Language changes

The main stabilization is C-variadic function definitions. Functions marked #[unsafe(naked)] can now also define C-variadic functions, behind the c_variadic_naked_functions feature gate. core::ffi::VaList is stable alongside them. Another stabilization allows outlined modules (mod foo;) anywhere in the body of a custom attribute or derive macro, so #[my_macro] mod foo; now works. On x86, asm! can pass 128-bit integers through vector registers.

Several lints changed. A new allow-by-default raw_borrows_via_references lint flags references that decay immediately into raw borrows. The unconditional_panic lint now covers function calls that panic when a chunks or windows size is zero. The overflowing_literals lint no longer fires on repeated negation such as --128_i8, which the arithmetic_overflow lint already catches. POSIX symbols were added to the invalid_runtime_symbol_definitions and suspicious_runtime_symbol_definitions lints. Unused #[path] attributes on inline modules are now linted.

The project also now guarantees that the contents of an UnsafeCell can be accessed without going through get. The invalid_reference_casting lint was adjusted to match. Documentation now says some allocations may grow in place, but none may shrink.

Libraries, compiler and platforms

The newly stable APIs include IntoIterator for Box<[T; N]> and for references to it, VecDeque::retain_back, Vec::into_parts and Vec::from_parts, and Box::into_non_null and Box::from_non_null. Also stable are String::from_utf8_lossy_owned, std::fs::set_times and set_times_nofollow, LocalKey<Cell<T>>::update, and the raw-pointer helpers size_of_val_raw, align_of_val_raw and Layout::for_value_raw.

Iteration over RangeInclusive is better optimized in some cases. As a result, start() and end() on an already exhausted range may return different values, and using such a range as a slice index may behave differently. The release notes say these behaviors were never guaranteed, so the change is not treated as breaking.

When rustc suggests a method for a missing name, it now prefers an exact doc alias match over a similarity search. Library authors can add aliases to help users who expect a different method name. riscv64-unknown-linux-musl moves to Tier 2 with host tools. Rustdoc's smarter filtering of trait impls improves performance by 20% on average and by up to 40% on some real-world crates.

Cargo and compatibility notes

Cargo adds a built-in debug profile. It is currently identical to dev, and it prepares for moving dev away from debugging to give faster default iteration. Workspace members on edition 2024 or later can now override an inherited dependency's default-features field. For example, serde = { workspace = true, default-features = false } now turns off default features even when the workspace definition enables them. Earlier editions ignore the setting and print a warning. Incremental compilation is now off by default in CI, which Cargo detects through the CI environment variable.

Some changes may break existing code:

  • no_mangle_generic_items is now a hard error.
  • The legacy integral modules, such as std::i32::MAX, are fully deprecated in favor of i32::MAX.
  • Attributes that apply to nothing are now errors in doc-comment code blocks.
  • Anonymous lifetimes in the types of associated consts are inferred as 'static.
  • Pin::new_unchecked has slightly changed safety invariants.

Macros that expand to a semicolon now trigger the semicolon_in_expressions_from_non_local_macros warning even when the macro comes from another crate. Previously the warning appeared only for macros in the same crate. The project says this hid problems, because a crate's integration tests compile as a separate crate. It asks developers who see the lint to report it to the macro's author instead of silencing it.

The Rust Reference also dropped its recommendation to match a union and another value in a single pattern, as in a hand-written tagged union. In some cases the compiler reads the union before checking the rest of the pattern, which can cause undefined behavior.