@@ -161,7 +161,7 @@ object Types {
161161 * Rationale: If an expression has a stable type, the expression must be idempotent, so stable types
162162 * must be singleton types of stable expressions. */
163163 final def isStable (using Context ): Boolean = stripTypeVar match {
164- case tp : TermRef => tp.symbol.isStableMember && tp.prefix.isStable || tp.info.isStable
164+ case tp : TermRef => tp.cachedIsStable
165165 case _ : SingletonType | NoPrefix => true
166166 case tp : RefinedOrRecType => tp.parent.isStable
167167 case tp : ExprType => tp.resultType.isStable
@@ -175,7 +175,7 @@ object Types {
175175 // see: tests/explicit-nulls/pos/flow-stable.scala.disabled
176176 tp.tp1.isStable && (realizability(tp.tp2) eq Realizable ) ||
177177 tp.tp2.isStable && (realizability(tp.tp1) eq Realizable )
178- case tp : AppliedType => tp.appliedTypeIsStable
178+ case tp : AppliedType => tp.cachedIsStable
179179 case _ => false
180180 }
181181
@@ -2665,6 +2665,19 @@ object Types {
26652665 override def designator : Designator = myDesignator
26662666 override protected def designator_= (d : Designator ): Unit = myDesignator = d
26672667
2668+ var myIsStablePeriod : Period = Nowhere
2669+ var myIsStable : Boolean = false
2670+
2671+ inline def cachedIsStable (using Context ): Boolean =
2672+ if myIsStablePeriod != ctx.period then
2673+ val isStable : Boolean = symbol.isStableMember && prefix.isStable || info.isStable
2674+ if ! isProvisional then
2675+ myIsStablePeriod = ctx.period
2676+ myIsStable = isStable
2677+ isStable
2678+ else
2679+ myIsStable
2680+
26682681 // assert(name.toString != "<local Coder>")
26692682 override def underlying (using Context ): Type = {
26702683 val d = denot
@@ -4163,12 +4176,11 @@ object Types {
41634176 private var myGround : Byte = 0
41644177 private var myIsStable : Byte = 0
41654178
4166-
41674179 def isGround (acc : TypeAccumulator [Boolean ])(using Context ): Boolean =
41684180 if myGround == 0 then myGround = if acc.foldOver(true , this ) then 1 else - 1
41694181 myGround > 0
41704182
4171- inline def appliedTypeIsStable (using Context ): Boolean =
4183+ inline def cachedIsStable (using Context ): Boolean =
41724184 if myIsStable == 0 then
41734185 val isStable : Byte = tycon match
41744186 case tycon : TypeRef if defn.isCompiletimeAppliedType(tycon.symbol) && args.forall(_.isStable) => 1
0 commit comments