aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools')
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala16
-rw-r--r--src/dotty/tools/dotc/core/TyperState.scala23
2 files changed, 30 insertions, 9 deletions
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index 0834c310f..dfa0180d1 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -34,12 +34,21 @@ class TypeComparer(initctx: Context) extends DotClass {
*/
protected var ignoreConstraint = false
+ private var needsGc = false
+
/** Is a subtype check in course? In that case we may not
* permanently instantiate type variables, because the corresponding
* constraint might still be retracted and the instantiation should
* then be reversed.
*/
- def subtypeCheckInProgress: Boolean = recCount >= 0
+ def subtypeCheckInProgress: Boolean = {
+ val result = recCount > 0
+ if (result) {
+ constr.println("*** needsGC ***")
+ needsGc = true
+ }
+ result
+ }
private var myAnyClass: ClassSymbol = null
private var myNothingClass: ClassSymbol = null
@@ -176,7 +185,7 @@ class TypeComparer(initctx: Context) extends DotClass {
def isNonBottomSubType(tp1: Type, tp2: Type): Boolean =
!(tp2 isRef NothingClass) && isSubType(tp1, tp2)
- def isSubType(tp1: Type, tp2: Type): Boolean = ctx.traceIndented(s"isSubType ${tp1.show} <:< ${tp2.show}", subtyping) {
+ def isSubType(tp1: Type, tp2: Type): Boolean = /*>|>*/ ctx.traceIndented(s"isSubType ${tp1.show} <:< ${tp2.show}", subtyping) /*<|<*/ {
if (tp1 == NoType || tp2 == NoType) false
else if (tp1 eq tp2) true
else {
@@ -196,6 +205,7 @@ class TypeComparer(initctx: Context) extends DotClass {
else monitoredIsSubType(tp1, tp2)
recCount -= 1
if (!result) constraint = saved
+ else if (recCount == 0 && needsGc) ctx.typerState.gc()
result
} catch {
case ex: Throwable =>
@@ -656,7 +666,7 @@ class TypeComparer(initctx: Context) extends DotClass {
// optimized case; all info on tp1.name2 is in refinement tp1.refinedInfo.
isSubType(tp1, parent2) && isSubType(tp1.refinedInfo, tp2.refinedInfo)
case _ =>
- def hasMatchingMember(name: Name): Boolean = traceIndented(s"hasMatchingMember($name) ${tp1.member(name)}") (
+ def hasMatchingMember(name: Name): Boolean = /*>|>*/ traceIndented(s"hasMatchingMember($name) ${tp1.member(name)}") /*<|<*/ (
tp1.member(name).hasAltWith(alt => isSubType(alt.info, tp2.refinedInfo))
||
{ // special case for situations like:
diff --git a/src/dotty/tools/dotc/core/TyperState.scala b/src/dotty/tools/dotc/core/TyperState.scala
index 455320ba8..13fbdbe15 100644
--- a/src/dotty/tools/dotc/core/TyperState.scala
+++ b/src/dotty/tools/dotc/core/TyperState.scala
@@ -38,6 +38,12 @@ class TyperState(val reporter: Reporter) extends DotClass with Showable {
/** Commit state so that it gets propagated to enclosing context */
def commit()(implicit ctx: Context): Unit = unsupported("commit")
+ /** Make type variable instances permanent by assigning to `inst` field if
+ * type variable instantiation cannot be retracted anymore. Then, remove
+ * no-longer needed constraint entries.
+ */
+ def gc(): Unit = ()
+
/** Is it allowed to commit this state? */
def isCommittable: Boolean = false
@@ -73,23 +79,28 @@ extends TyperState(reporter) {
assert(isCommittable)
targetState.constraint = constraint
- val toCollect = new mutable.ListBuffer[PolyType]
constraint foreachTypeVar { tvar =>
if (tvar.owningState eq this)
tvar.owningState = targetState
+ }
+ targetState.gc()
+ reporter.flush()
+ }
+
+ override def gc(): Unit = {
+ val toCollect = new mutable.ListBuffer[PolyType]
+ constraint foreachTypeVar { tvar =>
if (!tvar.inst.exists) {
val inst = instType(tvar)
- if (inst.exists && (tvar.owningState eq targetState)) {
+ if (inst.exists && (tvar.owningState eq this)) {
tvar.inst = inst
val poly = tvar.origin.binder
- if (targetState.constraint.isRemovable(poly)) toCollect += poly
+ if (constraint.isRemovable(poly)) toCollect += poly
}
}
}
for (poly <- toCollect)
- targetState.constraint = targetState.constraint.remove(poly)
-
- reporter.flush()
+ constraint = constraint.remove(poly)
}
override def toText(printer: Printer): Text = constraint.toText(printer)