E02090: a listed trait is already a trait of another listed trait or of the super class - it is inherited through that one
What went wrong
A trait in the 'with trait of' list is already a trait of ANOTHER trait in the same list, or of the SUPER CLASS. With 'LoudSpeaker with trait of Speaker', writing 'with trait of LoudSpeaker, Speaker' lists Speaker twice over: everything Speaker brings is already inherited through LoudSpeaker, so the second name adds nothing. The same holds for 'Announcer extends Base with trait of Speaker' when 'Base with trait of Speaker': Announcer is already a Speaker through Base. The message names the trait and where it already comes from: 'Speaker' is already a trait of 'LoudSpeaker' (or 'Base'). Every redundant trait on the declaration is named in that one error ('Speaker' is already a trait of 'LoudSpeaker'; 'Listener' is already a trait of 'LoudListener'; list each once).
The order does not matter ('Speaker, LoudSpeaker' is the same), and neither does the depth: a trait of a trait of a listed trait counts too, and so does a trait of the super class's super class.
How to fix it
- Delete the redundant name and keep the trait that has it: 'with trait of LoudSpeaker'
- When the super class has it and it is the only trait listed, delete the whole 'with trait of Speaker': 'Announcer extends Base'
- The compiler's repair does exactly this for you ('ek9 -fc', 'ek9_compile', 'ek9_edit_file', 'ek9_write_file'), since it is the only reading. By hand: delete the name from the list.
- Listed 'by' a delegate ('Announcer extends Base with trait of Speaker by speaker'), the message says it cannot be delegated again here: the super class (or the listed trait that has it) already provides Speaker, so this type cannot hand it to another object. Nothing is repaired - deleting the name would silently drop the delegation. Decide which you want: keep what the super class provides and delete 'Speaker by speaker', or delegate a different trait.
The [EXAMPLE] section below shows a class listing both, and the class listing only the trait that has the other; the second example shows a class whose super class already has the trait.
Common causes
- Listing every trait a type should satisfy, without noticing that one of them already has another, or that the super class already has it
- A trait gained a trait of its own, or a super class gained a trait, after the types using it were written
Note
A diamond - two DIFFERENT listed traits, or the super class and a listed trait, that share a trait you do NOT list ('with trait of LoudSpeaker, QuietSpeaker' where both are Speakers) - is fine: each of the shared trait's methods reaches the type along both routes but is one method. Two different traits that each implement the same method is a real conflict, and that stays E06150: override the method in the type and choose.
See also
Examples
Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.
Fails with E02090: a listed trait is already a trait of another listed trait or of the super class - it is inherited through that one
#!ek9 defines module error.e02090.bad defines trait Speaker speak() <- rtn as String: "hello" LoudSpeaker with trait of Speaker shout() <- rtn as String: "HELLO" defines class //LoudSpeaker already has Speaker, so listing Speaker again adds nothing Megaphone with trait of LoudSpeaker, Speaker default operator ? Stage with trait of Speaker as open default operator ? //The super class Stage already has Speaker, so listing it again adds nothing Podium extends Stage with trait of Speaker default operator ?
Fixed: List only the trait that has the other - it brings both; a trait the super class has is not listed again
#!ek9 defines module error.e02090.good defines trait Speaker speak() <- rtn as String: "hello" LoudSpeaker with trait of Speaker shout() <- rtn as String: "HELLO" defines class //A Megaphone is a LoudSpeaker and so a Speaker too Megaphone with trait of LoudSpeaker default operator ? Stage with trait of Speaker as open default operator ? //A Podium is a Stage and so a Speaker too Podium extends Stage default operator ? defines program Announce() stdout <- Stdout() megaphone <- Megaphone() podium <- Podium() stdout.println(`${megaphone.speak()} ${megaphone.shout()} ${podium.speak()}`)