E07186: a subtype of an ordered type (its super has '<=>') must stay ordered: it declares '<=>' (by hand or 'default operator <=>'), not '==' alone, and a bare 'default operator' needs every one of its fields to have a '<=>'
What went wrong
This type extends an ORDERED type - a super with '<=>' - and declares its own sameness as '==' only. The type would then answer two questions differently: its own '==' compares all its fields, while the '<=>' it inherits from the super compares only the super's. Two values that '==' says differ would still give '<=>' 0, so a sort, a sorted collection or '<?' would treat them as the same.
A type defines its SAMENESS once and every other comparison is generated from it. Below an ordered type the sub-type's own sameness keeps the type ordered: it declares '<=>' over all its fields, and '==' is generated from that '<=>', so the two can never disagree.
Below an equatable-only super (one with '==' and no '<=>'), this error does not apply: below an equatable-only super you may keep '==', or write '<=>' by hand to order the sub-type. A generated '<=>' there is E07190 - it would order the super's fields first, through a '<=>' the super does not have.
The same happens when the sub-type asks for its sameness with the BARE 'default operator' and one of its fields cannot be ordered - a Dict, a List or any type with no '<=>'. The bare 'default operator' gives the sub-type '<=>' only where every field can be ordered. Here it could not, so the type would be left with '==' alone while its super is ordered: the same disagreement, made silently. The message names the field that cannot be ordered. A sub-type of an ordered type is ordered, or it is not a sub-type.
Worked examples
The [EXAMPLE] section below shows a Named that extends an ordered Holder and asks for 'default operator ==', and a Bag that extends it with a Dict field and the bare 'default operator', then the fixes - 'default operator <=>' in place of '==', and a Bag that holds a Holder.
How to fix it
- Declare '<=>' in place of '==': 'default operator <=>' compares the super's '<=>' first and then the type's own fields; '==' and the rest are generated.
- Or write '<=>' by hand over the same fields, with a hand-written '#?' beside it (E07184).
- If the type should not be ordered at all, it cannot extend an ordered type: hold the other type as a field instead (composition). That is the fix for a bare 'default operator' over a field that cannot be ordered: 'Bag' holds a Holder, it is not one.
- For a bare 'default operator' over such a field, you may instead write '<=>' by hand over the fields that can be ordered, with a hand-written '#?' beside it (E07184).
Common causes
- 'default operator ==' on a sub-type, copied from an equatable-only example
- A hand-written '==' over a new field in a sub-type of a type with '<=>'
- A bare 'default operator' on a sub-type of an ordered type that adds a Dict, a List or another field type with no '<=>'
See also
Examples
Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.
Fails with E07186: a subtype of an ordered type (its super has '<=>') must stay ordered: it declares '<=>' (by hand or 'default operator <=>'), not '==' alone, and a bare 'default operator' needs every one of its fields to have a '<=>'
#!ek9 defines module error.e07186.bad defines class Holder as open count as Integer: 1 Holder() -> count as Integer this.count: count default operator Named extends Holder name as String: String() Named() -> count as Integer name as String super(count) this.name: name //Holder is ordered: the '<=>' Named inherits compares only count, so it would disagree with this '==' default operator == default operator ? default operator $ default operator $$ default operator #? default operator :=: //Holder is ordered, and Bag's field 'extras' is a Dict, which has no '<=>': the bare 'default operator' below //cannot be given one - the type would be equatable only while Holder is ordered Bag extends Holder extras as Dict of (String, Integer): Dict() of (String, Integer) Bag() -> count as Integer super(count) default operator
Fixed: Declare '<=>', or hold the ordered type instead
#!ek9 defines module error.e07186.good defines class Holder as open count as Integer: 1 Holder() -> count as Integer this.count: count default operator Named extends Holder name as String: String() Named() -> count as Integer name as String super(count) this.name: name //'<=>' compares Holder's count, then name; '==' and the rest are generated from it default operator <=> default operator ? default operator $ default operator $$ default operator #? default operator :=: //A Bag that is not a Holder: it HOLDS one, and its bare 'default operator' gives it '==' alone Bag holder as Holder: Holder(1) extras as Dict of (String, Integer): Dict() of (String, Integer) default operator
Questions and answers
These Q&A entries show E07186 and its fix: