E07190: 'default' of operators requires super to have appropriate operator
What went wrong
You're using 'default operator' in a class that extends another class, but no class ABOVE it has the required operator. Default operators in derived classes call the NEAREST version above them first - the super's, or one further up the chain when the classes in between declare none (a field-less class in the middle needs nothing of its own).
When nothing above has the operator (only 'Any'), the message NAMES where it belongs: the nearest super class that has fields of its own - the root of the data decides whether its fields are exposed - or, when no super class has fields, the root of the hierarchy. Add 'default operator <op>' THERE. For the [EXAMPLE] below the message reads "Relating to 'Holder' requires operator '$()': nothing above 'Leaf' has it; add 'default operator $' to 'Holder' (the nearest super class with fields)".
SAMENESS ('==' and '<=>') is different. A generated '==' or '<=>' compares the type's own fields and leaves the inherited ones to the super's sameness - a '==' or '<=>' that takes the super itself, matched by its signature. So:
- When the super chain HAS fields and nothing above compares them, it is this error. A '==(Integer)' or '<=>(Integer)' in the super does not count: it compares with an Integer, not with the super.
- When the super chain has NO fields, there is nothing to compare: the generated one compares only the sub-type's own fields, with no call to the super, and is legal.
So the fix is to give the super class with fields its sameness - the sub-type then keeps its own 'default operator ==' or '<=>', which compares its own fields after the super's (a sub-type that adds fields must declare its own: E07238) - or to write the sub-type's operator by hand.
AN EQUATABLE-ONLY SUPER (one with '==' and no '<=>') cannot be built on by a GENERATED '<=>'. The message reads "'Base' is equatable only - a generated '<=>' has no '<=>(Base)' to order Base's fields first; write '<=>' by hand, or declare 'default operator =='". A sub-type of an equatable-only type may be ordered by a HAND-WRITTEN '<=>' only, which says itself how Base's fields take part; or it keeps '==' ('default operator ==', or the bare 'default operator', which follows the super). Below sameness written BY HAND on an abstract base or a trait the sub-type may declare no sameness at all: that is E07182, reported in place of this error.
A SUPER THAT CANNOT BE ORDERED has no '<=>' either. The bare 'default operator' gives a type '<=>' only when every field can be ordered; a field whose type has '==' only (or a List, a Dict) leaves it '==' and '#?'. A sub-type follows its super: below it, the bare 'default operator' gives '==' and '#?' only, and an explicit 'default operator <=>' is this error - the message says which super cannot be ordered and which field causes it. Declare 'default operator ==' on the sub-type (good_follows.ek9), give the field's type a '<=>', or write the sub-type's '<=>' by hand.
Worked examples
Compilable examples demonstrating this error and the correct fix:
- ek9 -q 1314 (Why does 'default operator' in a derived class fail wh...)
Note
Each 'default operator' shows only ONE error at a time. Fix the first, then you may see additional errors for other missing operators.
How to fix it
- Add 'default operator <op>' to the class the message names (the nearest super class with fields, or the hierarchy's root)
- For '==' or '<=>': give the super class with fields its sameness; the sub-type's own then compares its fields after the super's
- Below a super that cannot be ordered, or one that is equatable only, default '==' instead - or, below an equatable-only super, write '<=>' by hand.
- Or implement operators manually in derived class
- Each missing operator is reported separately
The [EXAMPLE] section below shows both cases (the message names 'Holder', the nearest super class with fields; and the root 'Plain' when none has fields), the fix of adding the operator above, and the alternative of writing the operator by hand (good_written.ek9). It also shows 'Detailed' asking for '<=>' below 'Labelled', which cannot be ordered, and the fix of following the super with '==' (good_follows.ek9).
Common causes
- Base class has no operators defined
- Inheritance chain missing operator implementations
- Using default in derived class without checking super
- A super '==' or '<=>' that takes another type ('==(Integer)'), which is not the super's sameness
- 'default operator <=>' below a super whose bare 'default operator' cannot order one of its fields
- 'default operator <=>' below an equatable-only super ('default operator ==' there, or a hand-written '==')
See also
Examples
Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.
Fails with E07190: 'default' of operators requires super to have appropriate operator
#!ek9 defines module error.e07190.bad defines class Root as open default operator ? Holder extends Root as open code as Integer: Integer() Holder() as pure -> initial as Integer code :=? Integer(initial) default operator ? Middle extends Holder as open Middle() as pure -> initial as Integer super(initial) Leaf extends Middle name as String: String() Leaf() as pure -> initial as Integer super(initial) name :=? String("leaf") default operator ? default operator $ //No super class has fields: the message names the root, Plain. Plain as open default operator ? PlainLeaf extends Plain label as String: String() default operator ? default operator $ //Equatable only, so Labelled's bare 'default operator' cannot give it a '<=>'. Tag text as String: String() Tag() -> text as String this.text: text default operator == default operator ? default operator $ default operator $$ default operator #? default operator :=: Labelled as open tag as Tag: Tag("t") default operator Detailed extends Labelled detail as String: String() default operator <=> default operator ? default operator $ default operator $$ default operator :=:
Fixed: Give a super with fields the operator too
#!ek9 defines module error.e07190.good defines class Root as open code as Integer: Integer() default operator ? default operator $ Leaf extends Root name as String: String() default operator ? //Root has its own '$', so the generated one can call it for Root's fields default operator $
Fixed: Below a super that cannot be ordered, follow it with '=='
#!ek9 defines module error.e07190.good.follows defines class //Equatable only, so Labelled's bare 'default operator' gives it '==' and '#?' but no '<=>' Tag text as String: String() Tag() -> text as String this.text: text default operator == default operator ? default operator $ default operator $$ default operator #? default operator :=: Labelled as open tag as Tag: Tag("t") default operator //A sub-type follows its super: '==' (with '#?'), built on Labelled's '==' Detailed extends Labelled detail as String: String() default operator == default operator ? default operator $ default operator $$ default operator #? default operator :=:
Fixed: Or write the operator by hand in the sub-type
#!ek9 defines module error.e07190.good.written defines class Root as open code as Integer: Integer() codeText() as pure <- rtn as String: $code default operator ? Leaf extends Root name as String: String() default operator ? //Nothing above has '$', so Leaf writes its own instead of generating one operator $ as pure <- rtn as String: `${name} (${codeText()})`
Questions and answers
These Q&A entries show E07190 and its fix: