Cómo va nuestra reescritura de Rust a Zig

Un artículo extenso sobre la reescritura del compilador del lenguaje Roc de Rust a Zig ha impulsado un examen más amplio de las concesiones entre seguridad, rendimiento y tooling en los lenguajes de sistemas. Los comentaristas contrastan las fuertes garantías estáticas y el ecosistema maduro de Rust con las compilaciones incrementales extremadamente rápidas de Zig, su control de memoria de grano fino y su inestabilidad pre‑1.0, debatiendo si siquiera es viable añadir a Zig un borrow checking similar al de Rust. El hilo también profundiza en cuánta “seguridad de memoria” pueden ofrecer realisticamente los compiladores y runtimes, el papel de la recolección de basura y los schedulers en lenguajes como Go, y cuándo está justificado aceptar más código `unsafe` a cambio de rendimiento o ergonomía.

Rust vs Zig para la implementación de compiladores

  • Muchos coinciden en que las compilaciones incrementales de Zig (p. ej., reconstrucciones de ~35 ms) son un gran atractivo para el trabajo en compiladores; Rust se percibe como más lento, aunque está mejorando, con una hoja de ruta oficial para compilaciones más rápidas.
  • Algunos señalan que en el compilador actual de Roc, las compilaciones completas todavía pueden ser más lentas en Zig que en Rust; otros enfatizan que la arquitectura de Zig está optimizada para el rendimiento futuro.
  • Varios sostienen que la elección del lenguaje importa menos que los algoritmos y las estructuras de datos, aunque otros replican que el control de bajo nivel sobre memoria/disposición puede producir mejoras de un orden de magnitud una vez que los algoritmos están fijados.

Seguridad de memoria, unsafe y borrow checking

  • Fuerte debate sobre si añadir a Zig un borrow checker al estilo de Rust (mediante análisis estático o herramientas de IR) es viable:
    • Un lado: “imposible” o muy poco ergonómico sin diseño de lenguaje consciente de lifetimes, traits, encapsulación y expresividad restringida.
    • El otro lado: cita herramientas, analizadores personalizados y ejemplos (Ada/SPARK, proyectos tipo Oxide) como evidencia de que una seguridad adicional puede “añadirse encima”, aunque con coste y falsos positivos.
  • Discusión sobre límites fundamentales: el análisis de aliasing y de seguridad temporal se vuelve indecidible en general; Rust resuelve esto restringiendo la expresividad (propiedad afín/lineal).
  • El modo ReleaseSafe de Zig y los allocators de depuración ofrecen comprobaciones de límites, detección de fugas, detección de double-free / cierta detección de UaF usando direcciones no reutilizadas, pero no una seguridad temporal completa.
  • Muchos subrayan que “memory safe” en Rust es una garantía específica y limitada; el Rust seguro aún puede generar código incorrecto o ser inseguro debido a errores del compilador (p. ej., CVEs teóricas).

Qué significa “seguridad” y dónde encajan los compiladores

  • Larga subdiscusión que distingue entre:
    • Seguridad de memoria (objetiva, formalizable).
    • “Seguridad” en sentido amplio (dependiente del contexto: seguridad, corrección, seguridad humana).
  • Algunos argumentan que la seguridad es una propiedad del sistema, no del lenguaje; un compilador seguro aún puede emitir binarios vulnerables.
  • Otros replican que las garantías a nivel de componente siguen siendo valiosas: reducir la superficie unsafe hace más manejables la depuración, el sandboxing y los límites de confianza.
  • Debate sobre si los compiladores son “sensibles a la seguridad”:
    • Una postura: los compiladores no están endurecidos contra entradas maliciosas (p. ej., el modelo declarado de LLVM); el UB en compiladores es “solo otro bug”.
    • Postura opuesta: los compiladores son raíces críticas de confianza; los exploits de memoria en ellos pueden inyectar código en todos los binarios derivados.

