Skip to content

Commit 1df045c

Browse files
committed
Resolve review commts
1 parent 4c6e80f commit 1df045c

File tree

1 file changed

+41
-65
lines changed

1 file changed

+41
-65
lines changed

Diff for: compiler/src/dotty/tools/dotc/core/Types.scala

+41-65
Original file line numberDiff line numberDiff line change
@@ -118,14 +118,20 @@ object Types extends TypeUtils {
118118
* a call to `resetInst`. This means all caches that rely on `isProvisional`
119119
* can likely end up returning stale results.
120120
*/
121-
// def isProvisional(using Context): Boolean = mightBeProvisional && testProvisional
122-
def isProvisional(using Context): Boolean = mightBeProvisional && !currentProvisionalState.isEmpty
121+
def isProvisional(using Context): Boolean = mightBeProvisional && currentProvisionalState != null
123122

124-
type ProvisionalState = util.HashMap[Type, Type]
123+
// The provisonal state of a type stores the parts which might be changed and their
124+
// info at a given point.
125+
// For example, a `TypeVar` is provisional until it is permently instantiated,
126+
// and its info is the current instantiation.
127+
type ProvisionalState = util.HashMap[Type, Type] | Null
125128

126129
def currentProvisionalState(using Context): ProvisionalState =
127-
val state: ProvisionalState = util.HashMap()
128-
// Compared to `testProvisional`, we don't use short-circuiting or,
130+
var state: ProvisionalState = null
131+
inline def record(tp: Type, info: Type): Unit =
132+
if state == null then state = util.HashMap()
133+
state.uncheckedNN(tp) = info
134+
// Compared to previous `testProvisional`, we don't use short-circuiting or (`||`),
129135
// because we want to collect all provisional types.
130136
class ProAcc extends TypeAccumulator[Boolean]:
131137
override def apply(x: Boolean, t: Type) = x | test(t, this)
@@ -137,7 +143,7 @@ object Types extends TypeUtils {
137143
// When t is a TypeRef and its symbol is provisional,
138144
// t will be considered provisional and its state is always updating.
139145
// We store itself as info.
140-
state(t) = t
146+
record(t, t)
141147
true
142148
else if !t.currentSymbol.isStatic then
143149
(t: Type).mightBeProvisional = false // break cycles
@@ -147,7 +153,7 @@ object Types extends TypeUtils {
147153
true
148154
else t.denot.infoOrCompleter.match
149155
case info: LazyType =>
150-
state(t) = info
156+
record(t, info)
151157
true
152158
case info: AliasingBounds =>
153159
test(info.alias, theAcc)
@@ -170,18 +176,18 @@ object Types extends TypeUtils {
170176
if inst.exists then
171177
// We want to store the temporary instance to the state
172178
// in order to reuse the cache when possible.
173-
state(t) = inst
179+
record(t, inst)
174180
test(inst, theAcc)
175181
else
176-
// When t is a TypeVar and does not have an instancication,
182+
// When t is a TypeVar and does not have an instantiation,
177183
// we store itself as info.
178-
state(t) = t
184+
record(t, t)
179185
true
180186
case t: LazyRef =>
181187
if !t.completed then
182188
// When t is a LazyRef and is not completed,
183189
// we store itself as info.
184-
state(t) = t
190+
record(t, t)
185191
true
186192
else
187193
test(t.ref, theAcc)
@@ -196,48 +202,17 @@ object Types extends TypeUtils {
196202

197203
def isStateUpToDate(
198204
currentState: ProvisionalState,
199-
lastState: ProvisionalState | Null)
205+
lastState: ProvisionalState)
200206
(using Context): Boolean =
201-
lastState != null
202-
&& currentState.size == lastState.size
203-
&& currentState.iterator.forall: (tp, info) =>
204-
lastState.contains(tp) && {
205-
tp match
206-
case tp: TypeRef => (info ne tp) && (info eq lastState(tp))
207-
case _=> info eq lastState(tp)
208-
}
209-
210-
// private def testProvisional(using Context): Boolean =
211-
// class ProAcc extends TypeAccumulator[Boolean]:
212-
// override def apply(x: Boolean, t: Type) = x || test(t, this)
213-
// def test(t: Type, theAcc: TypeAccumulator[Boolean] | Null): Boolean =
214-
// if t.mightBeProvisional then
215-
// t.mightBeProvisional = t match
216-
// case t: TypeRef =>
217-
// t.currentSymbol.isProvisional || !t.currentSymbol.isStatic && {
218-
// (t: Type).mightBeProvisional = false // break cycles
219-
// test(t.prefix, theAcc)
220-
// || t.denot.infoOrCompleter.match
221-
// case info: LazyType => true
222-
// case info: AliasingBounds => test(info.alias, theAcc)
223-
// case TypeBounds(lo, hi) => test(lo, theAcc) || test(hi, theAcc)
224-
// case _ => false
225-
// }
226-
// case t: TermRef =>
227-
// !t.currentSymbol.isStatic && test(t.prefix, theAcc)
228-
// case t: AppliedType =>
229-
// t.fold(false, (x, tp) => x || test(tp, theAcc))
230-
// case t: TypeVar =>
231-
// !t.isPermanentlyInstantiated || test(t.permanentInst, theAcc)
232-
// case t: LazyRef =>
233-
// !t.completed || test(t.ref, theAcc)
234-
// case _ =>
235-
// (if theAcc != null then theAcc else ProAcc()).foldOver(false, t)
236-
// end if
237-
// t.mightBeProvisional
238-
// end test
239-
// test(this, null)
240-
// end testProvisional
207+
(currentState eq lastState)
208+
|| currentState != null && lastState != null
209+
&& currentState.size == lastState.size
210+
&& currentState.iterator.forall: (tp, info) =>
211+
lastState.contains(tp) && {
212+
tp match
213+
case tp: TypeRef => (info ne tp) && (info eq lastState(tp))
214+
case _ => info eq lastState(tp)
215+
}
241216

242217
/** Is this type different from NoType? */
243218
final def exists: Boolean = this.ne(NoType)
@@ -1398,8 +1373,6 @@ object Types extends TypeUtils {
13981373
final def widen(using Context): Type = this match
13991374
case _: TypeRef | _: MethodOrPoly => this // fast path for most frequent cases
14001375
case tp: TermRef => // fast path for next most frequent case
1401-
// Don't call `isOverloaded` and `underlying` on `tp` directly,
1402-
// to avoid computing provisional state twice.
14031376
val denot = tp.denot
14041377
if denot.isOverloaded then tp else denot.info.widen
14051378
case tp: SingletonType => tp.underlying.widen
@@ -1414,10 +1387,12 @@ object Types extends TypeUtils {
14141387
/** Widen from singleton type to its underlying non-singleton
14151388
* base type by applying one or more `underlying` dereferences.
14161389
*/
1417-
final def widenSingleton(using Context): Type = stripped match {
1418-
case tp: SingletonType if !tp.isOverloaded => tp.underlying.widenSingleton
1390+
final def widenSingleton(using Context): Type = stripped match
1391+
case tp: TermRef =>
1392+
val denot = tp.denot
1393+
if denot.isOverloaded then this else denot.info.widenSingleton
1394+
case tp: SingletonType => tp.underlying.widenSingleton
14191395
case _ => this
1420-
}
14211396

14221397
/** Widen from TermRef to its underlying non-termref
14231398
* base type, while also skipping Expr types.
@@ -2395,12 +2370,12 @@ object Types extends TypeUtils {
23952370

23962371
private var myName: Name | Null = null
23972372
private var lastDenotation: Denotation | Null = null
2398-
private var lastDenotationProvState: ProvisionalState | Null = null
2373+
private var lastDenotationProvState: ProvisionalState = null
23992374
private var lastSymbol: Symbol | Null = null
24002375
private var checkedPeriod: Period = Nowhere
24012376
private var myStableHash: Byte = 0
24022377
private var mySignature: Signature = uninitialized
2403-
private var mySignatureProvState: ProvisionalState | Null = null
2378+
private var mySignatureProvState: ProvisionalState = null
24042379
private var mySignatureRunId: Int = NoRunId
24052380

24062381
// Invariants:
@@ -2473,7 +2448,9 @@ object Types extends TypeUtils {
24732448
final def symbol(using Context): Symbol =
24742449
// We can rely on checkedPeriod (unlike in the definition of `denot` below)
24752450
// because SymDenotation#installAfter never changes the symbol
2476-
if (checkedPeriod.code == ctx.period.code) lastSymbol.asInstanceOf[Symbol]
2451+
if checkedPeriod.code == ctx.period.code
2452+
&& isStateUpToDate(prefix.currentProvisionalState, lastDenotationProvState) then
2453+
lastSymbol.asInstanceOf[Symbol]
24772454
else computeSymbol
24782455

24792456
private def computeSymbol(using Context): Symbol =
@@ -2482,7 +2459,6 @@ object Types extends TypeUtils {
24822459
if (sym.isValidInCurrentRun) sym else denot.symbol
24832460
case name =>
24842461
(if (denotationIsCurrent) lastDenotation.asInstanceOf[Denotation] else denot).symbol
2485-
if checkedPeriod.code != NowhereCode then checkedPeriod = ctx.period
24862462
result
24872463

24882464
/** There is a denotation computed which is valid (somewhere in) the
@@ -2532,8 +2508,8 @@ object Types extends TypeUtils {
25322508
// Even if checkedPeriod == now we still need to recheck lastDenotation.validFor
25332509
// as it may have been mutated by SymDenotation#installAfter
25342510
if checkedPeriod.code != NowhereCode
2535-
&& isStateUpToDate(prefix.currentProvisionalState, lastDenotationProvState)
25362511
&& lastd.validFor.contains(ctx.period)
2512+
&& isStateUpToDate(prefix.currentProvisionalState, lastDenotationProvState)
25372513
then lastd
25382514
else computeDenot
25392515

@@ -3959,13 +3935,13 @@ object Types extends TypeUtils {
39593935
// (3) myScala2SignatureRunId != NoRunId => myScala2Signature != null
39603936

39613937
private var mySignature: Signature = uninitialized
3962-
private var mySignatureProvState: ProvisionalState | Null = null
3938+
private var mySignatureProvState: ProvisionalState = null
39633939
private var mySignatureRunId: Int = NoRunId
39643940
private var myJavaSignature: Signature = uninitialized
3965-
private var myJavaSignatureProvState: ProvisionalState | Null = null
3941+
private var myJavaSignatureProvState: ProvisionalState = null
39663942
private var myJavaSignatureRunId: Int = NoRunId
39673943
private var myScala2Signature: Signature = uninitialized
3968-
private var myScala2SignatureProvState: ProvisionalState | Null = null
3944+
private var myScala2SignatureProvState: ProvisionalState = null
39693945
private var myScala2SignatureRunId: Int = NoRunId
39703946

39713947
/** If `isJava` is false, the Scala signature of this method. Otherwise, its Java signature.

0 commit comments

Comments
 (0)