-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Closed
Labels
Description
Is this difference in behavior in Scala 2 vs dotty intentional or a bug?
// Scala 2.12.8
scala> trait X { override def toString = super.toString + " X" }
defined trait X
scala> trait Y { override def toString = super.toString + " Y" }
defined trait Y
scala> class Z extends X with Y { override def toString = super.toString + " Z" }
defined class Z
scala> new Z
res1: Z = Z@20a24edf X Y Z
In dotty
// dotty 0.14.0-bin-20190312-3c9935f-NIGHTLY
scala> trait X { override def toString = super.toString + " X" }
| trait Y { override def toString = super.toString + " Y" }
| class Z extends X with Y { override def toString = super.toString + " Z" }
|
3 |class Z extends X with Y { override def toString = super.toString + " Z" }
| ^
| class Z cannot be defined due to a conflict between its parents when
| implementing a super-accessor for toString in trait Y:
|
| 1. One of its parent (Y) contains a call super.toString 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 X comes before Y in the linearization
| order of Z, and because X overrides toString,
| the super-accessor in Z is implemented as a call to
| super[X].toString.
| 3. However,
| String (the type of super[X].toString in Z)
| is not a subtype of
| (): String (the type of toString in trait Y).
| Hence, the super-accessor that needs to be generated in Z
| is illegal.
|
| Here are two possible ways to resolve this:
|
| 1. Change the linearization order of Z such that
| Y comes before X.
| 2. Alternatively, replace super.toString in the body of trait Y by a
| super-call to a specific parent, e.g. super[Object].toString
I wonder why 3 talks about the subtype of (): String
.
And if I follow proposal 1 from this error message it is still an error and proposal 2 gives this:
scala> trait X { override def toString = super[Object].toString + " X" }
| trait Y { override def toString = super[Object].toString + " Y" }
| class Z extends X with Y { override def toString = super.toString + " Z" }
|
// defined trait X
// defined trait Y
// defined class Z
scala> new Z
val res0: Z = Z@30a3e9b Y Z
Compared to Scala 2 which also prints X
...
Shouldn't the behavior in Scala 2 and dotty be the same when not specifying parent super[Object] ?