Class DefaultedComparisonDelegate
A defaulted < <= > >= is <=> against zero. A defaulted == is
<=> when the type has its own comparator, otherwise field by field. A defaulted <> is <=>
when the type has its own comparator and no hand-written ==, otherwise the negation of ==.
Two parts of the compiler must answer this identically: synthesis (SyntheticOperatorGenerator), which
emits the delegating call, and the phase-5 call graph, which must hold the same edge - without it an assert in a
<=> reached only through a generated < was reported orphaned (E81011) instead of reached from
production (E81012) (B18 prerequisite P3). Extracted 2026-09-30 from SyntheticOperatorGenerator's private
predicates so they cannot drift; B18 reshapes these rules here, once.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final class -
Method Summary
Modifier and TypeMethodDescriptionforAggregate(IAggregateSymbol aggregate, ISymbol ek9Any) of(IAggregateSymbol, MethodSymbol, ISymbol)for the operators of ONE aggregate, for a caller that asks about each of them in turn: the type's facts - whether it has its own comparator or a hand-written==, and which<=>and==serve it - are worked out at most once, not once per operator.static booleanhasHandWrittenEquality(IAggregateSymbol aggregate) True when the developer wrote an==that takes the type itself (not a defaulted one).static booleanhasOwnComparator(IAggregateSymbol aggregate, ISymbol ek9Any) True when the aggregate has its own REAL<=>that takes itself - hand-written, or defaulted (and not retracted) over fields that can all really be ordered.static Optional<MethodSymbol> of(IAggregateSymbol aggregate, MethodSymbol operator, ISymbol ek9Any) The operator a generated comparison delegates to, resolved on the type (its own, a super's or a trait's).
-
Method Details
-
of
public static Optional<MethodSymbol> of(IAggregateSymbol aggregate, MethodSymbol operator, ISymbol ek9Any) The operator a generated comparison delegates to, resolved on the type (its own, a super's or a trait's). Empty when the operator is not a generated comparison, or it is compared field by field (a defaulted==with no comparator) and so delegates to no single operator of this type. -
forAggregate
public static DefaultedComparisonDelegate.Resolver forAggregate(IAggregateSymbol aggregate, ISymbol ek9Any) of(IAggregateSymbol, MethodSymbol, ISymbol)for the operators of ONE aggregate, for a caller that asks about each of them in turn: the type's facts - whether it has its own comparator or a hand-written==, and which<=>and==serve it - are worked out at most once, not once per operator. The same decision asof(IAggregateSymbol, MethodSymbol, ISymbol), which uses it. Holds answers about the type as it is now, so use it while nothing is being defined into the type. -
hasOwnComparator
True when the aggregate has its own REAL<=>that takes itself - hand-written, or defaulted (and not retracted) over fields that can all really be ordered. Then every defaulted comparison,==and<>included, is answered by it (Steve, 2026-09-29), so a defaulted operator can never disagree with the type's ordering. Without one,==is field by field and<>its negation.🔑 A defaulted
<=>over a field that cannot be ordered degenerates toAny's, which is UNSET: a genericBox of Listderived an UNSET==from it while field by field is true (Fable review p05d). So such an instantiation falls back to field-wise==- B07's rule applied per instantiation (B18 rule 8). -
hasHandWrittenEquality
True when the developer wrote an==that takes the type itself (not a defaulted one). A hand-written==is the type's equality, so the defaulted<>is its negation - even beside a<=>, or the two would disagree. INTERIM: B18 makes a hand-written comparison beside a<=>an error.
-