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
Incorrect wireing of abstract override methods implementing specialized (narrowed) version of the root trait #9894
Comments
Imported From: https://issues.scala-lang.org/browse/SI-9894?orig=1
|
@SethTisue said: |
Marcin Mościcki (mmoscicki) said (edited by @lrytz on Sep 30, 2016 9:42:11 AM UTC): trait AbstractOverrideTest[-I, +O] { self =>
def flatMap[T](f :O=>Seq[T]) :AbstractOverrideTest[I, T]
}
trait EnhancedAOT[-I, +O] extends AbstractOverrideTest[I, O] { self =>
override def flatMap[T](f: (O) => Seq[T]): EnhancedAOT[I, T]
}
trait EnhancedMixin[-I, +O] extends EnhancedAOT[I, O] {
self =>
abstract override def flatMap[T](f: (O) => Seq[T]): EnhancedAOT[I, T] = {
val e = super.flatMap(f)
//we won't reach here
???
}
}
class RealAOT[-I, +O] extends AbstractOverrideTest[I, O] {
override def flatMap[T](f: (O) => Seq[T]): AbstractOverrideTest[I, T] = new RealAOT[I, T]
}
class Mixed[-I, +O] extends RealAOT[I, O] with EnhancedAOT[I, O] with EnhancedMixin[I, O]
object AbstractOverrideApp extends App {
//below throws a ClassCast because EnhancedMixin expects an EnhancedAOT result in abstract override instead of just AbstractOverrideTest
val mf = new Mixed[Any, Any].flatMap(Seq(_))
}
And the stack trace (not very helpful due to all re-wiring by the compiler, but the final like should be obvious:
I don't think I can simplify it to use fewer classes. The bug is between class linearization and how method overriding works;
After itemizing it this way, I believe that my first conclusion was wrong, and in fact the declaration class Mixed[-I, +O] extends RealAOT[I, O] with EnhancedAOT[I, O] with EnhancedMixin[I, O] should be illegal, failing compilation at this point, even if Sorry if I refered to linearization in different order than definition from scala spec, but I find it much more intuitive if it follows the order in which the types are mixed in, rather than the reverse for the sake of being able to call the right method the first. I hope this explanation will be clear enough. |
@SethTisue said: |
Marcin Mościcki (mmoscicki) said (edited on Sep 29, 2016 9:26:32 PM UTC): |
@lrytz said: trait T {
def m: T
}
trait U extends T {
override def m: U
}
trait V extends U {
abstract override def m: U = super.m
}
class W extends T {
override def m: T = new W
}
class C extends W with U with V
object Test extends App {
new C().m // bum
} |
Having a base trait,
AbstractOverrideTest
, with a specialized versionEnhancedAOT
, intended to be implemented as a mixin using stacked traits pattern, results in the following code compiling, but throwingClassCastException
as the abstract override method expectsan
EnhancedAOT
instead of rootAbstractOverrideTest
. In practice, the following mixin shouldn't compile:And the resulting stack trace:
Proper implementation with the following change:
Works as expected, so this is a minor issue which should just report an error during compilation.
The text was updated successfully, but these errors were encountered: