How can trait diamond patterns cause dispatcher ambiguity?
← Dispatcher Validation · Ref: Q617
When a class implements two traits and a dispatcher has handlers for both traits, the dispatch cost to both handlers is identical (0.10 each). This creates ambiguity (E05230) because the compiler cannot determine which handler should win.
THE DIAMOND PROBLEM
Consider: Duck implements both Flyable and Swimmable. A dispatcher has handlers for Flyable (cost 0.10) and Swimmable (cost 0.10). When dispatching a Duck, both handlers are equally good matches. This is the diamond problem applied to dispatch.
BRIDGE TRAIT SOLUTION
Create a combining trait that encompasses both competing traits:
AmphibiousFlyer with trait of Flyable, Swimmable
Then Duck implements ONLY AmphibiousFlyer (not Flyable and Swimmable directly). The dispatcher handler for AmphibiousFlyer has cost 0.10, while Flyable and Swimmable handlers have cost 0.20 (two hops through the bridge). The bridge handler wins.
CRITICAL: the concrete type should implement ONLY the bridge trait, not the individual traits directly. If Duck lists the bridge AND the individual traits, whether the bridge handler still wins depends on the order they are listed in: some orders leave all three handlers tied at the same cost and the dispatch is ambiguous. Implementing only the bridge trait is the order-independent form.
EXPLICIT HANDLER SOLUTION
Add a handler for the specific ambiguous type (e.g., Duck) at cost 0.00 (exact match), which beats any trait handler.
See Q616 for ambiguity basics. See Q60 for dispatcher fundamentals. See Q107 for multiple trait implementation.
Example
defines module qa.dispatchervalidation.diamond defines trait //Bridge trait pattern to resolve diamond ambiguity Flyable canFly() as abstract <- rtn as Boolean? Swimmable canSwim() as abstract <- rtn as Boolean? //Bridge trait: combines both capabilities AmphibiousFlyer with trait of Flyable, Swimmable defines class //Duck implements ONLY the bridge trait (not Flyable/Swimmable directly) //This gives the bridge handler cost 0.10, the individual trait handlers cost 0.20 Duck with trait of AmphibiousFlyer override canFly() <- rtn as Boolean: true override canSwim() <- rtn as Boolean: true //The dispatcher has a handler for each trait and for the bridge Describer describe() as dispatcher -> thing as Any <- rtn as String: "thing" describe() -> thing as Flyable <- rtn as String: "flyable" describe() -> thing as Swimmable <- rtn as String: "swimmable" describe() -> thing as AmphibiousFlyer <- rtn as String: "bridge" //Eagle implements only Flyable Eagle with trait of Flyable override canFly() <- rtn as Boolean: true //Fish implements only Swimmable Fish with trait of Swimmable override canSwim() <- rtn as Boolean: true defines function testBridgeTrait() duck <- Duck() eagle <- Eagle() fish <- Fish() require duck.canFly() require duck.canSwim() require eagle.canFly() require fish.canSwim() describer <- Describer() require describer.describe(duck) == "bridge" require describer.describe(eagle) == "flyable" require describer.describe(fish) == "swimmable"
Common mistakes
E50060 — Boolean has no booleanValue() method in EK9. Boolean values are used directly in conditions. See ek9 -h E50060 for details.
Incorrect:
require duck.canFly().booleanValue()
Correct:
require duck.canFly()
E05120 — When implementing a trait abstract method, the override keyword is required. Omitting it on canFly triggers shadowing detection. See ek9 -h E05120 for details.
Incorrect:
with trait of AmphibiousFlyer canFly()
Correct:
with trait of AmphibiousFlyer override canFly()
Other ways to ask this
- What is the diamond problem in EK9 dispatchers?
- How do multiple trait implementations affect dispatch?
- Why does implementing two traits cause E05230?
Coming from another language?
Java: no runtime dispatch, diamond problem handled by interface default method rules. C++: virtual inheritance for diamond problem. Python: C3 linearization (MRO) provides deterministic resolution. Kotlin: explicit override resolution for diamond conflicts. Rust: no class inheritance, trait coherence rules. EK9: E05230 detects diamond dispatch ambiguity, resolved structurally via bridge traits or explicit handlers.
Keywords: visitor, bridge, dispatch, diamond, multiple, implement, validate, cost, trait, ambiguity, sealed, E05230, handler