Rust activa Polonius Alpha en nightly, su nuevo verificador de préstamos

Fuentes: blog.rust-lang.org, Enabling the next iteration of the borrow checker on nightly | Rust Blog

El equipo de desarrollo del lenguaje de programación Rust ha anunciado la activación de Polonius Alpha, una nueva versión del verificador de préstamos (borrow checker), en su canal nightly. El objetivo es estabilizar esta funcionalidad en los próximos meses y, según sus propias previsiones, antes de que termine el año. Se trata de un paso largamente esperado por la comunidad, dado que el proyecto Polonius nació como una extensión del verificador NLL (Non-Lexical Lifetimes) en 2018 y, aunque su formulación inicial resultó correcta, su rendimiento era demasiado lento para resultar viable.

El sucesor del AST borrowck
Rust cuenta con un sistema de propiedad y préstamos que garantiza la seguridad de memoria sin necesidad de un recolector de basura. El primer verificador de préstamos, conocido como AST borrowck, fue sustituido en 2019 por NLL, una versión más flexible que, sin embargo, realiza un análisis flow-insensitive. Es decir, no distingue entre las distintas rutas de ejecución de un programa a la hora de determinar la vigencia de los préstamos. En 2023, una nueva reformulación del enfoque Polonius abrió la puerta a una implementación que requiere cambios mínimos en NLL y permite aceptar más código válido.

La principal novedad que aporta Polonius Alpha es precisamente el análisis flow-sensitive, lo que en la práctica permite compilar programas que NLL rechaza incorrectamente. El ejemplo más ilustrativo es una función que devuelve o muta una referencia según el resultado de map.get_mut en Rust. Bajo NLL, el compilador asume que el préstamo devuelto vive durante toda la función porque el tipo de retorno es &'r mut V, lo que impide reinsertar un valor en la rama None. Polonius Alpha solventa este caso al comprender que el préstamo no está vivo en esa rama.

Otro ejemplo afectado es la conocida función get_mut_or_default, habitual al trabajar con mapas hash. La comunidad llevaba años encontrando situaciones similares en las que el verificador bloqueaba código que, semánticamente, era correcto.

Rendimiento: pocas regresiones significativas
El equipo reconoce que Polonius Alpha realiza igual o más trabajo que NLL en todos los casos. Para evaluar el impacto, analizaron los 10.000 crates más descargados de crates.io. Los resultados muestran relativamente pocas regresiones significativas. Aunque existen crates que experimentan ralentizaciones considerables, en términos absolutos los incrementos suelen ser mínimos. El peor caso observado fuera del top 10.000 corresponde a crates con muchos préstamos y alcanza una regresión de 2 a 3 veces el tiempo original.

El equipo afirma haber iniciado el triaje de las causas de estas regresiones y estar trabajando en posibles soluciones, aunque consideran que, incluso sin corregirlas, el equilibrio entre potencia adicional y pérdida de rendimiento es razonable.

Limitaciones conocidas
Polonius Alpha no cubre todos los casos que aceptaba la formulación original de Polonius, conocida como legacy Polonius. Un ejemplo típico son las estructuras recursivas tipo X { next: Option> } usadas en listas enlazadas, donde las referencias condicionales siguen sin compilar. Curiosamente, existen programas que compilan con Polonius Alpha pero no con la versión legacy, por lo que ninguna de las dos implementaciones es subconjunto estricto de la otra. Por esta razón se ha elegido el nombre Alpha.

Próximos pasos y desactivación
Hasta que se estabilice la nueva funcionalidad, los usuarios que encuentren problemas pueden reportarlos en el repositorio de GitHub del proyecto o en el canal de Zulip habilitado a tal efecto. Quienes necesiten volver al comportamiento de NLL pueden desactivar Polonius Alpha con el flag -Zpolonius=off, mediante la variable de entorno RUSTFLAGS o en el archivo .cargo/config.toml del proyecto.

Durante los próximos meses, el equipo seguirá monitorizando los informes recibidos, abordará las regresiones conocidas y elaborará documentación interna sobre la implementación. Tras la estabilización, no hay planes concretos para continuar el trabajo de funciones en Polonius a corto plazo, ya que Alpha resuelve los problemas más frecuentes; sin embargo, se espera retomar ese desarrollo en el futuro. Hasta entonces, el foco se desplazará hacia otras prioridades del lenguaje.

En definitiva, Polonius Alpha representa la culminación de un esfuerzo de varios años para ofrecer un verificador de préstamos más potente y expresivo sin sacrificar el rendimiento, consolidando a Rust como un lenguaje que sigue evolucionando para reducir la fricción con sus usuarios.