@@ -22,14 +22,18 @@ object Potentials {
22
22
23
23
/** A potential represents an aliasing of a value that is possibly under initialization */
24
24
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
+
26
31
def show (using Context ): String
27
32
def source : Tree
28
33
}
29
34
30
35
/** The object pointed by `this` */
31
36
case class ThisRef ()(val source : Tree ) extends Potential {
32
- val size : Int = 1
33
37
def show (using Context ): String = " this"
34
38
35
39
/** Effects of a method call or a lazy val access
@@ -49,7 +53,8 @@ object Potentials {
49
53
50
54
/** The object pointed by `C.super.this`, mainly used for override resolution */
51
55
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
53
58
def show (using Context ): String = pot.show + " .super[" + supercls.name.show + " ]"
54
59
}
55
60
@@ -60,7 +65,7 @@ object Potentials {
60
65
* @param outer The potential for `this` of the enclosing class
61
66
*/
62
67
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
64
69
def show (using Context ): String = " Warm[" + classSymbol.show + " , outer = " + outer.show + " ]"
65
70
66
71
/** Effects of a method call or a lazy val access
@@ -111,35 +116,44 @@ object Potentials {
111
116
*/
112
117
case class Outer (pot : Potential , classSymbol : ClassSymbol )(val source : Tree ) extends Potential {
113
118
// 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
115
121
def show (using Context ): String = pot.show + " .outer[" + classSymbol.show + " ]"
116
122
}
117
123
118
124
/** The object pointed by `this.f` */
119
125
case class FieldReturn (potential : Potential , field : Symbol )(val source : Tree ) extends Potential {
120
126
assert(field != NoSymbol )
121
127
122
- def size : Int = potential.size + 1
128
+ override def size : Int = potential.size + 1
129
+ override def level : Int = potential.size
123
130
def show (using Context ): String = potential.show + " ." + field.name.show
124
131
}
125
132
126
133
/** The object returned by `this.m()` */
127
134
case class MethodReturn (potential : Potential , method : Symbol )(val source : Tree ) extends Potential {
128
135
assert(method != NoSymbol )
129
136
130
- def size : Int = potential.size + 1
137
+ override def size : Int = potential.size + 1
138
+ override def level : Int = potential.size
131
139
def show (using Context ): String = potential.show + " ." + method.name.show
132
140
}
133
141
134
142
/** The object whose initialization status is unknown */
135
143
case class Cold ()(val source : Tree ) extends Potential {
136
- def size : Int = 1
137
144
def show (using Context ): String = " Cold"
138
145
}
139
146
140
147
/** A function when called will produce the `effects` and return the `potentials` */
141
148
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
+
143
157
def show (using Context ): String =
144
158
" Fun[pots = " + potentials.map(_.show).mkString(" ;" ) + " , effs = " + effects.map(_.show).mkString(" ;" ) + " ]"
145
159
}
@@ -192,8 +206,11 @@ object Potentials {
192
206
case Warm (cls, outer2) =>
193
207
// widening to terminate
194
208
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
197
214
}
198
215
199
216
val outer3 = asSeenFrom(outer2, thisValue2)
0 commit comments