El 15 de julio de 2026, Richard Feldman, creador del lenguaje de programación Roc, publicó una entrada técnica anunciando que, tras 487 días, habían reescrito 300.000 líneas de Rust en Zig. El tiempo de build incremental del compilador bajó de 3,4 segundos a 35 milisegundos —cien veces más rápido.
No es un caso aislado. Antes, el compilador del lenguaje Gleam recorrió el mismo camino: de Rust a Zig. Y a la inversa, el runtime Bun completó a comienzos de 2026 la operación contraria —de Zig a Rust—, en solo 11 días.
Dos grupos de desarrolladores de compiladores de primer nivel, en sentidos opuestos, tomaron decisiones contrarias. Cuando algo tiene defensores y detractores que votaron con código real, sabes que detrás hay un problema de balanza.

¿Qué significan realmente esos 35 milisegundos?
3,4 segundos ya es rápido. He escrito bastantes proyectos en Rust, he visto cargo check tardar dos o tres segundos y a rust-analyzer zumbando en segundo plano —a decir verdad, uno se acostumbra—. La velocidad de compilación de Rust ha avanzado muchísimo en los últimos 18 meses; Rust 1.97 recortó dos tercios del tiempo de build incremental respecto a 1.85. El propio Feldman elogia sinceramente ese esfuerzo del equipo de Rust en su artículo.
Pero 35 milisegundos es de otra especie.
35 milisegundos significa que en el instante en que pulsas Ctrl+S —antes de levantar el dedo del teclado— el compilador ya te ha dado el resultado. Eso es el bucle de retroalimentación desaparece. mlugg, miembro del equipo de Zig, describió en Lobsters esta experiencia con un detalle: cada build incremental le toma unos 30 milisegundos, de los cuales el enlazador ocupa apenas 1 milisegundo. Porque el nuevo enlazador ELF de Zig está diseñado para el enlazado incremental a nivel de función individual —modificas una función, el compilador genera el nuevo código máquina y el enlazador sobrescribe directamente la posición del código viejo dentro de la sección .text del archivo de salida. Sin syscall, porque el archivo de salida está mapeado en memoria con mmap.
Esta «espera cero» cambia la relación del desarrollador con el compilador. Ya no necesitas acumular un lote de cambios para lanzar un build; puedes probar y retroceder rápidamente entre modificación y feedback —usar un lenguaje compilado como si fuera interpretado—. La nueva versión del compilador de Roc incluso soporta carga de código en caliente: un servidor en ejecución puede cambiar automáticamente al código modificado sin reiniciar el proceso. En el mundo Python eso es estándar; en el de los lenguajes compilados, es un lujo.
Entonces, ¿qué «cuesta» realmente la seguridad de tipos de Rust?
Si 35 milisegundos es el dulce de Zig, ¿qué tan cara es la «tasa de seguridad» que cobra Rust? Hay que desglosarlo.
Cuenta uno: tiempo de compilación. El borrow checker de Rust hace en tiempo de compilación algo sumamente caro —demuestra que tu programa no tiene use-after-free, ni double-free, ni data races—. Ese proceso de prueba debe recorrer todo el grafo de relaciones de referencia, con una complejidad que crece superlinealmente con el tamaño del código. La compilación incremental de Rust mejora, pero la esencia del borrow checker imposibilita un «listo al instante» como el de Zig.
Cuenta dos: libertad de arquitectura. El compilador de Roc usa profusamente asignadores de arena (arena allocators) y disposición struct-of-arrays —todas las estructuras de datos usan índices de 32 bits en lugar de punteros, partidos en arrays independientes por campo—. Este estilo vuela en CPUs modernas y permite mapear directo a disco para una «deserialización sin parseo» —la segunda vez que corres roc check, todas las estructuras ya parseadas saltan del disco a la memoria a velocidad cercana a memcpy.
Pero el problema es: este estilo de programación choca casi inevitablemente con el borrow checker de Rust. El patrón arena+índices elude el sistema de ownership de Rust, lo que significa que tu proporción de unsafe será muy superior a la de un proyecto Rust típico. El equipo de Feldman tenía unas 1.200 apariciones de unsafe en 300.000 líneas de Rust —un orden de magnitud por encima de la densidad de unsafe del propio compilador rustc. Cuando el unsafe pasa de «rincón minoritario que auditar» a «norma por todos lados», la sensación de seguridad que da el borrow checker se resiente.
Los libros de ambos bandos: los números mienten, y también dicen la verdad
Feldman hizo algo muy honesto: contabilizó los bugs de corrupción de memoria en ambas versiones del compilador.
Versión Rust: 21. Versión Zig: 10.
A primera vista, gana Zig. Pero al desglosar —los 21 bugs de la versión Rust eran todos miscompilation (el compilador generó código máquina incorrecto), ninguno en la lógica del propio compilador. El borrow checker hizo bien su trabajo—. De los 10 de Zig, 8 también eran miscompilation, y los 2 restantes eran use-after-free —ambos en el lugar donde el reporte de error renderiza el nombre de archivo, con el síntoma de que el nombre salía como basura.
La conclusión de Feldman es serena hasta sorprender: «mirando atrás a 18 meses de desarrollo, cientos de reportes de bug y cientos de miles de líneas, mi impresión principal es: da igual cuál elijas». Esos 2 use-after-free, el borrow checker de Rust los habría parado y el modo ReleaseSafe de Zig hace panic en runtime —pero el impacto real de las tres opciones fue «dos reportes de bug: ciertos mensajes de error no mostraban el nombre de archivo».
Esta conclusión contrasta sutilmente con la del equipo de Bun. Al migrar de Zig a Rust, Bun enfatizó que, para proyectos que deben gestionar a la vez valores GC de JavaScript y memoria manual, el use-after-free es «una gran fuente de bugs». Feldman está totalmente de acuerdo —y añade que el compilador de Roc no necesita interoperar con JavaScript.
La clave no está en quién tiene la razón. La clave es: el contexto lo decide todo.

