⏱️ Lectura: 11 min

El equipo de Rust anunció oficialmente la liberación de Rust 1.86, una versión que consolida una de las funcionalidades más esperadas desde los primeros días del lenguaje: el trait upcasting. Tras casi seis años de discusión en el repositorio oficial, Rust 1.86 permite convertir referencias dyn Trait en referencias a sus supertrait, abriendo patrones de polimorfismo que la comunidad venía solicitando desde la estabilización de 1.0. Junto al upcasting, la versión estabiliza APIs de la biblioteca estándar, ajusta políticas de plataformas soportadas y afina garantías numéricas que impactan directamente en código de sistemas y seguridad.

📑 En este artículo
  1. Qué pasó: Rust 1.86 ya está disponible
  2. Trait upcasting: la feature estrella de Rust 1.86
  3. Mejoras prácticas en la biblioteca estándar
    1. #[target_feature] en funciones seguras
  4. Contexto e historia: diez años de Rust estable
  5. Datos y cifras del lanzamiento
  6. Impacto y análisis: qué significa para la industria
  7. Flujo de actualización recomendado
  8. Qué sigue en la hoja de ruta
  9. Preguntas frecuentes
    1. ¿Rust 1.86 rompe código existente?
    2. ¿Qué es exactamente el trait upcasting?
    3. ¿Cómo actualizo a Rust 1.86?
    4. ¿Se elimina algún API conocido?
    5. ¿Qué pasa con los targets Tier 3?
    6. ¿Rust 1.86 cambia el rendimiento de mi código?
  10. Referencias

Qué pasó: Rust 1.86 ya está disponible

La Fundación Rust liberó la versión 1.86.0 el 3 de abril, cumpliendo con el ciclo de seis semanas que el proyecto mantiene de forma estricta desde la versión estable 1.0 publicada en mayo de 2015. La distribución se realizó a través del gestor de toolchain rustup, que permite actualizar con un único comando: rustup update stable. La versión quedó disponible inmediatamente para las plataformas de soporte Tier 1 del proyecto —Linux, macOS y Windows— más decenas de arquitecturas Tier 2 y Tier 3, incluyendo embebidos como thumbv7em-none-eabi y WebAssembly.

El anuncio oficial en el blog de Rust destaca tres ejes principales: la estabilización de trait upcasting, un conjunto de nuevas APIs en la biblioteca estándar (entre ellas HashMap::get_disjoint_mut y Vec::pop_if), y cambios de política en plataformas soportadas, con la degradación de i586-pc-windows-msvc de Tier 2 a Tier 3. También se incorporan mejoras en el borrow checker, diagnósticos más precisos del compilador y ajustes en cargo para manejar mejor los workspaces.

💭 Clave: El trait upcasting es la feature que la comunidad de Rust llevaba esperando más tiempo en la historia del lenguaje: casi seis años entre el RFC inicial y su estabilización definitiva.

Trait upcasting: la feature estrella de Rust 1.86

Hasta la versión 1.85, si se tenía un valor dyn Subtrait y se necesitaba pasarlo a una función que esperaba dyn Supertrait, el compilador lo rechazaba. La única alternativa era crear un método as_super manualmente en cada trait, una receta boilerplate que cualquier programador con experiencia en Rust ha escrito al menos una vez.

Con Rust 1.86, el lenguaje permite realizar esta conversión directamente. El compilador se encarga de generar la vtable correcta y la conversión ocurre en tiempo constante, sin costo adicional en runtime. Un ejemplo sencillo:

trait Animal {
    fn name(&self) -> &str;
}

trait Dog: Animal {
    fn bark(&self);
}

fn print_name(animal: &dyn Animal) {
    println!("Se llama {}", animal.name());
}

fn main() {
    let my_dog: Box<dyn Dog> = Box::new(Poodle);
    // En Rust 1.86 esto compila sin boilerplate:
    let as_animal: &dyn Animal = &*my_dog;
    print_name(as_animal);
}

La importancia va más allá de la ergonomía. Frameworks que dependen de jerarquías dinámicas —sistemas GUI, motores de juego, plataformas de plugins— podrán simplificar enormemente su código interno. Bibliotecas como bevy, druid o slint ya han empezado a discutir cómo refactorizar sus APIs para aprovechar esta capacidad.

Código Rust 1.86 mostrando trait upcasting en acción
Trait upcasting simplifica jerarquías dinámicas en sistemas grandes.

Mejoras prácticas en la biblioteca estándar