Runtime y planificación de Go

  • Un comentarista afirma que el scheduler de Go es “el más sofisticado del mundo” y puede superar a Rust en throughput al intercambiar memoria por concurrencia.
  • Varias respuestas cuestionan esto por exagerado y poco consistente con la experiencia y los benchmarks, señalando sistemas de alto rendimiento que terminan optimizando la memoria manualmente de todos modos.
  • Otros mencionan runtimes competidores (JVM, CLR, Erlang) y que la teoría de scheduling es profunda; la afirmación se considera en general no sustentada.

Tiempos de compilación, cachés y tooling

  • Las compilaciones lentas de Rust y los grandes directorios de artefactos son una queja recurrente; algunos proyectos ven compilaciones incrementales de varios minutos debido al uso intensivo de genéricos y macros/generación de código (p. ej., algunas pilas GraphQL).
  • Sugerencias:
    • Usar directorios target compartidos/globales y herramientas como sccache.
    • El equipo de Cargo está rediseñando el diseño de artefactos para habilitar recolección de basura y mejor gestión de caché.
  • El equipo de Zig explica que, para ediciones pequeñas, el coste de la reconstrucción incremental está dominado por el recorrido del grafo de dependencias y la detección de cambios, no por la generación de código, así que el rendimiento debería ser similar entre arquitecturas.

Madurez de Zig, cambios incompatibles y “listo para producción”

  • Tensión en torno al estado pre‑1.0 de Zig:
    • Defensores: en la práctica está “listo para producción”; la etiqueta pre‑1.0 principalmente preserva la libertad de hacer cambios incompatibles frecuentes. Se citan usuarios de producción exitosos.
    • Críticos: los cambios incompatibles frecuentes en el núcleo (p. ej., APIs de E/S) hacen que no esté listo para la mayoría de los equipos de producción; argumentan a favor de semver o esquemas de edición adecuados en lugar de una ruptura abierta.
  • Algunos prefieren el enfoque de Zig (volatilidad honesta) frente a lenguajes conservadores y de acumulación pesada; otros insisten en la estabilidad a largo plazo para despliegues serios.

Elección de lenguaje, GC y rendimiento

  • Discusión sobre OCaml y otros lenguajes gestionados/FP para compiladores: históricamente exitosos, existen compiladores muy rápidos; algunos creen que la suposición de Roc de “debe ser un lenguaje de sistemas” es demasiado fuerte.
  • Contraargumento: las CPUs modernas y las características del lenguaje (p. ej., asignación sofisticada de closures) cambian las restricciones; el control fino sobre la disposición y la asignación puede importar mucho.
  • Debate más amplio sobre GC:
    • Algunos sostienen que el rechazo al GC está exagerado y que la mayoría de los servicios reales podrían tolerar GCs modernos.
    • Otros describen sistemas de alto throughput / baja latencia donde los parones de escala de µs importan y las pausas del GC (incluso las de “baja latencia”) son inaceptables, así que el GC queda descartado.

Reacciones al lenguaje Roc y preguntas abiertas

  • Varios comentaristas encuentran Roc interesante pero no están seguros de su nicho objetivo y casos de uso (scripting, plugins frente a lenguaje para apps servidor/cliente; competencia frente a WASM, Gleam, Elm).
  • A algunos les gustan el pattern matching de Roc y los patrones de cadenas sin asignación, pero señalan un bug sutil en un ejemplo de enrutamiento y se preocupan por semánticas delicadas con barras diagonales incrustadas.
  • Comentario menor sobre estilo: las líneas separadas de anotación de tipos resultan incómodas para algunos en comparación con la sintaxis al estilo F#.

Cultura, reescrituras y subhilos de AI/Bun

  • Algunos ven surgir una ola de ruido de “reescribir Rust a X” y advierten contra el tribalismo de lenguajes; otros enfatizan el “herramienta adecuada para el trabajo” y aceptan reescrituras cuando cambia la adecuación al dominio.
  • Una comparación breve con la reescritura de otro proyecto de Zig a Rust provoca bromas sobre un “UNO reverse”, pero también plantea preguntas sobre la sostenibilidad a largo plazo de ecosistemas pre‑1.0.
  • Un hilo pregunta por qué una gran empresa de IA adquirió un proveedor de runtime de JavaScript en lugar de simplemente hacer un port; las respuestas se centran en el riesgo de fracaso de una startup, el control estratégico y las motivaciones de acquihire.