Skip to content

Commit 2a5dbcb

Browse files
committed
Reuse current ProvisionalState if it is still valid
1 parent 1df045c commit 2a5dbcb

File tree

1 file changed

+27
-5
lines changed

1 file changed

+27
-5
lines changed

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

+27-5
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@ object Types extends TypeUtils {
109109
/** A cache indicating whether the type was still provisional, last time we checked */
110110
@sharable private var mightBeProvisional = true
111111

112+
// The provisonal state of a type stores the parts which could be changed and
113+
// their info at a given point.
114+
// For example, a `TypeVar` is provisional until it is permanently instantiated,
115+
// and its info is the current instantiation.
116+
type ProvisionalState = util.HashMap[Type, Type] | Null
117+
112118
/** Is this type still provisional? This is the case if the type contains, or depends on,
113119
* uninstantiated type variables or type symbols that have the Provisional flag set.
114120
* This is an antimonotonic property - once a type is not provisional, it stays so forever.
@@ -120,13 +126,28 @@ object Types extends TypeUtils {
120126
*/
121127
def isProvisional(using Context): Boolean = mightBeProvisional && currentProvisionalState != null
122128

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
129+
private var myCurrentProvisionalState: ProvisionalState = null
130+
131+
private def isCurrentProvisionalStateValid(using Context): Boolean =
132+
myCurrentProvisionalState != null
133+
&& myCurrentProvisionalState.uncheckedNN.iterator.forall: (tp, info) =>
134+
tp.mightBeProvisional && tp.match
135+
case tp: TypeRef =>
136+
if tp.currentSymbol.isProvisional then tp eq info
137+
else !tp.currentSymbol.isStatic && (tp.denot.infoOrCompleter eq info)
138+
case tp: TypeVar =>
139+
!tp.isPermanentlyInstantiated
140+
&& {
141+
val inst = tp.instanceOpt
142+
if inst.exists then inst eq info
143+
else tp eq info
144+
}
145+
case tp: LazyRef =>
146+
!tp.completed && (tp eq info)
147+
case _ => false
128148

129149
def currentProvisionalState(using Context): ProvisionalState =
150+
if isCurrentProvisionalStateValid then return myCurrentProvisionalState
130151
var state: ProvisionalState = null
131152
inline def record(tp: Type, info: Type): Unit =
132153
if state == null then state = util.HashMap()
@@ -197,6 +218,7 @@ object Types extends TypeUtils {
197218
t.mightBeProvisional
198219
end test
199220
test(this, null)
221+
myCurrentProvisionalState = state
200222
state
201223
end currentProvisionalState
202224

0 commit comments

Comments
 (0)