Además del upcasting, Rust 1.86 estabiliza APIs que resuelven dolores de cabeza cotidianos. La más celebrada es HashMap::get_disjoint_mut, que permite obtener múltiples referencias mutables a entradas distintas de un mismo mapa. Antes, el borrow checker lo prohibía —y con razón—, ya que dos referencias mutables simultáneas al mismo dato violan las reglas de aliasing de Rust. La nueva API acepta un arreglo de claves y devuelve un arreglo de Option<&mut V>, garantizando en tiempo de ejecución que las claves sean distintas.

Otra adición útil es Vec::pop_if, que combina la lectura condicional con la eliminación del último elemento en una sola operación. El método acepta un closure y solo elimina el elemento si el predicado devuelve true:

let mut numbers = vec![1, 2, 3, 4, 5];
let popped = numbers.pop_if(|last| *last == 5);
assert_eq!(popped, Some(5));
assert_eq!(numbers, vec![1, 2, 3, 4]);

Se estabilizaron también f32::midpoint y f64::midpoint, que calculan el punto medio entre dos números flotantes sin el riesgo de overflow intermedio que tendría la fórmula naive (a + b) / 2. Es un detalle pequeño, pero crítico para cálculos numéricos, binary search con flotantes y algoritmos de geometría computacional donde la pérdida de precisión o los desbordamientos pueden introducir bugs sutilísimos.

#[target_feature] en funciones seguras

Rust 1.86 también habilita el uso de #[target_feature] en funciones safe bajo ciertas condiciones. Hasta ahora, cualquier función con ese atributo debía marcarse unsafe porque invocarla en hardware sin esas instrucciones causaría undefined behavior. Con la nueva regla, el compilador puede inferir que una función marcada con ese atributo solo se llame desde otras funciones con el mismo atributo, eliminando la obligación de unsafe en cadenas de llamadas internas. Esto beneficia a crates de bajo nivel como simd-json o bytemuck.

Contexto e historia: diez años de Rust estable

Rust cumplió una década como lenguaje estable el 15 de mayo de 2025, apenas seis semanas después del lanzamiento de la versión 1.86. Desde 1.0, el proyecto ha mantenido un compromiso estricto de retrocompatibilidad: código que compilaba en 2015 debería seguir compilando hoy, salvo bugs de soundness corregidos con períodos de transición amplios. La versión 1.86 sigue esa tradición; ninguno de los cambios introduce rupturas para código estable existente.

El trait upcasting tiene una historia particularmente larga. El RFC original fue abierto en 2019 y pasó por múltiples iteraciones de diseño. Dos veces se estuvo cerca de estabilizar, y en ambas ocasiones se detectaron unsoundness en la implementación que forzaron a regresar a la mesa de diseño. Esta vez, el equipo de tipos (T-types) del proyecto validó el modelo completo usando a-mir-formality, el sistema de verificación formal que Rust ha estado construyendo para su especificación.

El crecimiento del ecosistema también contextualiza el momento: crates.io superó los 170.000 crates publicados en 2025, y Rust lleva nueve años consecutivos liderando la encuesta anual de Stack Overflow como el lenguaje “más querido” por los desarrolladores.

Datos y cifras del lanzamiento

  • Fecha oficial de lanzamiento: 3 de abril, siguiendo el ciclo de seis semanas desde Rust 1.85 (20 de febrero).
  • Contribuciones a esta release: más de 3.000 commits provenientes de alrededor de 280 contribuidores distintos.
  • APIs estabilizadas: 12 nuevas APIs pasan de nightly a stable, incluyendo HashMap::get_disjoint_mut, Vec::pop_if, {float}::midpoint y variantes relacionadas.
  • Plataformas Tier 1: se mantienen las tres tradicionales —x86_64-unknown-linux-gnu, x86_64-pc-windows-msvc, x86_64-apple-darwin— más las versiones aarch64.
  • Adopción empresarial: compañías como Microsoft, Amazon, Google y Cloudflare continúan expandiendo su uso de Rust en componentes críticos de infraestructura.
💡 Tip: Antes de actualizar en producción, ejecuta cargo clippy --all-targets con la nueva toolchain. Rust 1.86 incluye lints mejorados que pueden detectar oportunidades reales de usar trait upcasting y pop_if en código existente.

Impacto y análisis: qué significa para la industria

Para proyectos que usan Rust en producción, Rust 1.86 es una actualización conservadora pero valiosa. No rompe código existente y añade herramientas que reducen boilerplate. Para los frameworks que exponen jerarquías de traits dinámicos, el trait upcasting elimina patrones workaround que llevaban años documentados como “así se hace en Rust, aunque no sea elegante”. Es probable que en los próximos seis a doce meses veamos versiones mayores de bibliotecas populares incorporando estas mejoras en sus APIs públicas.

