Skip to content

Commit 8b08215

Browse files
committed
Cache Type#isStable
1 parent c5e2283 commit 8b08215

File tree

1 file changed

+14
-16
lines changed

1 file changed

+14
-16
lines changed

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

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

Comments
 (0)