@@ -100,7 +100,9 @@ object Types {
100100// }
101101
102102 /** 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
104106
105107 /** Is this type still provisional? This is the case if the type contains, or depends on,
106108 * uninstantiated type variables or type symbols that have the Provisional flag set.
@@ -160,7 +162,16 @@ object Types {
160162 * Like in isStableMember, "stability" means idempotence.
161163 * Rationale: If an expression has a stable type, the expression must be idempotent, so stable types
162164 * 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
164175 case tp : TermRef => tp.symbol.isStableMember && tp.prefix.isStable || tp.info.isStable
165176 case _ : SingletonType | NoPrefix => true
166177 case tp : RefinedOrRecType => tp.parent.isStable
@@ -175,9 +186,8 @@ object Types {
175186 // see: tests/explicit-nulls/pos/flow-stable.scala.disabled
176187 tp.tp1.isStable && (realizability(tp.tp2) eq Realizable ) ||
177188 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
179190 case _ => false
180- }
181191
182192 /** Is this type a (possibly refined or applied or aliased) type reference
183193 * to the given type symbol?
@@ -4161,23 +4171,11 @@ object Types {
41614171 // Boolean caches: 0 = uninitialized, -1 = false, 1 = true
41624172 private var myStableHash : Byte = 0
41634173 private var myGround : Byte = 0
4164- private var myIsStable : Byte = 0
4165-
41664174
41674175 def isGround (acc : TypeAccumulator [Boolean ])(using Context ): Boolean =
41684176 if myGround == 0 then myGround = if acc.foldOver(true , this ) then 1 else - 1
41694177 myGround > 0
41704178
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-
41814179 override def underlying (using Context ): Type = tycon
41824180
41834181 override def superType (using Context ): Type =
0 commit comments