Skip to content

Commit 43cd6cb

Browse files
committed
Loosen the widening condition for non-termination
1 parent 83b2f66 commit 43cd6cb

File tree

2 files changed

+32
-13
lines changed

2 files changed

+32
-13
lines changed

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@ object Effects {
1818
def show(effs: Effects)(using Context): String =
1919
effs.map(_.show).mkString(", ")
2020

21-
/** Effects that are related to safe initialization */
21+
/** Effects that are related to safe initialization performed on potentials */
2222
sealed trait Effect {
23-
def size: Int
23+
def potential: Potential
24+
2425
def show(using Context): String
26+
2527
def source: Tree
2628
}
2729

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

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,18 @@ object Potentials {
2222

2323
/** A potential represents an aliasing of a value that is possibly under initialization */
2424
sealed trait Potential {
25-
def size: Int
25+
/** Length of the potential. Used for widening */
26+
def size: Int = 1
27+
28+
/** Nested levels of the potential. Used for widening */
29+
def level: Int = 1
30+
2631
def show(using Context): String
2732
def source: Tree
2833
}
2934

3035
/** The object pointed by `this` */
3136
case class ThisRef()(val source: Tree) extends Potential {
32-
val size: Int = 1
3337
def show(using Context): String = "this"
3438

3539
/** Effects of a method call or a lazy val access
@@ -49,7 +53,8 @@ object Potentials {
4953

5054
/** The object pointed by `C.super.this`, mainly used for override resolution */
5155
case class SuperRef(pot: Potential, supercls: ClassSymbol)(val source: Tree) extends Potential {
52-
val size: Int = 1
56+
override def size: Int = pot.size
57+
override def level: Int = pot.level
5358
def show(using Context): String = pot.show + ".super[" + supercls.name.show + "]"
5459
}
5560

@@ -60,7 +65,7 @@ object Potentials {
6065
* @param outer The potential for `this` of the enclosing class
6166
*/
6267
case class Warm(classSymbol: ClassSymbol, outer: Potential)(val source: Tree) extends Potential {
63-
def size: Int = 1
68+
override def level: Int = 1 + outer.level
6469
def show(using Context): String = "Warm[" + classSymbol.show + ", outer = " + outer.show + "]"
6570

6671
/** Effects of a method call or a lazy val access
@@ -111,35 +116,44 @@ object Potentials {
111116
*/
112117
case class Outer(pot: Potential, classSymbol: ClassSymbol)(val source: Tree) extends Potential {
113118
// be lenient with size of outer selection, no worry for non-termination
114-
def size: Int = pot.size
119+
override def size: Int = pot.size
120+
override def level: Int = pot.size
115121
def show(using Context): String = pot.show + ".outer[" + classSymbol.show + "]"
116122
}
117123

118124
/** The object pointed by `this.f` */
119125
case class FieldReturn(potential: Potential, field: Symbol)(val source: Tree) extends Potential {
120126
assert(field != NoSymbol)
121127

122-
def size: Int = potential.size + 1
128+
override def size: Int = potential.size + 1
129+
override def level: Int = potential.size
123130
def show(using Context): String = potential.show + "." + field.name.show
124131
}
125132

126133
/** The object returned by `this.m()` */
127134
case class MethodReturn(potential: Potential, method: Symbol)(val source: Tree) extends Potential {
128135
assert(method != NoSymbol)
129136

130-
def size: Int = potential.size + 1
137+
override def size: Int = potential.size + 1
138+
override def level: Int = potential.size
131139
def show(using Context): String = potential.show + "." + method.name.show
132140
}
133141

134142
/** The object whose initialization status is unknown */
135143
case class Cold()(val source: Tree) extends Potential {
136-
def size: Int = 1
137144
def show(using Context): String = "Cold"
138145
}
139146

140147
/** A function when called will produce the `effects` and return the `potentials` */
141148
case class Fun(potentials: Potentials, effects: Effects)(val source: Tree) extends Potential {
142-
def size: Int = 1
149+
override def size: Int = 1
150+
151+
override def level: Int = {
152+
val max1 = potentials.map(_.level).max
153+
val max2 = effects.map(_.potential.level).max
154+
if max1 > max2 then max1 else max2
155+
}
156+
143157
def show(using Context): String =
144158
"Fun[pots = " + potentials.map(_.show).mkString(";") + ", effs = " + effects.map(_.show).mkString(";") + "]"
145159
}
@@ -192,8 +206,11 @@ object Potentials {
192206
case Warm(cls, outer2) =>
193207
// widening to terminate
194208
val thisValue2 = thisValue match {
195-
case Warm(cls, outer) => Warm(cls, Cold()(outer2.source))(thisValue.source)
196-
case _ => thisValue
209+
case Warm(cls, outer) if outer.level > 2 =>
210+
Warm(cls, Cold()(outer2.source))(thisValue.source)
211+
212+
case _ =>
213+
thisValue
197214
}
198215

199216
val outer3 = asSeenFrom(outer2, thisValue2)

0 commit comments

Comments
 (0)