Skip to content

Commit 89ab499

Browse files
authored
Merge pull request #4817 from Medowhill/issue4451
Fix #4451: Set flag in the correct order
2 parents e6110c4 + e6f11f0 commit 89ab499

File tree

2 files changed

+59
-5
lines changed

2 files changed

+59
-5
lines changed

compiler/src/dotty/tools/dotc/transform/LazyVals.scala

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -218,11 +218,10 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
218218
* ```
219219
*/
220220
def mkNonThreadSafeDef(target: Tree, flag: Tree, rhs: Tree, nullables: List[Symbol])(implicit ctx: Context) = {
221-
val setFlag = flag.becomes(Literal(Constants.Constant(true)))
222-
val setNullables = nullOut(nullables)
223-
val setTargetAndNullable = if (isWildcardArg(rhs)) setNullables else target.becomes(rhs) :: setNullables
224-
val init = Block(setFlag :: setTargetAndNullable, target.ensureApplied)
225-
If(flag.ensureApplied, target.ensureApplied, init)
221+
val stats = new mutable.ListBuffer[Tree]
222+
if (!isWildcardArg(rhs)) stats += target.becomes(rhs)
223+
stats += flag.becomes(Literal(Constants.Constant(true))) ++= nullOut(nullables)
224+
If(flag.ensureApplied, target.ensureApplied, Block(stats.toList, target.ensureApplied))
226225
}
227226

228227
/** Create non-threadsafe lazy accessor for not-nullable types equivalent to such code

tests/run/i4451.scala

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
class InitError extends Exception
2+
3+
class Lazy(x: Int) {
4+
private[this] var init = false
5+
lazy val value = {
6+
if (!init) {
7+
init = true
8+
throw new InitError
9+
}
10+
x
11+
}
12+
}
13+
14+
class LazyVolatile(x: Int) {
15+
private[this] var init = false
16+
@volatile lazy val value = {
17+
if (!init) {
18+
init = true
19+
throw new InitError
20+
}
21+
x
22+
}
23+
}
24+
25+
object Test {
26+
27+
def tryTwice(x: => Int): Int =
28+
try {
29+
x; assert(false); 0
30+
} catch {
31+
case _: InitError => x
32+
}
33+
34+
def lazyInMethod(x: Int) = {
35+
var init = false
36+
lazy val value = {
37+
if (!init) {
38+
init = true
39+
throw new InitError
40+
}
41+
x
42+
}
43+
tryTwice(value)
44+
}
45+
46+
def main(args: Array[String]) = {
47+
val v = 42
48+
49+
val l0 = new Lazy(v)
50+
val l1 = new LazyVolatile(v)
51+
assert(tryTwice(l0.value) == v)
52+
assert(tryTwice(l1.value) == v)
53+
assert(lazyInMethod(v) == v)
54+
}
55+
}

0 commit comments

Comments
 (0)