Skip to content

Commit 9205cc6

Browse files
committed
Cache AppliedType#isStable
1 parent 16fa957 commit 9205cc6

File tree

1 file changed

+23
-1
lines changed

1 file changed

+23
-1
lines changed

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

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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 AppliedType(tycon: TypeRef, args) if defn.isCompiletimeAppliedType(tycon.symbol) && args.forall(_.isStable) => true
178+
case tp: AppliedType => tp.cachedIsStable
179179
case _ => false
180180
}
181181

@@ -4162,10 +4162,32 @@ object Types {
41624162
private var myStableHash: Byte = 0
41634163
private var myGround: Byte = 0
41644164

4165+
private var myIsStablePeriod: Period = Nowhere
4166+
private var myIsStable: Boolean = false
4167+
41654168
def isGround(acc: TypeAccumulator[Boolean])(using Context): Boolean =
41664169
if myGround == 0 then myGround = if acc.foldOver(true, this) then 1 else -1
41674170
myGround > 0
41684171

4172+
private[Types] def cachedIsStable(using Context): Boolean =
4173+
// We need to invalidate the cache when the period changes because the
4174+
// case `TermRef` of `Type#isStable` reads denotations, which depend on
4175+
// the period. See docs/_docs/internals/periods.md for more information.
4176+
if myIsStablePeriod != ctx.period then
4177+
val res: Boolean = computeIsStable
4178+
// We don't cache if the type is provisional because `Type#isStable`
4179+
// calls `Type#stripTypeVar` which might return different results later.
4180+
if !isProvisional then
4181+
myIsStablePeriod = ctx.period
4182+
myIsStable = res
4183+
res
4184+
else
4185+
myIsStable
4186+
4187+
private def computeIsStable(using Context): Boolean = tycon match
4188+
case tycon: TypeRef if defn.isCompiletimeAppliedType(tycon.symbol) && args.forall(_.isStable) => true
4189+
case _ => false
4190+
41694191
override def underlying(using Context): Type = tycon
41704192

41714193
override def superType(using Context): Type =

0 commit comments

Comments
 (0)