From 966edc4d6bb2fd4be0b8706959e24e680969b23d Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 25 Jan 2014 12:59:26 +0100 Subject: Breaking out gc() method in TyperState. Will need to call from type comparer if instantiations were delayed --- src/dotty/tools/dotc/core/TypeComparer.scala | 16 +++++++++++++--- src/dotty/tools/dotc/core/TyperState.scala | 23 +++++++++++++++++------ 2 files changed, 30 insertions(+), 9 deletions(-) (limited to 'src') 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) -- cgit v1.2.3