El `!` de Rust no es el bottom type: es el empty type, y hay diferencias prácticas
Rust permitirá usar `!` en cualquier anotación de tipo desde la 1.100, pero el tipo vacío no se comporta como el fondo: sin subtipos, la coerción falla en contextos anidados.
Hace un par de semanas, Rust aceptó el tipo vacío ! en todas las anotaciones de tipo, no solo como retorno de funciones. El pull request se fusionó el 25 de agosto de 2026 y llegará en la versión 1.100. La novedad trae consigo una confusión recurrente: ¿! es el bottom type o el empty type? Un artículo de ettolrach explica que no son lo mismo, y que en Rust la diferencia se nota en el código.
El tipo vacío (!) no tiene valores ni constructores. Para construir cualquier otro tipo desde él se usa una función absurd, que toma un ! y devuelve lo que quieras. El bottom type también está vacío, pero en lugar de absurd se apoya en el subtipado: es subtipo de todos los tipos, así que un valor de tipo fondo puede usarse donde se espere cualquier otro tipo. La clave es que el subtipado exige una relación de subtipos en el lenguaje; Rust solo tiene subtipos relacionados con lifetimes, así que no puede tener bottom type. ! es el empty type.
¿Qué implica esto en la práctica? Scala, con subtipos, define Nothing como fondo. En Scala puedes asignar una función que devuelve Nothing a una que devuelve Int sin más. En Rust, cuando ! aparece como tipo de retorno de un puntero a función, la coerción implícita no se aplica si está anidado en otro tipo. El compilador rechaza esto:
fn f() -> fn(i32) -> ! { |_| panic!() }
fn g() -> fn(i32) -> i32 { f() }
Da el error E0308, porque fn(i32) -> ! no se convierte a fn(i32) -> i32. Es necesario desempaquetar el ! explícitamente, como en:
fn g() -> fn(i32) -> i32 {
|x| {
let never: ! = f()(x);
never
}
}
Aquí la coerción ocurre en la asignación a never. No es menos potente que Scala, solo más incómodo. La diferencia es real y práctica.
El origen de la confusión, apunta el autor, está en Wikipedia: las páginas de bottom type y empty type sugieren que en sistemas de tipos sólidos no hay distinción, pero omiten que el fondo requiere subtipado. La página de empty type ni siquiera menciona los subtipos.
Para quien trabaje con Rust, este matiz importa: cuando definas funciones que devuelven !, recuerda que no son intercambiables con otros tipos si van dentro de una firma más grande. La buena noticia es que el propio compilador te avisará con un error claro.
