E137: Illegal Super Accessor
This error occurs when a class cannot be defined due to a conflict between its parent traits when implementing a super-accessor.
When a trait calls super.method without explicitly naming a parent (like super[Parent].method), Scala generates a super-accessor in the extending class based on the linearization order. If the resolved super-call has an incompatible return type with what the trait expects, this error is raised.
This typically happens when:
- A trait contains a
super.methodcall - Another trait in the hierarchy overrides the same method with a different return type
- Due to linearization order, the super-accessor would bind to the wrong implementation
Example
class X
class Y extends X
trait A[+T]:
def foo: T = null.asInstanceOf[T]
trait B extends A[X]:
override def foo: X = new X
trait C extends A[Y]:
override def foo: Y = new Y
def superFoo: Y = super.foo
class Fail extends B with C
Error
-- [E137] Declaration Error: example.scala:14:6 --------------------------------
14 |class Fail extends B with C
| ^
|class Fail cannot be defined due to a conflict between its parents when
|implementing a super-accessor for foo in trait C:
|
|1. One of its parent (C) contains a call super.foo in its body,
| and when a super-call in a trait is written without an explicit parent
| listed in brackets, it is implemented by a generated super-accessor in
| the class that extends this trait based on the linearization order of
| the class.
|2. Because B comes before C in the linearization
| order of Fail, and because B overrides foo,
| the super-accessor in Fail is implemented as a call to
| super[B].foo.
|3. However,
| X (the type of super[B].foo in Fail)
| is not a subtype of
| Y (the type of foo in trait C).
| Hence, the super-accessor that needs to be generated in Fail
| is illegal.
|
|Here are two possible ways to resolve this:
|
|1. Change the linearization order of Fail such that
| C comes before B.
|2. Alternatively, replace super.foo in the body of trait C by a
| super-call to a specific parent, e.g. super[A].foo
Solution
// Use explicit super-call in the trait
class X
class Y extends X
trait A[+T]:
def foo: T = null.asInstanceOf[T]
trait B extends A[X]:
override def foo: X = new X
trait C extends A[Y]:
override def foo: Y = new Y
def superFoo: Y = super[A].foo
class Fixed extends B with C
In this article