diff options
author | Martin Odersky <odersky@gmail.com> | 2013-11-22 13:42:09 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2013-11-22 13:42:09 +0100 |
commit | b14291436172bf53cb40fdd2e94491e36a7da115 (patch) | |
tree | 67bb0321df0960ba283fc685b0233f0cebaa145c | |
parent | e38813ac1362a1d528dfa1ee79f0f8b0d6f7ccb8 (diff) | |
download | dotty-b14291436172bf53cb40fdd2e94491e36a7da115.tar.gz dotty-b14291436172bf53cb40fdd2e94491e36a7da115.tar.bz2 dotty-b14291436172bf53cb40fdd2e94491e36a7da115.zip |
Dropping cinsistency checking logic from typerstates.
Because of the new typerstate design, we can enforce most invariants by design, or in a purely local manner. We can therefore drop the checkConsistent checks and replace them with much more lightweight assertions that make sure that only committable states are committed and only committable states can create typevars.
-rw-r--r-- | src/dotty/tools/dotc/core/Constraint.scala | 12 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TyperState.scala | 85 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 10 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Inferencing.scala | 4 |
4 files changed, 32 insertions, 79 deletions
diff --git a/src/dotty/tools/dotc/core/Constraint.scala b/src/dotty/tools/dotc/core/Constraint.scala index 8ffdce71c..bee21d499 100644 --- a/src/dotty/tools/dotc/core/Constraint.scala +++ b/src/dotty/tools/dotc/core/Constraint.scala @@ -198,8 +198,16 @@ class Constraint(val myMap: SimpleMap[PolyType, Array[Type]]) extends AnyVal wit Text(assocs, "\n") } - override def toText(printer: Printer): Text = - "Constraint(" ~ constrainedTypesText(printer) ~ ") {" ~ constraintText(2, printer) ~ "}" + override def toText(printer: Printer): Text = { + val header: Text = "Constraint(" + val uninstVarsText = " uninstVars = " ~ + Text(uninstVars map (_.toText(printer)), ", ") ~ ";" + val constrainedText = + " constrained types = " ~ constrainedTypesText(printer) ~ ";" + val constraintsText = + " constraint = " ~ constraintText(3, printer) ~ ")" + Text.lines(List(header, uninstVarsText, constrainedText, constraintsText)) + } } object Constraint { diff --git a/src/dotty/tools/dotc/core/TyperState.scala b/src/dotty/tools/dotc/core/TyperState.scala index 8b5e2c85e..53782c642 100644 --- a/src/dotty/tools/dotc/core/TyperState.scala +++ b/src/dotty/tools/dotc/core/TyperState.scala @@ -10,17 +10,18 @@ import reporting._ import printing.{Showable, Printer} import printing.Texts._ import collection.mutable -import annotation.elidable class TyperState(val reporter: Reporter) extends DotClass with Showable { /** The current constraint set */ def constraint: Constraint = new Constraint(SimpleMap.Empty) + def constraint_=(c: Constraint): Unit = {} def uninstVars = constraint.uninstVars - /** A map that records for instantiated type vars their instance type. - * Used only in a temporary way for contexts that may be retracted + /** Gives for each instantiated type var that does not yet have its `inst` field + * set, the instance value stored in the constraint. Storing instances in constraints + * is done only in a temporary way for contexts that may be retracted * without also retracting the type var as a whole. */ def instType(tvar: TypeVar): Type = constraint.at(tvar.origin) match { @@ -28,20 +29,16 @@ class TyperState(val reporter: Reporter) extends DotClass with Showable { case tp => tp } - def constraint_=(c: Constraint): Unit = {} - + /** A fresh typer state with the same constraint as this one. + * @param isCommittable The constraint can be committed to an exclosing context. + */ def fresh(isCommittable: Boolean): TyperState = this + /** Commit state so that it gets propagated to enclosing context */ def commit()(implicit ctx: Context): Unit = unsupported("commit") - def isCommittable: Boolean = false - - @elidable(elidable.FINER) - def checkConsistent(implicit ctx: Context) = () - @elidable(elidable.FINER) - def enableChecking(b: Boolean): Boolean = true - - def withCheckingDisabled[T](op: => T)(implicit ctx: Context): T = op + /** Is it allowed to commit this state? */ + def isCommittable: Boolean = false override def toText(printer: Printer): Text = "ImmutableTyperState" } @@ -50,13 +47,9 @@ class MutableTyperState(previous: TyperState, reporter: Reporter, override val i extends TyperState(reporter) { private var myConstraint: Constraint = previous.constraint - private var checkingEnabled: Boolean = true override def constraint = myConstraint - override def constraint_=(c: Constraint) = { - myConstraint = c - checkConsistent() - } + override def constraint_=(c: Constraint) = myConstraint = c override def fresh(isCommittable: Boolean): TyperState = new MutableTyperState(this, new StoreReporter, isCommittable) @@ -68,11 +61,10 @@ extends TyperState(reporter) { * instantiated instead. */ override def commit()(implicit ctx: Context) = { - checkConsistent val targetState = ctx.typerState - val prev = targetState.enableChecking(false) + assert(isCommittable) + assert(targetState.isCommittable) targetState.constraint = constraint - targetState.enableChecking(prev) val toCollect = new mutable.ListBuffer[PolyType] constraint foreachTypeVar { tvar => @@ -90,59 +82,10 @@ extends TyperState(reporter) { for (poly <- toCollect) targetState.constraint = targetState.constraint.remove(poly) - targetState.checkConsistent // !!! DEBUG - reporter.flush() } - @elidable(elidable.FINER) - def checkConsistent(show: Showable => String = MutableTyperState.toStr): Unit = if (checkingEnabled) { - def err(msg: String, what: Showable) = s"$msg: ${show(what)}\n${show(this)}" - for (tvar <- uninstVars) - assert(constraint contains tvar.origin, err("unconstrained type var", tvar.origin)) - if (isCommittable) { - val undetParams = uninstVars map (_.origin) - for (param <- constraint.domainParams) - assert(undetParams contains param, err("junk constraint on", param)) - } - } - - @elidable(elidable.FINER) - override def checkConsistent(implicit ctx: Context): Unit = checkConsistent(_.show) - - @elidable(elidable.FINER) - override def enableChecking(b: Boolean) = { - val prev = checkingEnabled - checkingEnabled = b - prev - } - - override def withCheckingDisabled[T](op: => T)(implicit ctx: Context): T = { - val prev = enableChecking(false) - var thrown = false - try op - catch { - case ex: Throwable => - thrown = true - throw ex - } - finally { - enableChecking(prev) - if (!thrown) checkConsistent - } - } - - override def toText(printer: Printer): Text = { - val header: Text = "Typer state:" - val uninstVarsText = - " uninstVars: " ~ - Text(uninstVars map (_.toText(printer)), ", ") ~ "." - val constrainedText = - " constrained types: " ~ constraint.constrainedTypesText(printer) ~ "." - val constraintText = - " constraint: " ~ constraint.constraintText(3, printer) - Text.lines(List(header, uninstVarsText, constrainedText, constraintText)) - } + override def toText(printer: Printer): Text = constraint.toText(printer) } object MutableTyperState { diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index f530ff986..8796b19ad 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -2032,12 +2032,10 @@ object Types { case OrType(tp1, tp2) => isSingleton(tp1) & isSingleton(tp2) case _ => false } - ctx.typerState.withCheckingDisabled { - var inst = ctx.typeComparer.approximation(origin, fromBelow) - if (fromBelow && isSingleton(inst) && !isSingleton(upperBound)) - inst = inst.widen - instantiateWith(inst.simplified) - } + var inst = ctx.typeComparer.approximation(origin, fromBelow) + if (fromBelow && isSingleton(inst) && !isSingleton(upperBound)) + inst = inst.widen + instantiateWith(inst.simplified) } /** Unwrap to instance (if instantiated) or origin (if not), until result diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala index 8b3c19b71..599dc5f4e 100644 --- a/src/dotty/tools/dotc/typer/Inferencing.scala +++ b/src/dotty/tools/dotc/typer/Inferencing.scala @@ -208,6 +208,10 @@ object Inferencing { * @return The tracked polytype, and the list of created type variables. */ def track(pt: PolyType, owningTree: untpd.Tree): (PolyType, List[TypeVar]) = { + def howmany = if (owningTree.isEmpty) "no" else "some" + def committable = if (ctx.typerState.isCommittable) "committable" else "uncommittable" + assert(owningTree.isEmpty != ctx.typerState.isCommittable, + s"inconsistent: $howmany typevars were added to $committable constraint ${state.constraint}") val tracked = if (state.constraint contains pt) pt.copy(pt.paramNames, pt.paramBounds, pt.resultType) else pt |