Skip to content

Commit d3a71ed

Browse files
committed
Cache TermRef#isStable
1 parent c5e2283 commit d3a71ed

File tree

1 file changed

+16
-4
lines changed

1 file changed

+16
-4
lines changed

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

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ object Types {
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. */
163163
final def isStable(using Context): Boolean = stripTypeVar match {
164-
case tp: TermRef => tp.symbol.isStableMember && tp.prefix.isStable || tp.info.isStable
164+
case tp: TermRef => tp.cachedIsStable
165165
case _: SingletonType | NoPrefix => true
166166
case tp: RefinedOrRecType => tp.parent.isStable
167167
case tp: ExprType => tp.resultType.isStable
@@ -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 tp: AppliedType => tp.appliedTypeIsStable
178+
case tp: AppliedType => tp.cachedIsStable
179179
case _ => false
180180
}
181181

@@ -2665,6 +2665,19 @@ object Types {
26652665
override def designator: Designator = myDesignator
26662666
override protected def designator_=(d: Designator): Unit = myDesignator = d
26672667

2668+
var myIsStablePeriod: Period = Nowhere
2669+
var myIsStable: Boolean = false
2670+
2671+
inline def cachedIsStable(using Context): Boolean =
2672+
if myIsStablePeriod != ctx.period then
2673+
val isStable: Boolean = symbol.isStableMember && prefix.isStable || info.isStable
2674+
if !isProvisional then
2675+
myIsStablePeriod = ctx.period
2676+
myIsStable = isStable
2677+
isStable
2678+
else
2679+
myIsStable
2680+
26682681
//assert(name.toString != "<local Coder>")
26692682
override def underlying(using Context): Type = {
26702683
val d = denot
@@ -4163,12 +4176,11 @@ object Types {
41634176
private var myGround: Byte = 0
41644177
private var myIsStable: Byte = 0
41654178

4166-
41674179
def isGround(acc: TypeAccumulator[Boolean])(using Context): Boolean =
41684180
if myGround == 0 then myGround = if acc.foldOver(true, this) then 1 else -1
41694181
myGround > 0
41704182

4171-
inline def appliedTypeIsStable(using Context): Boolean =
4183+
inline def cachedIsStable(using Context): Boolean =
41724184
if myIsStable == 0 then
41734185
val isStable: Byte = tycon match
41744186
case tycon: TypeRef if defn.isCompiletimeAppliedType(tycon.symbol) && args.forall(_.isStable) => 1

0 commit comments

Comments
 (0)