diff --git a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala index 7e5cc6a277d9..6545977ba874 100644 --- a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala +++ b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala @@ -218,11 +218,10 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer { * ``` */ def mkNonThreadSafeDef(target: Tree, flag: Tree, rhs: Tree, nullables: List[Symbol])(implicit ctx: Context) = { - val setFlag = flag.becomes(Literal(Constants.Constant(true))) - val setNullables = nullOut(nullables) - val setTargetAndNullable = if (isWildcardArg(rhs)) setNullables else target.becomes(rhs) :: setNullables - val init = Block(setFlag :: setTargetAndNullable, target.ensureApplied) - If(flag.ensureApplied, target.ensureApplied, init) + val stats = new mutable.ListBuffer[Tree] + if (!isWildcardArg(rhs)) stats += target.becomes(rhs) + stats += flag.becomes(Literal(Constants.Constant(true))) ++= nullOut(nullables) + If(flag.ensureApplied, target.ensureApplied, Block(stats.toList, target.ensureApplied)) } /** Create non-threadsafe lazy accessor for not-nullable types equivalent to such code diff --git a/tests/run/i4451.scala b/tests/run/i4451.scala new file mode 100644 index 000000000000..6d713bf4b38c --- /dev/null +++ b/tests/run/i4451.scala @@ -0,0 +1,55 @@ +class InitError extends Exception + +class Lazy(x: Int) { + private[this] var init = false + lazy val value = { + if (!init) { + init = true + throw new InitError + } + x + } +} + +class LazyVolatile(x: Int) { + private[this] var init = false + @volatile lazy val value = { + if (!init) { + init = true + throw new InitError + } + x + } +} + +object Test { + + def tryTwice(x: => Int): Int = + try { + x; assert(false); 0 + } catch { + case _: InitError => x + } + + def lazyInMethod(x: Int) = { + var init = false + lazy val value = { + if (!init) { + init = true + throw new InitError + } + x + } + tryTwice(value) + } + + def main(args: Array[String]) = { + val v = 42 + + val l0 = new Lazy(v) + val l1 = new LazyVolatile(v) + assert(tryTwice(l0.value) == v) + assert(tryTwice(l1.value) == v) + assert(lazyInMethod(v) == v) + } +}