@@ -160,24 +160,7 @@ object Types {
160
160
* Like in isStableMember, "stability" means idempotence.
161
161
* Rationale: If an expression has a stable type, the expression must be idempotent, so stable types
162
162
* 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
181
164
182
165
/** Is this type a (possibly refined or applied or aliased) type reference
183
166
* to the given type symbol?
@@ -2035,6 +2018,7 @@ object Types {
2035
2018
*/
2036
2019
trait SingletonType extends TypeProxy with ValueType {
2037
2020
def isOverloaded (using Context ): Boolean = false
2021
+ override def isStable (using Context ): Boolean = true
2038
2022
}
2039
2023
2040
2024
/** A trait for types that bind other types that refer to them.
@@ -2668,7 +2652,7 @@ object Types {
2668
2652
var myIsStablePeriod : Period = Nowhere
2669
2653
var myIsStable : Boolean = false
2670
2654
2671
- private [ Types ] def cachedIsStable (using Context ): Boolean =
2655
+ override def isStable (using Context ): Boolean =
2672
2656
if myIsStablePeriod != ctx.period then
2673
2657
val isStable : Boolean = symbol.isStableMember && prefix.isStable || info.isStable
2674
2658
if ! isProvisional then
@@ -2957,6 +2941,7 @@ object Types {
2957
2941
2958
2942
abstract class RefinedOrRecType extends CachedProxyType with ValueType {
2959
2943
def parent : Type
2944
+ override def isStable (using Context ): Boolean = parent.isStable
2960
2945
}
2961
2946
2962
2947
/** A refined type parent { refinement }
@@ -3201,6 +3186,12 @@ object Types {
3201
3186
case that : AndType => tp1.eq(that.tp1) && tp2.eq(that.tp2)
3202
3187
case _ => false
3203
3188
}
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 )
3204
3195
}
3205
3196
3206
3197
final class CachedAndType (tp1 : Type , tp2 : Type ) extends AndType (tp1, tp2)
@@ -3427,6 +3418,8 @@ object Types {
3427
3418
case that : ExprType => resType.eq(that.resType)
3428
3419
case _ => false
3429
3420
}
3421
+
3422
+ override def isStable (using Context ): Boolean = resultType.isStable
3430
3423
3431
3424
// equals comes from case class; no matching override is needed
3432
3425
@@ -4182,7 +4175,7 @@ object Types {
4182
4175
if myGround == 0 then myGround = if acc.foldOver(true , this ) then 1 else - 1
4183
4176
myGround > 0
4184
4177
4185
- private [ Types ] def cachedIsStable (using Context ): Boolean =
4178
+ override def isStable (using Context ): Boolean =
4186
4179
if myIsStablePeriod != ctx.period then
4187
4180
val res = tycon match
4188
4181
case tycon : TypeRef if defn.isCompiletimeAppliedType(tycon.symbol) && args.forall(_.isStable) => true
@@ -4825,6 +4818,8 @@ object Types {
4825
4818
4826
4819
override def stripped (using Context ): Type = stripTypeVar.stripped
4827
4820
4821
+ override def isStable (using Context ): Boolean = stripTypeVar.isStable
4822
+
4828
4823
/** If the variable is instantiated, its instance, otherwise its origin */
4829
4824
override def underlying (using Context ): Type = {
4830
4825
val inst = instanceOpt
@@ -5273,6 +5268,13 @@ object Types {
5273
5268
isRefiningCache
5274
5269
}
5275
5270
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
+
5276
5278
// equals comes from case class; no matching override is needed
5277
5279
5278
5280
override def computeHash (bs : Binders ): Int =
@@ -5328,6 +5330,7 @@ object Types {
5328
5330
/** Missing prefix */
5329
5331
@ sharable case object NoPrefix extends CachedGroundType {
5330
5332
override def computeHash (bs : Binders ): Int = hashSeed
5333
+ override def isStable (using Context ): Boolean = true
5331
5334
}
5332
5335
5333
5336
/** A common superclass of `ErrorType` and `TryDynamicCallSite`. Instances of this
0 commit comments