Skip to content

Commit 6bb7b5e

Browse files
committed
Refactor code
1 parent 0754aa0 commit 6bb7b5e

File tree

4 files changed

+81
-23
lines changed

4 files changed

+81
-23
lines changed

compiler/src/dotty/tools/dotc/transform/init/Semantic.scala

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,19 @@ object Semantic:
777777

778778
/** Handle a new expression `new p.C` where `p` is abstracted by `value` */
779779
def instantiate(klass: ClassSymbol, ctor: Symbol, args: List[ArgInfo]): Contextual[Value] = log("instantiating " + klass.show + ", value = " + value + ", args = " + args.map(_.value.show), printer, (_: Value).show) {
780+
def tryLeak(warm: Warm, argValues: List[Value]): Contextual[Value] =
781+
val argInfos2 = args.zip(argValues).map { (argInfo, v) => argInfo.copy(value = v) }
782+
val errors = Reporter.stopEarly {
783+
given Trace = Trace.empty
784+
warm.callConstructor(ctor, argInfos2)
785+
}
786+
if errors.nonEmpty then
787+
val error = UnsafeLeaking(trace.toVector, errors.head)
788+
reporter.report(error)
789+
Hot
790+
else
791+
warm
792+
780793
if promoted.isCurrentObjectPromoted then Hot
781794
else value match {
782795
case Hot =>
@@ -793,17 +806,7 @@ object Semantic:
793806
else
794807
val outer = Hot
795808
val warm = Warm(klass, outer, ctor, args2).ensureObjectExists()
796-
val argInfos2 = args.zip(args2).map { (argInfo, v) => argInfo.copy(value = v) }
797-
val errors = Reporter.stopEarly {
798-
given Trace = Trace.empty
799-
warm.callConstructor(ctor, argInfos2)
800-
}
801-
if errors.nonEmpty then
802-
val error = UnsafeLeaking(trace.toVector, errors.head)
803-
reporter.report(error)
804-
Hot
805-
else
806-
warm
809+
tryLeak(warm, args2)
807810

808811
case Cold =>
809812
val error = CallCold(ctor, trace.toVector)
@@ -819,10 +822,13 @@ object Semantic:
819822
case _ => ref
820823

821824
val argsWidened = args.map(_.value).widenArgs
822-
val argInfos2 = args.zip(argsWidened).map { (argInfo, v) => argInfo.copy(value = v) }
823825
val warm = Warm(klass, outer, ctor, argsWidened).ensureObjectExists()
824-
warm.callConstructor(ctor, argInfos2)
825-
warm
826+
if argsWidened.exists(_.isCold) then
827+
tryLeak(warm, argsWidened)
828+
else
829+
val argInfos2 = args.zip(argsWidened).map { (argInfo, v) => argInfo.copy(value = v) }
830+
warm.callConstructor(ctor, argInfos2)
831+
warm
826832

827833
case Fun(body, thisV, klass) =>
828834
report.error("unexpected tree in instantiating a function, fun = " + body.show, trace.toVector.last)
@@ -1518,6 +1524,10 @@ object Semantic:
15181524
eval(tree, thisV, klass)
15191525
}
15201526

1527+
// ensure we try promotion once even if class body is empty
1528+
if fieldsChanged && thisV.isThisRef then
1529+
thisV.asInstanceOf[ThisRef].tryPromoteCurrentObject()
1530+
15211531
// The result value is ignored, use Hot to avoid futile fixed point computation
15221532
Hot
15231533
}

tests/init/neg/apply2.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ object O:
33
println(n)
44

55
class B:
6-
val a = A(this)
6+
val a = A(this) // error
77

88
val b = new B
9-
val n = 10 // error
9+
val n = 10
1010
end O