La fisura de la comunidad: esto no es una guerra santa
Esta entrada sumó 175 puntos y 62 comentarios en Lobsters, y también provocó debate intenso en Hacker News. Pero lo más notable es que ambos bandos trajeron argumentos fundamentados, de primera línea.
Ralf Jung, miembro del equipo central de Rust, señaló un problema en el dato «rustc tiene 40.000 apariciones de unsafe» que citaba Feldman —esa cifra incluye la biblioteca estándar, los tests y los comentarios; el unsafe real en el compilador es muy inferior—. Y reconoció: «estoy totalmente de acuerdo en que el Rust unsafe es difícil de escribir bien, es algo que me preocupa mucho».
llogiq —autor del crate compact_arena— señaló que el sistema de etiquetas de tipos de Rust puede distinguir en tiempo de compilación los índices de distintas arenas, evitando el problema de «usar el array equivocado». Pero admitió que esta técnica falla cuando el número de arenas es desconocido en tiempo de compilación.
aapoalas —un usuario de Rust que se describe como «fanático del diseño orientado a datos»— expresó la típica actitud ambivalente: «como fanático del diseño orientado a datos y usuario empedernido de Rust, duele ver a un proyecto afín abandonar Rust». Luego enumeró sus propios intentos de lograr optimizaciones similares en Rust, con un tono de honesta «falta que no se quiera rendir».
Creo que lo sano de esta discusión es que nadie llamó tonto al otro. Nadie dijo «elegir Rust es no entender rendimiento» ni «elegir Zig es no importarle la seguridad». Todos admiten que es una compensación real —y eligen distinto según el contexto de su proyecto.
Una lid más profunda: comptime frente a proc macro
Tras el juego de números de la velocidad de compilación hay una divergencia filosófica más sabrosa: ¿cómo hacer metaprogramación en tiempo de compilación?
La apuesta de Zig es comptime —escribes Zig normal y corriente, solo marcas que se ejecute en tiempo de compilación. Es como un intérprete embebido en el compilador, que hace que la programación genérica, la generación de código y la manipulación de tipos sean tan naturales como escribir código en runtime. Sin una segunda sintaxis, sin manipular token trees, sin las manías de los macros higiénicos.
La apuesta de Rust es proc macro —un programa Rust independiente que se ejecuta en tiempo de compilación, recibe un flujo de tokens, los manipula y emite un flujo de tokens. Es enormemente potente (en teoría puedes hacer cualquier cosa), pero también enormemente pesado. Cada proc macro es un crate independiente, y compilarlo ya lleva tiempo. El comptime de Zig se integra en el mismo proceso de compilación, con casi nula sobrecarga.
Esta es una razón oculta de por qué Zig compila rápido: no necesita compilar primero un sistema de macros y luego tu código. La metaprogramación y el programa principal comparten la misma tubería del compilador. Feldman escribe en el artículo: «me gusta que Zig no tiene macros» —aislada suena a queja, pero en contexto expresa una estética de resta: un mecanismo menos, una capa de abstracción menos, una carga de compilación menos.
Claro, restar significa perder. Feldman admite que echa de menos el sistema de trait y los campos privados de Rust. Esas son capacidades expresivas que Rust compró con sumas. Elegir Zig es aceptar que «simple» importa más que «expresividad» —al menos para los proyectos a los que la velocidad de compilación les va la vida.
Mi lectura: el pez y el oso, pero puedes elegir plato
Este no es un artículo que tome partido. Mi sensación tras el análisis es: la relación entre Rust y Zig está pasando de «cuál es mejor» a «cuál es más adecuado para qué».
Si tu proyecto es como un servidor web o una base de datos —estructura de código estable, unsafe concentrado en pocos puntos calientes, y lo que necesitas es la confianza a largo plazo del borrow checker— Rust sigue siendo hoy la opción más segura.
Si tu proyecto es como un compilador —código que hay que refactorizar e iterar a menudo, unsafe por todos lados, y la velocidad de compilación marca directamente tu ritmo de pensamiento— Zig se está volviendo una opción que no puedes ignorar. Porque en ese escenario, el precio de la seguridad se tarifa distinto.
Lo que el equipo de Roc hizo fue redefinir el tipo de seguridad que necesitaban. Sus problemas de memoria salían sobre todo del código máquina generado, no del propio compilador —y el borrow checker no alcanza a lo primero. Cuando el cuello de botella de la seguridad queda fuera de lo que el lenguaje garantiza, pagar con tiempo de compilación por eso se vuelve discutible.
La distancia entre 35 milisegundos y 3,4 segundos es, en el fondo, la materialización de dos filosofías de desarrollo: una cree que la máquina puede demostrar todo en tiempo de compilación; otra cree que el desarrollador puede gestionar todo en runtime. Ninguna es perfecta —pero al menos hoy, los desarrolladores tienen opciones verdaderamente distintas.
Puede que esta sea la mejor noticia de la programación de sistemas en años recientes.
Enlaces de referencia:
- Richard Feldman: How Our Rust-to-Zig Rewrite is Going (15 de julio de 2026)
- Discusión en Lobsters: How Our Rust-to-Zig Rewrite is Going (175 puntos / 62 comentarios)
- Equipo de Bun: Why We’re Rewriting Bun from Zig to Rust (2026)
- Registro de desarrollo oficial de Zig: Incremental Compilation Demo
- FAQ de Gleam: Why Rust for the compiler?