Rust 1.99 estabiliza la definición de funciones C-variadic
Rust 1.99.0, publicado el 1 de octubre de 2026, permite a Rust estable definir funciones C-variadic como printf, pasa a LLVM 23 y convierte no_mangle en genéricos en un error.
4 min de lectura

En cifras
- new code-generation backend
- LLVM 23
- average Rustdoc speedup on trait impl filtering
- 20%
- best-case Rustdoc speedup on some crates
- 40%
- release that first warned about no_mangle on generics
- 1.56
El equipo de Rust publicó Rust 1.99.0 el 1 de octubre de 2026. Su cambio principal permite a Rust estable definir funciones C-variadic, el tipo de función que acepta cualquier número de argumentos, como printf de C. Eso cierra una brecha para el código Rust que tiene que trabajar codo con codo con C.
La versión también pasa el compilador a LLVM 23, acelera la herramienta de documentación y convierte una advertencia de larga data en un error definitivo.
Qué aportan las definiciones C-variadic
Una función variádica acepta un número variable de argumentos. C las usa ampliamente, y Rust lleva mucho tiempo pudiendo llamarlas. Definir una en Rust era otra cosa. "Rust ya podía llamar a funciones variádicas definidas externamente (por ejemplo, libc::printf). Con Rust 1.99, estas funciones ahora pueden escribirse en el propio Rust", dice el anuncio oficial.
La sintaxis usa ... como último parámetro. ByteIOTA da la forma de una definición como unsafe extern "C" fn my_logger(count: u32, mut args: ...) -> i32. Dentro de la función, los argumentos adicionales llegan como un core::ffi::VaList, que según el blog de Rust es compatible con el tipo va_list de C a nivel binario. Linux Compatible informa de que el código lee cada argumento con next_arg::<T>().
Un trait llamado VaArgSafe controla qué tipos pueden pasar. Marca los tipos que se pueden leer de forma segura de la lista de argumentos, lo que ayuda a evitar discrepancias de tipos. La versión también permite que las funciones naked usen firmas variádicas, según el blog de Rust y releases.rs. Una función naked es aquella que el compilador emite sin código de preparación. El código de bajo nivel y el embebido la usan para controlar con exactitud la convención de llamada.
Nuevas API de biblioteca estables
El blog de Rust incluye estas entre las API que ya están disponibles en la versión estable:
- Disposición de memoria:
Layout::for_value_raw,mem::size_of_val_raw,mem::align_of_val_raw - Colecciones y Box:
Box::into_non_null,Vec::into_parts,Vec::from_parts,VecDeque::retain_back - Sistema de archivos:
std::fs::set_times,std::fs::set_times_nofollow
Las funciones set_times cambian las marcas de tiempo de un archivo desde la biblioteca estándar. Como sugiere su nombre, la variante _nofollow no sigue los enlaces simbólicos.
Cambios en el compilador, las plataformas y las herramientas
Rust 1.99 se actualiza a LLVM 23, la biblioteca de generación de código que convierte Rust en código máquina. ByteIOTA informa de una reducción media del 1,2 % en el tiempo real de compilación en los benchmarks, parte de una mejora del 4,57 % en dos meses.
Otros cambios, según Linux Compatible y releases.rs:
| Área | Cambio |
|---|---|
| Plataformas | Linux RISC-V de 64 bits con musl sube al soporte Tier 2 |
| Enlazado | Los ejecutables estáticos independientes de la posición se habilitan en los targets GNU y musl |
| Rustdoc | Filtrar implementaciones de traits es alrededor de un 20 % más rápido de media, hasta un 40 % en algunos crates |
| Macros | Las macros de atributo ahora funcionan en módulos definidos en un archivo aparte, como #[my_macro] mod foo; |
| Ensamblador en línea | Los enteros de 128 bits pueden pasarse en registros vectoriales en x86 |
Cargo, la herramienta de compilación de Rust, recibe tres cambios. Reserva un nuevo perfil debug, que releases.rs describe como preparación para alejar el perfil dev de la depuración "para dar un valor predeterminado más sensato". Desactiva la compilación incremental cuando la variable de entorno CI está definida, y ByteIOTA señala que CARGO_INCREMENTAL=1 vuelve a activarla. Los miembros de un workspace en la edición 2024 también pueden sobrescribir los valores predeterminados de dependencias heredados.
Qué podría romperse
La versión incluye varios cambios de compatibilidad:
| Cambio | Detalle |
|---|---|
#[no_mangle] en elementos genéricos | Ahora es un error definitivo; generaba una advertencia desde Rust 1.56, según ByteIOTA |
| Módulos de enteros heredados | Ahora totalmente obsoletos |
| Statics externos | Los préstamos ya no se promueven automáticamente a 'static, informa ByteIOTA |
| Bloques de código en comentarios de documentación | Sus atributos deben tener destinos válidos, o la compilación de la documentación falla |
RangeInclusive | Su iteración está mejor optimizada, lo que cambia el comportamiento de un rango ya agotado |
Pin::new_unchecked | Sus reglas de seguridad se detallan con más precisión |
Este es el paso más reciente en un año intenso para el lenguaje. En agosto, Rust estabilizó el tipo never tras diez años, y las builds nightly activaron el solucionador de traits de nueva generación.
Qué significa esto para los desarrolladores
Elimina tus shims de printf. Si escribiste código C, o usaste una función de nightly, solo para aceptar argumentos variádicos de un llamador en C, ahora puedes hacerlo en Rust estable. Los hosts de plugins, los asignadores personalizados y los puentes de registro son los lugares obvios donde mirar.
Revisa el código genérico en busca de #[no_mangle] antes de actualizar. Genera una advertencia desde Rust 1.56, así que un crate que todavía compila con esa advertencia ahora fallará. Busca el atributo en cualquier función genérica de tu código y de tus dependencias vendorizadas.
Vigila los tiempos de compilación de tu CI. Cargo ahora desactiva la compilación incremental cuando CI está definida. Suele ser la decisión correcta para compilaciones limpias, pero una configuración de CI que guarda en caché el directorio target entre ejecuciones puede volverse más lenta. Define CARGO_INCREMENTAL=1 si tus propias mediciones lo indican.
Ejecuta tus pruebas de documentación. Los atributos obsoletos en bloques de código dentro de comentarios de documentación ahora hacen fallar la compilación de la documentación. Ejecuta cargo test --doc pronto para que un ejemplo roto no bloquee una versión.
Prueba el código que reutiliza rangos terminados. El cambio en RangeInclusive solo afecta a los rangos que ya se han iterado hasta el final. El código que sigue usando un rango así después del bucle debe comprobarse frente al nuevo comportamiento.
Fuentes
- Announcing Rust 1.99.0 - Rust Blog
- Rust 1.99.0 Ships with Stable C-Variadic Functions - Linux Compatible
- Rust 1.99 Is Out: C-Variadics and What Breaks - ByteIOTA
- 1.99.0 - releases.rs
Artículos relacionados

La reescritura de mold en Rust aspira a ser el enlazador de Linux
Mold enlaza 4,9 veces más rápido que LLVM lld. Su autor lo está reescribiendo en Rust y quiere que las distribuciones lo instalen como /usr/bin/ld.

Zig 0.17.0 llega con un sistema de compilación dividido y recompilaciones rápidas
Zig 0.17.0 salió el 2 de octubre con 925 commits de 206 colaboradores: un sistema de compilación rediseñado, compilaciones incrementales en Linux x86_64 y LLVM 22.1.8.

Rust 1.100 elimina las herramientas de host para Windows de 32 bits
Rust 1.100 deja de distribuir el compilador para Windows de 32 bits. Los objetivos i686 conservan la biblioteca estándar, así que la compilación cruzada desde Windows de 64 bits sigue funcionando.