diff --git a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala index a6ac71286543..899ee82c9033 100644 --- a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala +++ b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala @@ -186,8 +186,22 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer { def mkNonThreadSafeDef(target: Tree, flag: Tree, rhs: Tree)(implicit ctx: Context) = { val setFlag = flag.becomes(Literal(Constants.Constant(true))) - val setTargets = if (isWildcardArg(rhs)) Nil else target.becomes(rhs) :: Nil - val init = Block(setFlag :: setTargets, target.ensureApplied) + val flagSet = setFlag :: Nil + + val init = evalOnce(rhs) { rhsRef => + val targetSet = if (isWildcardArg(rhs)) flagSet else target.becomes(rhsRef) :: flagSet + val checkValidity = + tpd.If( + target.select(defn.Any_!=).appliedTo(tpd.defaultValue(target.tpe.widenDealias)).select(defn.Boolean_&&). + appliedTo( + target.select(defn.Any_!=).appliedTo(rhsRef) + ), + tpd.Throw(tpd.New(ctx.requiredClass("java.lang.IllegalStateException").namedType, Nil)), + tpd.EmptyTree + ) + Block(checkValidity :: targetSet, rhsRef) + } + If(flag.ensureApplied, target.ensureApplied, init) } diff --git a/tests/run/i1856.check b/tests/run/i1856.check new file mode 100644 index 000000000000..5ebf09a88014 --- /dev/null +++ b/tests/run/i1856.check @@ -0,0 +1,11 @@ +Iteration 0 +Iteration 1 +Iteration 2 +Iteration 3 +Iteration 4 +Iteration 5 +Iteration 6 +Iteration 7 +Iteration 8 +Iteration 9 +42 diff --git a/tests/run/i1856.scala b/tests/run/i1856.scala new file mode 100644 index 000000000000..b50fb51862e9 --- /dev/null +++ b/tests/run/i1856.scala @@ -0,0 +1,14 @@ +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) + } +} diff --git a/tests/run/i1856b.check b/tests/run/i1856b.check new file mode 100644 index 000000000000..d7556d459565 --- /dev/null +++ b/tests/run/i1856b.check @@ -0,0 +1,22 @@ +Iteration 0 +Iteration 1 +Iteration 2 +Iteration 3 +Iteration 4 +Iteration 5 +Iteration 6 +Iteration 7 +Iteration 8 +Iteration 9 +Lzy has been read as: 42 +Lzy has been read as: 43 +Lzy has been read as: 44 +Lzy has been read as: 45 +Lzy has been read as: 46 +Lzy has been read as: 47 +Lzy has been read as: 48 +Lzy has been read as: 49 +Lzy has been read as: 50 +Lzy has been read as: 51 +52 +Lzy has been read as: 52 diff --git a/tests/run/i1856b.scala b/tests/run/i1856b.scala new file mode 100644 index 000000000000..1a208600798b --- /dev/null +++ b/tests/run/i1856b.scala @@ -0,0 +1,21 @@ +object Test { + var count: Int = 0 + def getLzy = { + val read = lzy + println("Lzy has been read as: " +read) + read + } + + lazy val lzy: Int = { + if (count < 10) { + println(s"Iteration $count") + count += 1 + getLzy + 1 + } else 42 + } + + def main(args: Array[String]): Unit = { + println(lzy) + getLzy + } +}