Skip to content

Commit 9bfc2f5

Browse files
committed
Override isStable in child classes instead of using pattern matching
1 parent 259be87 commit 9bfc2f5

File tree

1 file changed

+23
-20
lines changed

1 file changed

+23
-20
lines changed

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)