@@ -160,24 +160,7 @@ object Types {
160160 * Like in isStableMember, "stability" means idempotence.
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. */
163- final def isStable (using Context ): Boolean = stripTypeVar match {
164- case tp : TermRef => tp.cachedIsStable
165- case _ : SingletonType | NoPrefix => true
166- case tp : RefinedOrRecType => tp.parent.isStable
167- case tp : ExprType => tp.resultType.isStable
168- case tp : AnnotatedType =>
169- // NOTE UncheckedStableAnnot was originally meant to be put on fields,
170- // not on types. Allowing it on types is a Scala 3 extension. See:
171- // https://www.scala-lang.org/files/archive/spec/2.11/11-annotations.html#scala-compiler-annotations
172- tp.annot.symbol == defn.UncheckedStableAnnot || tp.parent.isStable
173- case tp : AndType =>
174- // TODO: fix And type check when tp contains type parames for explicit-nulls flow-typing
175- // see: tests/explicit-nulls/pos/flow-stable.scala.disabled
176- tp.tp1.isStable && (realizability(tp.tp2) eq Realizable ) ||
177- tp.tp2.isStable && (realizability(tp.tp1) eq Realizable )
178- case tp : AppliedType => tp.cachedIsStable
179- case _ => false
180- }
163+ def isStable (using Context ): Boolean = false
181164
182165 /** Is this type a (possibly refined or applied or aliased) type reference
183166 * to the given type symbol?
@@ -2035,6 +2018,7 @@ object Types {
20352018 */
20362019 trait SingletonType extends TypeProxy with ValueType {
20372020 def isOverloaded (using Context ): Boolean = false
2021+ override def isStable (using Context ): Boolean = true
20382022 }
20392023
20402024 /** A trait for types that bind other types that refer to them.
@@ -2668,7 +2652,7 @@ object Types {
26682652 var myIsStablePeriod : Period = Nowhere
26692653 var myIsStable : Boolean = false
26702654
2671- private [ Types ] def cachedIsStable (using Context ): Boolean =
2655+ override def isStable (using Context ): Boolean =
26722656 if myIsStablePeriod != ctx.period then
26732657 val isStable : Boolean = symbol.isStableMember && prefix.isStable || info.isStable
26742658 if ! isProvisional then
@@ -2957,6 +2941,7 @@ object Types {
29572941
29582942 abstract class RefinedOrRecType extends CachedProxyType with ValueType {
29592943 def parent : Type
2944+ override def isStable (using Context ): Boolean = parent.isStable
29602945 }
29612946
29622947 /** A refined type parent { refinement }
@@ -3201,6 +3186,12 @@ object Types {
32013186 case that : AndType => tp1.eq(that.tp1) && tp2.eq(that.tp2)
32023187 case _ => false
32033188 }
3189+
3190+ override def isStable (using Context ): Boolean =
3191+ // TODO: fix And type check when tp contains type parames for explicit-nulls flow-typing
3192+ // see: tests/explicit-nulls/pos/flow-stable.scala.disabled
3193+ tp1.isStable && (realizability(tp2) eq Realizable ) ||
3194+ tp2.isStable && (realizability(tp1) eq Realizable )
32043195 }
32053196
32063197 final class CachedAndType (tp1 : Type , tp2 : Type ) extends AndType (tp1, tp2)
@@ -3427,6 +3418,8 @@ object Types {
34273418 case that : ExprType => resType.eq(that.resType)
34283419 case _ => false
34293420 }
3421+
3422+ override def isStable (using Context ): Boolean = resultType.isStable
34303423
34313424 // equals comes from case class; no matching override is needed
34323425
@@ -4182,7 +4175,7 @@ object Types {
41824175 if myGround == 0 then myGround = if acc.foldOver(true , this ) then 1 else - 1
41834176 myGround > 0
41844177
4185- private [ Types ] def cachedIsStable (using Context ): Boolean =
4178+ override def isStable (using Context ): Boolean =
41864179 if myIsStablePeriod != ctx.period then
41874180 val res = tycon match
41884181 case tycon : TypeRef if defn.isCompiletimeAppliedType(tycon.symbol) && args.forall(_.isStable) => true
@@ -4825,6 +4818,8 @@ object Types {
48254818
48264819 override def stripped (using Context ): Type = stripTypeVar.stripped
48274820
4821+ override def isStable (using Context ): Boolean = stripTypeVar.isStable
4822+
48284823 /** If the variable is instantiated, its instance, otherwise its origin */
48294824 override def underlying (using Context ): Type = {
48304825 val inst = instanceOpt
@@ -5273,6 +5268,13 @@ object Types {
52735268 isRefiningCache
52745269 }
52755270
5271+ override def isStable (using Context ): Boolean = stripTypeVar match
5272+ case AnnotatedType (parent, annot) =>
5273+ // NOTE UncheckedStableAnnot was originally meant to be put on fields,
5274+ // not on types. Allowing it on types is a Scala 3 extension. See:
5275+ // https://www.scala-lang.org/files/archive/spec/2.11/11-annotations.html#scala-compiler-annotations
5276+ annot.symbol == defn.UncheckedStableAnnot || parent.isStable
5277+
52765278 // equals comes from case class; no matching override is needed
52775279
52785280 override def computeHash (bs : Binders ): Int =
@@ -5328,6 +5330,7 @@ object Types {
53285330 /** Missing prefix */
53295331 @ sharable case object NoPrefix extends CachedGroundType {
53305332 override def computeHash (bs : Binders ): Int = hashSeed
5333+ override def isStable (using Context ): Boolean = true
53315334 }
53325335
53335336 /** A common superclass of `ErrorType` and `TryDynamicCallSite`. Instances of this
0 commit comments