Para desarrolladores que empiezan con Rust, la curva de aprendizaje se suaviza un poco más. Uno de los puntos de confusión recurrentes en principiantes era exactamente el comportamiento de dyn Trait con jerarquías. Ahora el comportamiento coincide con la intuición: si Dog es Animal, entonces &dyn Dog puede usarse donde se espera &dyn Animal, sin código de pegamento.

En el plano de seguridad, la expansión del atributo #[target_feature] a funciones seguras reduce el área de código marcado unsafe en crates SIMD y criptográficos. Eso facilita auditorías y reduce la superficie de error humano: menos unsafe escrito manualmente significa menos oportunidades de introducir bugs de memoria en zonas críticas.

Desarrolladores trabajando con Rust 1.86 en equipo
Rust 1.86 mantiene el compromiso de estabilidad tras una década.

Flujo de actualización recomendado

graph LR;
    A[cargo check actual] --> B[rustup update stable];
    B --> C[cargo build];
    C --> D{¿warnings nuevos?};
    D -->|Sí| E[cargo clippy --fix];
    D -->|No| F[Listo para release];
    E --> F;

El equipo de Rust recomienda siempre seguir la secuencia: probar con la toolchain nueva en una rama dedicada, correr clippy con los nuevos lints, validar que la suite de tests pase y finalmente actualizar en main. Proyectos con dependencias sensibles deberían además verificar que sus crates directas sean compatibles con la nueva MSRV si aplican políticas estrictas.

Qué sigue en la hoja de ruta

Con el trait upcasting completado, la atención del equipo de tipos se desplaza a otros dos grandes pendientes: el soporte completo de async closures estables —actualmente en nightly bajo la feature gate correspondiente— y la evolución de async fn en traits, que en 1.75 se estabilizó parcialmente pero aún deja fuera casos dinámicos. Se espera que versiones posteriores vayan cerrando ese hueco progresivamente.

En el frente de herramientas, rust-analyzer ya incorpora soporte completo para el upcasting, lo que significa que IDEs como VS Code, RustRover y Helix mostrarán la conversión como parte de las sugerencias automáticas. Cargo continúa trabajando en el soporte estable para scripts de un solo archivo (-Zscript), una funcionalidad que reduciría significativamente la fricción para prototipos rápidos.

La edición 2024, estabilizada en Rust 1.85, sigue siendo el foco de limpieza sintáctica del ecosistema. Equipos que aún usan la edición 2021 pueden migrar con cargo fix --edition, y la mayoría de las ventajas de nuevas versiones como 1.86 funcionan independientemente de la edición elegida.

📖 Resumen en Telegram: Ver resumen

Preguntas frecuentes

¿Rust 1.86 rompe código existente?

No. Rust mantiene su garantía de retrocompatibilidad estable. Cualquier código que compile en 1.85 seguirá compilando en 1.86. Los únicos cambios potencialmente incompatibles afectan a plataformas degradadas a Tier 3, no al lenguaje en sí.

¿Qué es exactamente el trait upcasting?

Es la capacidad de convertir una referencia dyn Subtrait en una referencia dyn Supertrait cuando existe la relación supertrait. Antes de Rust 1.86 esto requería métodos manuales; ahora el compilador lo hace automáticamente con cero costo en runtime.

¿Cómo actualizo a Rust 1.86?

Con el comando rustup update stable. Si usás una toolchain específica por proyecto vía rust-toolchain.toml, actualizá el archivo a channel = "1.86" o "stable".

¿Se elimina algún API conocido?

No se elimina nada. HashMap::get_many_mut, que era nightly, se renombró a get_disjoint_mut al estabilizarse. Si lo usabas en nightly, el nombre anterior queda deprecado pero disponible como alias.

¿Qué pasa con los targets Tier 3?

Los targets Tier 3 como i586-pc-windows-msvc siguen disponibles pero sin garantías oficiales: no corren la suite completa de tests del proyecto, y los breakages pueden ocurrir sin aviso. Si tu proyecto depende de ese target, considerá migrar a i686-pc-windows-msvc.

¿Rust 1.86 cambia el rendimiento de mi código?

Para la mayoría de código no hay cambios medibles. Los programas que usen intensivamente los nuevos APIs podrían ver mejoras marginales al eliminar llamadas virtuales o código de pegamento. Se recomienda medir con benchmarks reales antes y después.

Referencias

📱 ¿Te gusta este contenido? Únete a nuestro canal de Telegram @programacion donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.

Categorías: Programación

0 Comentarios

Deja un comentario

Marcador de posición del avatar

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.