### Problema: Trait no "dyn compatible" en Rust En Rust, un trait no es "dyn compatible" (antes llamado "object safe") si: - Tiene tipos asociados. - Tiene métodos genéricos. Esto impide usar trait objects como `Box`, ya que Rust necesita saber cómo despachar métodos en tiempo de ejecución y los tipos asociados o métodos genéricos lo hacen imposible[1][2]. ### Solución: Uso de Enum en lugar de Trait Object Cuando un trait no es "dyn compatible", una alternativa común es usar un **enum** que encapsule todas las implementaciones concretas que necesitas manejar. Así evitas las restricciones de los trait objects y puedes seguir usando polimorfismo, pero de manera estática. #### Ejemplo Supón que tienes dos structs que implementan `DatabaseConnection`: ```rust struct PostgresConnection { /* ... */ } struct SqliteConnection { /* ... */ } ``` En lugar de: ```rust trait DatabaseConnection { type Row; fn query(&self, sql: &str) -> T; // método genérico, no object-safe } ``` Define un enum: ```rust enum DatabaseConnectionEnum { Postgres(PostgresConnection), Sqlite(SqliteConnection), } ``` Y luego implementa métodos para el enum que deleguen a cada variante: ```rust impl DatabaseConnectionEnum { fn query(&self, sql: &str) -> T { match self { DatabaseConnectionEnum::Postgres(conn) => conn.query(sql), DatabaseConnectionEnum::Sqlite(conn) => conn.query(sql), } } } ``` ### Ventajas y Desventajas | Opción | Ventajas | Desventajas | |-------------------|-------------------------------------------------|------------------------------------| | Enum | Más rápido (dispatch estático), sin restricciones de object safety[3][4] | Solo puedes manejar variantes conocidas en tiempo de compilación | | Trait Object (`dyn`) | Extensible, permite tipos externos | Más lento (dispatch dinámico), requiere trait object-safe | ### Cuándo usar Enum - Cuando conoces todas las implementaciones posibles en tiempo de compilación. - Cuando necesitas evitar las restricciones de object safety. - Cuando el rendimiento es crítico y quieres evitar el coste de la vtable[3][5]. ### Resumen - Un trait con tipos asociados o métodos genéricos no puede usarse como trait object. - Refactoriza usando un enum que contenga todas las implementaciones concretas. - Implementa métodos en el enum que deleguen a cada variante. - Elige enum si el conjunto de tipos es cerrado y controlado por ti. Esta técnica es común en Rust para evitar los límites de los trait objects y seguir obteniendo polimorfismo estático y eficiente[3][6][5]. Sources [1] Traits - The Rust Reference https://doc.rust-lang.org/reference/items/traits.html [2] Why doesn't Rust support trait objects with associated constants? https://stackoverflow.com/questions/77433184/why-doesnt-rust-support-trait-objects-with-associated-constants [3] Enum or Trait Object - Possible Rust https://www.possiblerust.com/guide/enum-or-trait-object [4] Trait Object or Enum, how to choice - Rust Users Forum https://users.rust-lang.org/t/trait-object-or-enum-how-to-choice/100268 [5] Should I use enums or boxed trait objects to emulate polymorphism? https://stackoverflow.com/questions/52240099/should-i-use-enums-or-boxed-trait-objects-to-emulate-polymorphism [6] Polymorphism in Rust: Enums vs Traits - Matthew Kennedy https://www.mattkennedy.io/blog/rust_polymorphism/ [7] dyn https://doc.rust-lang.org/std/keyword.dyn.html [8] Returning Traits with dyn - Rust By Example https://doc.rust-lang.org/rust-by-example/trait/dyn.html [9] "object safety" is now called "dyn compatibility" : r/rust https://www.reddit.com/r/rust/comments/1i0hwa5/unmentioned_1840_change_object_safety_is_now/ [10] Dyn async traits, part 10: Box box box · baby steps https://smallcultfollowing.com/babysteps/blog/2025/03/24/box-box-box/ [11] Pre-RFC: Object-safe traits with associated types - Rust Internals https://internals.rust-lang.org/t/pre-rfc-object-safe-traits-with-associated-types/7996 [12] trait not dyn compatible when using dyn Trait in ... https://github.com/rust-lang/rust/issues/136744 [13] Trait Objects - The Rust Programming Language - MIT https://web.mit.edu/rust-lang_v1.25/arch/amd64_ubuntu1404/share/doc/rust/html/book/first-edition/trait-objects.html [14] A tour of `dyn Trait` - tutorials https://users.rust-lang.org/t/a-tour-of-dyn-trait/97053 [15] dyn Trait implementations - Learning Rust https://quinedot.github.io/rust-learning/dyn-trait-impls.html [16] Trait objects do not work with generic associated types #81823 https://github.com/rust-lang/rust/issues/81823 [17] Why is `Sized` trait not allowed in dyn MyTrait? https://users.rust-lang.org/t/why-is-sized-trait-not-allowed-in-dyn-mytrait/125323 [18] Understanding trait object safety - return types - Rust Users Forum https://users.rust-lang.org/t/understanding-trait-object-safety-return-types/73425 [19] Enum or Trait Object : r/rust - Reddit https://www.reddit.com/r/rust/comments/hz5iwm/enum_or_trait_object/ [20] Any alternatives to dyn when your trait is not object-safe? https://stackoverflow.com/questions/77582616/any-alternatives-to-dyn-when-your-trait-is-not-object-safe