Skip to content

Commit

Permalink
Reuse current ProvisionalState if it is still valid
Browse files Browse the repository at this point in the history
  • Loading branch information
noti0na1 committed Sep 4, 2024
1 parent 1df045c commit 2a5dbcb
Showing 1 changed file with 27 additions and 5 deletions.
32 changes: 27 additions & 5 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ object Types extends TypeUtils {
/** A cache indicating whether the type was still provisional, last time we checked */
@sharable private var mightBeProvisional = true

// The provisonal state of a type stores the parts which could be changed and
// their info at a given point.
// For example, a `TypeVar` is provisional until it is permanently instantiated,
// and its info is the current instantiation.
type ProvisionalState = util.HashMap[Type, Type] | Null

/** Is this type still provisional? This is the case if the type contains, or depends on,
* uninstantiated type variables or type symbols that have the Provisional flag set.
* This is an antimonotonic property - once a type is not provisional, it stays so forever.
Expand All @@ -120,13 +126,28 @@ object Types extends TypeUtils {
*/
def isProvisional(using Context): Boolean = mightBeProvisional && currentProvisionalState != null

// The provisonal state of a type stores the parts which might be changed and their
// info at a given point.
// For example, a `TypeVar` is provisional until it is permently instantiated,
// and its info is the current instantiation.
type ProvisionalState = util.HashMap[Type, Type] | Null
private var myCurrentProvisionalState: ProvisionalState = null

private def isCurrentProvisionalStateValid(using Context): Boolean =
myCurrentProvisionalState != null
&& myCurrentProvisionalState.uncheckedNN.iterator.forall: (tp, info) =>
tp.mightBeProvisional && tp.match
case tp: TypeRef =>
if tp.currentSymbol.isProvisional then tp eq info
else !tp.currentSymbol.isStatic && (tp.denot.infoOrCompleter eq info)
case tp: TypeVar =>
!tp.isPermanentlyInstantiated
&& {
val inst = tp.instanceOpt
if inst.exists then inst eq info
else tp eq info
}
case tp: LazyRef =>
!tp.completed && (tp eq info)
case _ => false

def currentProvisionalState(using Context): ProvisionalState =
if isCurrentProvisionalStateValid then return myCurrentProvisionalState
var state: ProvisionalState = null
inline def record(tp: Type, info: Type): Unit =
if state == null then state = util.HashMap()
Expand Down Expand Up @@ -197,6 +218,7 @@ object Types extends TypeUtils {
t.mightBeProvisional
end test
test(this, null)
myCurrentProvisionalState = state
state
end currentProvisionalState

Expand Down

0 comments on commit 2a5dbcb

Please sign in to comment.