c218d875 · core f63c1e69 · built 2026-10-26 22:39 UTCCoherence
A standalone validation pass between path normalization and type checking: it resolves aspect-impl type/aspect names to their declaring module using only ResolvedNames (no inferred types needed) and rejects two categories of illegal impl. Owning crate: metel-frontend. Defined in coherence.rs.
Model
Coherence answers a deliberately narrow question before inference adds any implementation-specific facts: may these aspect implementations coexist at all? An implementation is allowed only when the module owns one side of the relation; otherwise downstream type checking would make independently-authored modules change each other's meaning. That ownership boundary is the orphan rule.
Within the implementations that are allowed to exist, the pass rejects pairs that could apply to the same type. It reasons about declared bounds and canonical type parameters, rather than inferred types, so the overlap rule is stable regardless of which call sites happen to be checked.
Verifiable architecture claims
Owner metel-frontend unless a requirement names another.
Requirement №1
The orphan rule (T0014): an aspect impl must be local to the aspect's declaring module or the implementing type's; an impl of a foreign aspect on a foreign type, including a negative or blanket/conditional impl with no local anchor, is rejected.
Requirement №2
Overlap detection (T0015): two impls whose coverage overlaps conflict unless provably disjoint, decided over impl-scoped CanonicalType::TypeParams by scoped_type_param_bounds (negation, RFC-0060 §3.1; unconditional-vs-conditional, §3.2; row presence/absence or type contradiction, RFC-0121 §3).
Known limitations
LIMIT-COHERENCE-001 — extend<record T: {...}> T: Aspect is accepted, then never applies. A blanket aspect impl bounded by a row (extend<record T: { x: f64, .. }> T: A) passes coherence, but a call through the bound never dispatches to it; the same class of mistake is rejected outright for the equivalent non-generic form. Open record ↗