- Add complete dark mode system with theme context and toggle - Implement dark mode toggle component in navigation menu - Add client-side routing with SSR-safe signal handling - Fix language selector styling for better dark mode compatibility - Add documentation system with mdBook integration - Improve navigation menu with proper external/internal link handling - Add comprehensive project documentation and configuration - Enhance theme system with localStorage persistence - Fix arena panic issues during server-side rendering - Add proper TypeScript configuration and build optimizations 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
5.2 KiB
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<dyn DatabaseConnection>, 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:
struct PostgresConnection { /* ... */ }
struct SqliteConnection { /* ... */ }
En lugar de:
trait DatabaseConnection {
type Row;
fn query<T>(&self, sql: &str) -> T; // método genérico, no object-safe
}
Define un enum:
enum DatabaseConnectionEnum {
Postgres(PostgresConnection),
Sqlite(SqliteConnection),
}
Y luego implementa métodos para el enum que deleguen a cada variante:
impl DatabaseConnectionEnum {
fn query<T>(&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