tests/init/neg/secondary-ctor4.check

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
-- Error: tests/init/neg/secondary-ctor4.scala:54:14 -------------------------------------------------------------------
2+
54 | val c = new C(b, 5) // error
3+
| ^^^^^^^^^^^
4+
| Unsafe leaking of uninitialized value: the leaked value is used. Calling trace:
5+
| -> class N(d: D) extends M(d) { [ secondary-ctor4.scala:59 ]
6+
| ^
7+
| -> def this(d: D) = { [ secondary-ctor4.scala:7 ]
8+
| ^
9+
| -> new A(new B(new D)) // error [ secondary-ctor4.scala:42 ]
10+
| ^^^^^
11+
| -> class D { [ secondary-ctor4.scala:52 ]
12+
| ^
13+
| -> val c = new C(b, 5) // error [ secondary-ctor4.scala:54 ]
14+
| ^^^^^^^^^^^
15+
|
16+
| The leaked uninitialized value is used as follows:
17+
| -> def this(b: B, x: Int) = this(b) [ secondary-ctor4.scala:49 ]
18+
| ^^^^^^^
19+
| -> class C(b: B) extends A(b) with T { [ secondary-ctor4.scala:48 ]
20+
| ^
21+
| -> def this(b: B) = { [ secondary-ctor4.scala:17 ]
22+
| ^
23+
| -> Inner().foo() [ secondary-ctor4.scala:26 ]
24+
| ^^^^^^^
25+
| -> class Inner() { [ secondary-ctor4.scala:21 ]
26+
| ^
27+
| -> println(b.n) [ secondary-ctor4.scala:23 ]
28+
| ^^^
29+
-- Error: tests/init/neg/secondary-ctor4.scala:42:4 --------------------------------------------------------------------
30+
42 | new A(new B(new D)) // error
31+
| ^^^^^^^^^^^^^^^^^^^
32+
| Unsafe leaking of uninitialized value: the leaked value is used. Calling trace:
33+
| -> class N(d: D) extends M(d) { [ secondary-ctor4.scala:59 ]
34+
| ^
35+
| -> def this(d: D) = { [ secondary-ctor4.scala:7 ]
36+
| ^
37+
| -> new A(new B(new D)) // error [ secondary-ctor4.scala:42 ]
38+
| ^^^^^^^^^^^^^^^^^^^
39+
|
40+
| The leaked uninitialized value is used as follows:
41+
| -> def this(b: B) = { [ secondary-ctor4.scala:17 ]
42+
| ^
43+
| -> Inner().foo() [ secondary-ctor4.scala:26 ]
44+
| ^^^^^^^
45+
| -> class Inner() { [ secondary-ctor4.scala:21 ]
46+
| ^
47+
| -> println(b.n) [ secondary-ctor4.scala:23 ]
48+
| ^^^

tests/init/neg/secondary-ctor4.scala

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,18 @@ class M(x: Int) {
1010
class L1(x: Int) { val n: Int = 5 }
1111

1212
class A(b: B, x: Int) {
13-
println(d.n) // error
13+
println(d.n)
1414

1515
class L2(x: Int) { val n: Int = 5 }
1616

1717
def this(b: B) = {
1818
this(b, 5)
19-
println(d.n) // error
19+
println(d.n)
2020

2121
class Inner() {
22-
println(d.n) // error
23-
println(b.n) // error
24-
def foo() = println(b.n) // error
22+
println(d.n)
23+
println(b.n)
24+
def foo() = println(b.n)
2525
}
2626
Inner().foo()
2727

@@ -39,7 +39,7 @@ class M(x: Int) {
3939
val n: Int = 10
4040
}
4141

42-
new A(new B(new D))
42+
new A(new B(new D)) // error
4343

4444
trait T {
4545
val m: Int = 10
@@ -51,7 +51,7 @@ class M(x: Int) {
5151

5252
class D {
5353
val b = new B(this)
54-
val c = new C(b, 5)
54+
val c = new C(b, 5) // error
5555
}
5656
}
5757
}

0 commit comments

Comments
 (0)