@@ -96,6 +96,41 @@ object Types {
96
96
nextId
97
97
}
98
98
99
+ /** A cache indicating whether the type was still provisional, last time we checked */
100
+ @ sharable private var mightBeProvisional = true
101
+
102
+ /** Is this type still provisional? This is the case if the type contains, or depends on,
103
+ * uninstantiated type variables or type symbols that have the Provisional flag set.
104
+ * This is an antimonotonic property - once a type is not provisional, it stays so forever.
105
+ */
106
+ def isProvisional (implicit ctx : Context ) = mightBeProvisional && testProvisional
107
+
108
+ private def testProvisional (implicit ctx : Context ) = {
109
+ val accu = new TypeAccumulator [Boolean ] {
110
+ override def apply (x : Boolean , t : Type ) =
111
+ x || t.mightBeProvisional && {
112
+ t.mightBeProvisional = t match {
113
+ case t : TypeVar =>
114
+ ! t.inst.exists
115
+ case t : TypeRef =>
116
+ (t : Type ).mightBeProvisional = false // break cycles
117
+ t.symbol.is(Provisional ) ||
118
+ apply(x, t.prefix) || {
119
+ t.info match {
120
+ case TypeAlias (alias) => apply(x, alias)
121
+ case TypeBounds (lo, hi) => apply(apply(x, lo), hi)
122
+ case _ => false
123
+ }
124
+ }
125
+ case _ =>
126
+ foldOver(x, t)
127
+ }
128
+ t.mightBeProvisional
129
+ }
130
+ }
131
+ accu.apply(false , this )
132
+ }
133
+
99
134
/** Is this type different from NoType? */
100
135
def exists : Boolean = true
101
136
@@ -590,7 +625,6 @@ object Types {
590
625
val next = tp.underlying
591
626
ctx.typerState.constraint.entry(tp) match {
592
627
case bounds : TypeBounds if bounds ne next =>
593
- ctx.typerState.ephemeral = true
594
628
go(bounds.hi)
595
629
case _ =>
596
630
go(next)
@@ -1667,9 +1701,7 @@ object Types {
1667
1701
private def computeDenot (implicit ctx : Context ): Denotation = {
1668
1702
1669
1703
def finish (d : Denotation ) = {
1670
- if (ctx.typerState.ephemeral)
1671
- record(" ephemeral cache miss: memberDenot" )
1672
- else if (d.exists)
1704
+ if (d.exists)
1673
1705
// Avoid storing NoDenotations in the cache - we will not be able to recover from
1674
1706
// them. The situation might arise that a type has NoDenotation in some later
1675
1707
// phase but a defined denotation earlier (e.g. a TypeRef to an abstract type
@@ -1696,23 +1728,19 @@ object Types {
1696
1728
finish(symd.current)
1697
1729
}
1698
1730
1699
- val savedEphemeral = ctx.typerState.ephemeral
1700
- ctx.typerState.ephemeral = false
1701
- try
1702
- lastDenotation match {
1703
- case lastd0 : SingleDenotation =>
1704
- val lastd = lastd0.skipRemoved
1705
- if (lastd.validFor.runId == ctx.runId) finish(lastd.current)
1706
- else lastd match {
1707
- case lastd : SymDenotation =>
1708
- if (ctx.stillValid(lastd)) finish(lastd.current)
1709
- else finish(memberDenot(lastd.initial.name, allowPrivate = false ))
1710
- case _ =>
1711
- fromDesignator
1712
- }
1713
- case _ => fromDesignator
1714
- }
1715
- finally ctx.typerState.ephemeral |= savedEphemeral
1731
+ lastDenotation match {
1732
+ case lastd0 : SingleDenotation =>
1733
+ val lastd = lastd0.skipRemoved
1734
+ if (lastd.validFor.runId == ctx.runId) finish(lastd.current)
1735
+ else lastd match {
1736
+ case lastd : SymDenotation =>
1737
+ if (ctx.stillValid(lastd)) finish(lastd.current)
1738
+ else finish(memberDenot(lastd.initial.name, allowPrivate = false ))
1739
+ case _ =>
1740
+ fromDesignator
1741
+ }
1742
+ case _ => fromDesignator
1743
+ }
1716
1744
}
1717
1745
1718
1746
private def disambiguate (d : Denotation )(implicit ctx : Context ): Denotation =
@@ -1797,7 +1825,7 @@ object Types {
1797
1825
1798
1826
lastDenotation = denot
1799
1827
lastSymbol = denot.symbol
1800
- checkedPeriod = ctx.period
1828
+ checkedPeriod = if (prefix.isProvisional) Nowhere else ctx.period
1801
1829
designator match {
1802
1830
case sym : Symbol if designator ne lastSymbol =>
1803
1831
designator = lastSymbol.asInstanceOf [Designator { type ThisName = self.ThisName }]
@@ -3138,20 +3166,13 @@ object Types {
3138
3166
3139
3167
override def superType (implicit ctx : Context ): Type = {
3140
3168
if (ctx.period != validSuper) {
3141
- validSuper = ctx.period
3142
3169
cachedSuper = tycon match {
3143
3170
case tycon : HKTypeLambda => defn.AnyType
3144
- case tycon : TypeVar if ! tycon.inst.exists =>
3145
- // supertype not stable, since underlying might change
3146
- validSuper = Nowhere
3147
- tycon.underlying.applyIfParameterized(args)
3148
- case tycon : TypeRef if tycon.symbol.isClass =>
3149
- tycon
3150
- case tycon : TypeProxy =>
3151
- if (tycon.typeSymbol.is(Provisional )) validSuper = Nowhere
3152
- tycon.superType.applyIfParameterized(args)
3171
+ case tycon : TypeRef if tycon.symbol.isClass => tycon
3172
+ case tycon : TypeProxy => tycon.superType.applyIfParameterized(args)
3153
3173
case _ => defn.AnyType
3154
3174
}
3175
+ validSuper = if (tycon.isProvisional) Nowhere else ctx.period
3155
3176
}
3156
3177
cachedSuper
3157
3178
}
@@ -3360,10 +3381,7 @@ object Types {
3360
3381
* uninstantiated
3361
3382
*/
3362
3383
def instanceOpt (implicit ctx : Context ): Type =
3363
- if (inst.exists) inst else {
3364
- ctx.typerState.ephemeral = true
3365
- ctx.typerState.instType(this )
3366
- }
3384
+ if (inst.exists) inst else ctx.typerState.instType(this )
3367
3385
3368
3386
/** Is the variable already instantiated? */
3369
3387
def isInstantiated (implicit ctx : Context ) = instanceOpt.exists
@@ -3403,11 +3421,7 @@ object Types {
3403
3421
/** If the variable is instantiated, its instance, otherwise its origin */
3404
3422
override def underlying (implicit ctx : Context ): Type = {
3405
3423
val inst = instanceOpt
3406
- if (inst.exists) inst
3407
- else {
3408
- ctx.typerState.ephemeral = true
3409
- origin
3410
- }
3424
+ if (inst.exists) inst else origin
3411
3425
}
3412
3426
3413
3427
override def computeHash (bs : Binders ): Int = identityHash(bs)
0 commit comments