Skip to content

Locks for volatile lazy vals should be static #1149

Closed
@odersky

Description

@odersky

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.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions