Description
The following program fails in LambdaLift:
trait Iterator {
def span() = {
val self: Int = 33
class Leading {
def finish(): Unit = println("finished")
}
val leading = new Leading
class Trailing {
@volatile lazy val it = leading.finish()
}
val trailing = new Trailing
(leading, trailing)
}
}
We get (with the improvements to EpxlicitOuter in another PR):
Exception in thread "main" java.lang.AssertionError: assertion failed: failure to construct path from value while$/getter it/class Trailing/trait Iterator/package /package to this
of trait Iterator;
class Trailing in trait Iterator does not have an outer accessor
at scala.Predef$.assert(Predef.scala:165)
at dotty.tools.dotc.transform.ExplicitOuter$OuterOps$.loop$1(ExplicitOuter.scala:323)
at dotty.tools.dotc.transform.ExplicitOuter$OuterOps$.path$extension(ExplicitOuter.scala:329)
at dotty.tools.dotc.transform.LambdaLift$LambdaLifter.memberRef(LambdaLift.scala:362)
at dotty.tools.dotc.transform.LambdaLift$LambdaLifter.transformIdent(LambdaLift.scala:429)
The problem is that we need to establish a reference to the companion object of Trailing
in order to
do the CAS. But that requires an explicit outer pointer and ExplicitOuter did not generate one. The best solution, I think is to make the locks static, also from a standpoint of speed.
Currently this is blocking another important change: We should always assume @volatile under Scala2 mode. But right now we cannot because compilestdlib does not compile due to the issue.