@@ -100,7 +100,9 @@ object Types {
100
100
// }
101
101
102
102
/** A cache indicating whether the type was still provisional, last time we checked */
103
- @ sharable private var mightBeProvisional = true
103
+ @ sharable private var mightBeProvisional : Boolean = true
104
+
105
+ @ sharable private var myIsStable : Byte = 0
104
106
105
107
/** Is this type still provisional? This is the case if the type contains, or depends on,
106
108
* uninstantiated type variables or type symbols that have the Provisional flag set.
@@ -160,7 +162,16 @@ object Types {
160
162
* Like in isStableMember, "stability" means idempotence.
161
163
* Rationale: If an expression has a stable type, the expression must be idempotent, so stable types
162
164
* must be singleton types of stable expressions. */
163
- final def isStable (using Context ): Boolean = stripTypeVar match {
165
+ final def isStable (using Context ): Boolean =
166
+ if myIsStable == 0 then
167
+ val isStable = computeIsStable()
168
+ if ! isProvisional then
169
+ myIsStable = if isStable then 1 else - 1
170
+ isStable
171
+ else
172
+ myIsStable > 0
173
+
174
+ private final def computeIsStable ()(using Context ): Boolean = stripTypeVar match
164
175
case tp : TermRef => tp.symbol.isStableMember && tp.prefix.isStable || tp.info.isStable
165
176
case _ : SingletonType | NoPrefix => true
166
177
case tp : RefinedOrRecType => tp.parent.isStable
@@ -175,9 +186,8 @@ object Types {
175
186
// see: tests/explicit-nulls/pos/flow-stable.scala.disabled
176
187
tp.tp1.isStable && (realizability(tp.tp2) eq Realizable ) ||
177
188
tp.tp2.isStable && (realizability(tp.tp1) eq Realizable )
178
- case tp : AppliedType => tp.appliedTypeIsStable
189
+ case AppliedType ( tycon : TypeRef , args) if defn.isCompiletimeAppliedType(tycon.symbol) && args.forall(_.isStable) => true
179
190
case _ => false
180
- }
181
191
182
192
/** Is this type a (possibly refined or applied or aliased) type reference
183
193
* to the given type symbol?
@@ -4161,23 +4171,11 @@ object Types {
4161
4171
// Boolean caches: 0 = uninitialized, -1 = false, 1 = true
4162
4172
private var myStableHash : Byte = 0
4163
4173
private var myGround : Byte = 0
4164
- private var myIsStable : Byte = 0
4165
-
4166
4174
4167
4175
def isGround (acc : TypeAccumulator [Boolean ])(using Context ): Boolean =
4168
4176
if myGround == 0 then myGround = if acc.foldOver(true , this ) then 1 else - 1
4169
4177
myGround > 0
4170
4178
4171
- inline def appliedTypeIsStable (using Context ): Boolean =
4172
- if myIsStable == 0 then
4173
- val isStable : Byte = tycon match
4174
- case tycon : TypeRef if defn.isCompiletimeAppliedType(tycon.symbol) && args.forall(_.isStable) => 1
4175
- case _ => - 1
4176
- if ! isProvisional then myIsStable = isStable
4177
- isStable > 0
4178
- else
4179
- myIsStable > 0
4180
-
4181
4179
override def underlying (using Context ): Type = tycon
4182
4180
4183
4181
override def superType (using Context ): Type =
0 commit comments