Skip to content

Recursively calling a lazy val is broken, prevents bootstrapping tests from passing #1856

Closed
@smarter

Description

@smarter

I don't know if any of this is specified but:

object Test {
  var count: Int = 0
  lazy val lzy: Int = {
    if (count < 10) {
      println(s"Iteration $count")
      count += 1
      lzy
    } else 42
  }

  def main(args: Array[String]): Unit = {
    println(lzy)
  }
}

With scalac:

Iteration 0
Iteration 1
Iteration 2
Iteration 3
Iteration 4
Iteration 5
Iteration 6
Iteration 7
Iteration 8
Iteration 9
42

With dotty:

Iteration 0
0

This is not just a theoretical problem, I hit this while trying to get the sbt-based bootstrapping tests to work, the lazy val was https://github.com/lampepfl/dotty/blob/119725799675ee00d6d3374771765b88e4de67bc/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala#L30, the cycle involves looking up the root DottyPredef import while completing the import (stacktrace: https://gist.github.com/smarter/b2126f895a8458506e58710c93bc9342). I assume that this is not a loop with the Scala2-compiled dotty because we carefully avoid cycles in various ways.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions