Skip to content

Failure to implement super-accessor to toString #6089

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
bjornregnell opened this issue Mar 13, 2019 · 1 comment
Closed

Failure to implement super-accessor to toString #6089

bjornregnell opened this issue Mar 13, 2019 · 1 comment

Comments

@bjornregnell
Copy link
Contributor

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] ?

@bjornregnell
Copy link
Contributor Author

(note from the Gitter chat) "Perhaps related to some confusion between toString and toString() "

odersky added a commit that referenced this issue Mar 21, 2019
 Fix #6089: Handle super-accessors involving `()T` to `=> T` overrides
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants