- Rust's trait system is powerful but strict about avoiding ambiguity, particularly with blanket implementations.
- A blanket implementation applies to any type meeting certain constraints, often via generics, like From<T> and Into<U> in Rust's standard library.
- Rust enforces a rule that no two blanket implementations can overlap, even theoretically, to prevent ambiguity.
- In Joydb, the Adapter trait needed to support two implementations: UnifiedAdapter and PartitionedAdapter, but Rust's rules prevented direct blanket implementations.
- A workaround involves using marker structs (Unified<T> and Partitioned<T>) and a helper trait (BlanketAdapter) to delegate behavior without violating coherence rules.
- The Adapter trait uses an associated type (Target) to specify whether to delegate to Unified<Self> or Partitioned<Self>.
- This pattern allows for alternative blanket implementations while adhering to Rust's coherence rules, enhancing ergonomics without code duplication.
- The solution is useful for supporting mutually exclusive behaviors under a unified interface in Rust.