Saltar al contenido

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.

Por Tech AI Wire Team

4 min de lectura

XLinkedIn
Screenshot of the Rust Blog post 'Announcing Rust 1.99.0', dated October 1, 2026, from the Rust Release Team.

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:

ÁreaCambio
PlataformasLinux RISC-V de 64 bits con musl sube al soporte Tier 2
EnlazadoLos ejecutables estáticos independientes de la posición se habilitan en los targets GNU y musl
RustdocFiltrar implementaciones de traits es alrededor de un 20 % más rápido de media, hasta un 40 % en algunos crates
MacrosLas macros de atributo ahora funcionan en módulos definidos en un archivo aparte, como #[my_macro] mod foo;
Ensamblador en líneaLos 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:

CambioDetalle
#[no_mangle] en elementos genéricosAhora es un error definitivo; generaba una advertencia desde Rust 1.56, según ByteIOTA
Módulos de enteros heredadosAhora totalmente obsoletos
Statics externosLos préstamos ya no se promueven automáticamente a 'static, informa ByteIOTA
Bloques de código en comentarios de documentaciónSus atributos deben tener destinos válidos, o la compilación de la documentación falla
RangeInclusiveSu iteración está mejor optimizada, lo que cambia el comportamiento de un rango ya agotado
Pin::new_uncheckedSus 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

  1. Announcing Rust 1.99.0 - Rust Blog
  2. Rust 1.99.0 Ships with Stable C-Variadic Functions - Linux Compatible
  3. Rust 1.99 Is Out: C-Variadics and What Breaks - ByteIOTA
  4. 1.99.0 - releases.rs

Artículos relacionados