object DetSkipOctree {
sealed trait Leaf [PL]
sealed trait Branch[PL]
}
trait DetSkipOctree[PL]
class Impl[PL] extends DetSkipOctree[PL] {
final type Leaf = DetSkipOctree.Leaf[PL]
protected trait LeftBranchImpl {
this: DetSkipOctree.Branch[PL] =>
def demoteLeaf(point: PL, leaf: Leaf): Unit = ???
}
}
Reference to PL is ambiguous,
it is both defined in class Impl
and inherited subsequently in trait LeftBranchImpl
It's clear that PL unambiguously refers to the same thing. This compiles in 2.13.
and I can't seem to find a work-around for this to cross-compile 2.13, Dotty
Here is a work-around (I still think this is a bug)
object DetSkipOctree {
sealed trait Leaf [PL]
sealed trait Branch[PL] {
def newLeaf(qIdx: Int): Leaf[PL]
}
}
trait DetSkipOctree[PL]
class Impl[_PL] extends DetSkipOctree[_PL] {
final type Leaf = DetSkipOctree.Leaf[_PL]
protected trait LeftBranchImpl {
this: DetSkipOctree.Branch[_PL] =>
def demoteLeaf(point: _PL, leaf: Leaf): Unit = ???
final def insert(point: _PL): Leaf = newLeaf(1234)
}
}
The work-around does not really work, as eventually there is a problem between _PL and PL, like
bad parameter reference (param)86#_T at pruneErasedDefs
the parameter is type _T in class Impl but the prefix (param)86
does not define any corresponding arguments. while compiling ...
(here it's _T versus T but it is the same thing)
trait Foo[A]
trait Baz[A] {
trait Bar {
this: Foo[A] =>
def bar(a: A): Unit
}
}
[info] Compiling 1 Scala source to /src/dotty-issues/i9844/target/scala-0.27/classes ...
[error] -- [E049] Reference Error: /src/dotty-issues/i9844/src/main/scala/Main.scala:6:15
[error] 6 | def bar(a: A): Unit
[error] | ^
[error] | Reference to A is ambiguous,
[error] | it is both defined in trait Baz
[error] | and inherited subsequently in trait Bar
But compiles successfully with Scala 2.13.3.
@griggt thanks for minimising even further
Potential workaround:
trait Foo[A]
trait Baz[A] {
type Q = A // added type alias
trait Bar {
this: Foo[A] =>
def bar(a: Q): Unit
}
}
and for the original code:
object DetSkipOctree {
sealed trait Leaf [PL]
sealed trait Branch[PL]
}
trait DetSkipOctree[PL]
class Impl[PL] extends DetSkipOctree[PL] {
final type Leaf = DetSkipOctree.Leaf[PL]
type PLL = PL // added type alias
protected trait LeftBranchImpl {
this: DetSkipOctree.Branch[PL] =>
def demoteLeaf(point: PLL, leaf: Leaf): Unit = ???
}
}
Seems to work for both dotty and scalac, for these examples.
This is the new check https://github.com/lampepfl/dotty/issues/8617 in overdrive.
Scala 2 doesn't benefit from the check yet.
It actually fails with a different error if compiled with a Dotty without #8622 (the fix for #8617) merged.
I tried it with both dotty 0.23.0 and 0.28.0-bin-SNAPSHOT-git-333ab8e that I patched to remove the change introduced by 8622. The result is the same in both cases:
trait Foo[A]
trait Baz[A] {
trait Bar {
this: Foo[A] =>
def bar(a: A): Unit
}
}
[info] Compiling 1 Scala source to /src/dotty-issues/i9844/target/scala-0.23/classes ...
[error] -- Error: /src/dotty-issues/i9844/src/main/scala/Main.scala:6:15 ---------------
[error] 6 | def bar(a: A): Unit
[error] | ^
[error] |type A in trait Foo cannot be accessed as a member of (Bar.this : Foo[A] & Baz.this.Bar) from trait Bar.
As it differs from Scala 2, what is the expected (documented?) behavior?
I think all examples should compile.
Thanks for the minimizations! That was vey helpful in finding the problem, which turned out to be quite fundamental.
Most helpful comment
But compiles successfully with Scala 2.13.3.