diff options
Diffstat (limited to 'src/dotty/tools')
-rw-r--r-- | src/dotty/tools/dotc/Compiler.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Contexts.scala | 3 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeComparer.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TyperState.scala | 53 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 11 | ||||
-rw-r--r-- | src/dotty/tools/dotc/printing/RefinedPrinter.scala | 7 | ||||
-rw-r--r-- | src/dotty/tools/dotc/reporting/Reporter.scala | 4 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Applications.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Implicits.scala | 29 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Inferencing.scala | 3 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 6 |
11 files changed, 94 insertions, 32 deletions
diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala index 8a37dba61..e6675237a 100644 --- a/src/dotty/tools/dotc/Compiler.scala +++ b/src/dotty/tools/dotc/Compiler.scala @@ -23,7 +23,7 @@ class Compiler { .withOwner(defn.RootClass) .withTyper(new Typer) .withNewMode(Mode.ImplicitsEnabled) - .withTyperState(new MutableTyperState(ctx.typerState, new ConsoleReporter()(ctx))) + .withTyperState(new MutableTyperState(ctx.typerState, new ConsoleReporter()(ctx), committable = true)) def addImport(ctx: Context, sym: Symbol) = ctx.fresh.withImportInfo(ImportInfo.rootImport(sym)(ctx)) (start.withRunInfo(new RunInfo(start)) /: rootImports)(addImport) diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala index 3110d8fd9..3de6337b1 100644 --- a/src/dotty/tools/dotc/core/Contexts.scala +++ b/src/dotty/tools/dotc/core/Contexts.scala @@ -288,7 +288,8 @@ object Contexts { def withPeriod(period: Period): this.type = { this.period = period; this } def withNewMode(mode: Mode): this.type = { this.mode = mode; this } def withTyperState(typerState: TyperState): this.type = { this.typerState = typerState; this } - def withNewTyperState: this.type = withTyperState(typerState.fresh) + def withNewTyperState: this.type = withTyperState(typerState.fresh(committable = true)) + def withExploreTyperState: this.type = withTyperState(typerState.fresh(committable = false)) def withPrinterFn(printer: Context => Printer): this.type = { this.printerFn = printer; this } def withOwner(owner: Symbol): this.type = { this.owner = owner; this } def withSettings(sstate: SettingsState): this.type = { this.sstate = sstate; this } diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala index 5701fcc95..cf24743bf 100644 --- a/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/src/dotty/tools/dotc/core/TypeComparer.scala @@ -796,7 +796,7 @@ class ExplainingTypeComparer(initctx: Context) extends TypeComparer(initctx) { } override def isSubType(tp1: Type, tp2: Type) = - traceIndented(s"${show(tp1)} <:< ${show(tp2)} ${tp1.getClass} ${tp2.getClass}") { + traceIndented(s"${show(tp1)} <:< ${show(tp2)}") { super.isSubType(tp1, tp2) } diff --git a/src/dotty/tools/dotc/core/TyperState.scala b/src/dotty/tools/dotc/core/TyperState.scala index 4fcfa323e..8ee219cec 100644 --- a/src/dotty/tools/dotc/core/TyperState.scala +++ b/src/dotty/tools/dotc/core/TyperState.scala @@ -29,32 +29,45 @@ class TyperState(val reporter: Reporter) extends DotClass with Showable { def undetVars_=(vs: Set[TypeVar]): Unit = unsupported("undetVars_=") def instType_=(m: SimpleMap[TypeVar, Type]): Unit = unsupported("instType_=") - def fresh: TyperState = this + def fresh(committable: Boolean): TyperState = this def commit()(implicit ctx: Context): Unit = unsupported("commit") @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 + override def toText(printer: Printer): Text = "ImmutableTyperState" } -class MutableTyperState(previous: TyperState, reporter: Reporter) +class MutableTyperState(previous: TyperState, reporter: Reporter, committable: Boolean) extends TyperState(reporter) { private var myConstraint: Constraint = previous.constraint private var myUndetVars: Set[TypeVar] = previous.undetVars private var myInstType: SimpleMap[TypeVar, Type] = previous.instType + private var checkingEnabled: Boolean = committable override def constraint = myConstraint override def undetVars = myUndetVars override def instType = myInstType - override def constraint_=(c: Constraint) = myConstraint = c - override def undetVars_=(vs: Set[TypeVar]) = myUndetVars = vs + override def constraint_=(c: Constraint) = { + myConstraint = c + checkConsistent() + } + override def undetVars_=(vs: Set[TypeVar]) = { + myUndetVars = vs + checkConsistent() + } override def instType_=(m: SimpleMap[TypeVar, Type]): Unit = myInstType = m - override def fresh: TyperState = new MutableTyperState(this, new StoreReporter) + override def fresh(committable: Boolean): TyperState = + new MutableTyperState(this, new StoreReporter, committable) /** Commit typer state so that its information is copied into current typer state * In addition (1) the owning state of undetermined or temporarily instantiated @@ -63,10 +76,13 @@ extends TyperState(reporter) { * instantiated instead. */ override def commit()(implicit ctx: Context) = { + checkConsistent val targetState = ctx.typerState + val prev = targetState.enableChecking(false) targetState.constraint = constraint targetState.undetVars = undetVars targetState.instType = instType + targetState.enableChecking(prev) def adjustOwningState(tvar: TypeVar) = if (tvar.owningState eq this) tvar.owningState = targetState @@ -84,8 +100,8 @@ extends TyperState(reporter) { } @elidable(elidable.FINER) - override def checkConsistent(implicit ctx: Context) = { - def err(msg: String, what: Showable) = s"$msg: ${what.show}\n${this.show}" + 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 <- undetVars) assert(constraint(tvar.origin).exists, err("unconstrained type var", tvar)) val undetParams = undetVars map (_.origin) @@ -96,6 +112,25 @@ extends TyperState(reporter) { } } + @elidable(elidable.FINER) + override def checkConsistent(implicit ctx: Context): Unit = checkConsistent(_.show) + + @elidable(elidable.FINER) + override def enableChecking(b: Boolean) = { + val prev = checkingEnabled + checkingEnabled = checkingEnabled && b + prev + } + + override def withCheckingDisabled[T](op: => T)(implicit ctx: Context): T = { + val prev = enableChecking(false) + try op + finally { + enableChecking(prev) + checkConsistent + } + } + override def toText(printer: Printer): Text = { val header: Text = "Typer state:" val undetVarsText = @@ -111,3 +146,7 @@ extends TyperState(reporter) { Text.lines(List(header, undetVarsText, constrainedText, constraintText, instTypeText)) } } + +object MutableTyperState { + private def toStr(x: Any) = x.toString +} diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 257128821..a7dadbd0e 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -1862,7 +1862,6 @@ object Types { owningState.undetVars -= this if (ctx.typerState eq creatorState) inst = tp else ctx.typerState.instType = ctx.typerState.instType.updated(this, tp) - ctx.typerState.checkConsistent // !!! DEBUG tp } @@ -1881,10 +1880,12 @@ object Types { case OrType(tp1, tp2) => isSingleton(tp1) & isSingleton(tp2) case _ => false } - var inst = ctx.typeComparer.approximate(origin, fromBelow) - if (fromBelow && isSingleton(inst) && !isSingleton(upperBound)) - inst = inst.widen - instantiateWith(inst) + ctx.typerState.withCheckingDisabled { + var inst = ctx.typeComparer.approximate(origin, fromBelow) + if (fromBelow && isSingleton(inst) && !isSingleton(upperBound)) + inst = inst.widen + instantiateWith(inst) + } } /** If the variable is instantiated, its instance, otherwise its origin */ diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala index bad2c071e..46a272c70 100644 --- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -98,7 +98,12 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { return (toTextLocal(tycon) ~ "[" ~ toTextGlobal(args, ", ") ~ "]").close } case tp @ TypeRef(pre, name) => - if (tp.symbol is TypeParam) return nameString(tp.symbol) + if (tp.symbol is TypeParam | TypeArgument) { + return tp.info match { + case TypeAlias(hi) => toText(hi) + case _ => nameString(tp.symbol) + } + } case _ => } super.toText(tp) diff --git a/src/dotty/tools/dotc/reporting/Reporter.scala b/src/dotty/tools/dotc/reporting/Reporter.scala index 9ef16d67a..6f5f3b5cb 100644 --- a/src/dotty/tools/dotc/reporting/Reporter.scala +++ b/src/dotty/tools/dotc/reporting/Reporter.scala @@ -97,8 +97,10 @@ trait Reporting { this: Context => def warning(msg: => String, pos: SourcePosition = NoSourcePosition): Unit = reporter.report(Diagnostic(msg, pos, WARNING)) - def error(msg: => String, pos: SourcePosition = NoSourcePosition): Unit = + def error(msg: => String, pos: SourcePosition = NoSourcePosition): Unit = { + // println("*** ERROR: " + msg) // !!! DEBUG reporter.report(Diagnostic(msg, pos, ERROR)) + } def incompleteInputError(msg: String, pos: SourcePosition = NoSourcePosition)(implicit ctx: Context): Unit = reporter.incomplete(Diagnostic(msg, pos, ERROR))(ctx) diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala index 05008ac1a..ef0fcf709 100644 --- a/src/dotty/tools/dotc/typer/Applications.scala +++ b/src/dotty/tools/dotc/typer/Applications.scala @@ -633,7 +633,7 @@ trait Applications extends Compatibility { self: Typer => * @param resultType The expected result type of the application */ def isApplicableToTrees(methRef: TermRef, args: List[Tree], resultType: Type)(implicit ctx: Context): Boolean = - new ApplicableToTrees(methRef, args, resultType)(ctx.fresh.withNewTyperState).success + new ApplicableToTrees(methRef, args, resultType)(ctx.fresh.withExploreTyperState).success def isApplicableToTrees(tp: Type, args: List[Tree], resultType: Type)(implicit ctx: Context): Boolean = tp match { case methRef: TermRef => isApplicableToTrees(methRef, args, resultType) @@ -647,7 +647,7 @@ trait Applications extends Compatibility { self: Typer => * @param resultType The expected result type of the application */ def isApplicableToTypes(methRef: TermRef, args: List[Type], resultType: Type = WildcardType)(implicit ctx: Context) = - new ApplicableToTypes(methRef, args, resultType)(ctx.fresh.withNewTyperState).success + new ApplicableToTypes(methRef, args, resultType)(ctx.fresh.withExploreTyperState).success def isApplicableToTypes(tp: Type, args: List[Type], resultType: Type)(implicit ctx: Context): Boolean = tp match { case methRef: TermRef => isApplicableToTypes(methRef, args, resultType) @@ -659,7 +659,7 @@ trait Applications extends Compatibility { self: Typer => /** Is `tp` a subtype of `pt`? */ def testCompatible(tp: Type, pt: Type)(implicit ctx: Context) = - isCompatible(tp, pt)(ctx.fresh.withNewTyperState) + isCompatible(tp, pt)(ctx.fresh.withExploreTyperState) /** In a set of overloaded applicable alternatives, is `alt1` at least as good as * `alt2`? `alt1` and `alt2` are nonoverloaded references. diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala index af36962a5..c84e3cbd6 100644 --- a/src/dotty/tools/dotc/typer/Implicits.scala +++ b/src/dotty/tools/dotc/typer/Implicits.scala @@ -37,9 +37,17 @@ object Implicits { /** Return those references in `refs` that are compatible with type `pt`. */ protected def filterMatching(pt: Type)(implicit ctx: Context): List[TermRef] = track("filterMatching") { - def result(implicit ctx: Context) = - refs filter (ref => isCompatible(normalize(ref), pt)) - result(ctx.fresh.withNewTyperState) // create a defensive copy of ctx to avoid constraint pollution + def result(implicit ctx: Context) = { + def refMatches(ref: TermRef) = { + if (ref.name.toString == "cb") { + println(i"refMatches ${ref.symbol}, ref = $ref, normalze = ${normalize(ref)}, pt = $pt = ${isCompatible(normalize(ref), pt)}") + println(err.typeMismatchStr(normalize(ref), pt)) + } + isCompatible(normalize(ref), pt) + } + refs filter refMatches + } + result(ctx.fresh.withExploreTyperState) // create a defensive copy of ctx to avoid constraint pollution } /** No further implicit conversions can be applied when searching for implicits. */ @@ -267,6 +275,9 @@ trait Implicits { self: Typer => /** An implicit search; parameters as in `inferImplicit` */ class ImplicitSearch(protected val pt: Type, protected val argument: Tree, pos: Position)(implicit ctx: Context) { + val initctx: Context = ctx.fresh.withNewTyperState.retractMode(ImplicitsEnabled) + def nestedContext = initctx.fresh.withNewTyperState + protected def nonMatchingImplicit(ref: TermRef): SearchFailure = NoImplicitMatches protected def shadowedImplicit(ref: TermRef, shadowing: Type): SearchFailure = NoImplicitMatches protected def failedSearch: SearchFailure = NoImplicitMatches @@ -277,12 +288,14 @@ trait Implicits { self: Typer => /** Try to typecheck an implicit reference */ def typedImplicit(ref: TermRef)(implicit ctx: Context): SearchResult = track("typedImplicit") { - ctx.typerState.checkConsistent // !!! DEBUG val id = Ident(ref).withPos(pos) val tree = - if (argument.isEmpty) adapt(id, pt) - else typedApply(id, ref, argument :: Nil, pt) - lazy val shadowing = typed(untpd.Ident(ref.name), ref).tpe + if (argument.isEmpty) + adapt(id, pt) + else + typed(untpd.Apply(untpd.TypedSplice(id), untpd.TypedSplice(argument) :: Nil), pt) + lazy val shadowing = + typed(untpd.Ident(ref.name), ref)(nestedContext).tpe if (ctx.typerState.reporter.hasErrors) nonMatchingImplicit(ref) else if (contextual && !(shadowing =:= ref)) shadowedImplicit(ref, shadowing) else SearchSuccess(tree)(ref, ctx.typerState) @@ -295,7 +308,7 @@ trait Implicits { self: Typer => */ def rankImplicits(pending: List[TermRef], acc: List[SearchSuccess]): List[SearchSuccess] = pending match { case ref :: pending1 => - typedImplicit(ref)(ctx.fresh.withNewTyperState.retractMode(ImplicitsEnabled)) match { + typedImplicit(ref)(nestedContext) match { case fail: SearchFailure => rankImplicits(pending1, acc) case best: SearchSuccess => diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala index 6f78409d0..8d85c1911 100644 --- a/src/dotty/tools/dotc/typer/Inferencing.scala +++ b/src/dotty/tools/dotc/typer/Inferencing.scala @@ -41,7 +41,7 @@ object Inferencing { isCompatible(normalize(mbrType), /*(new WildApprox) apply (needed?)*/ proto) name == nme.WILDCARD || { val mbr = tp1.member(name) - mbr.exists && mbr.hasAltWith(m => testCompatible(m.info)(ctx.fresh.withNewTyperState)) + mbr.exists && mbr.hasAltWith(m => testCompatible(m.info)(ctx.fresh.withExploreTyperState)) } } override def toString = "Proto" + super.toString @@ -207,7 +207,6 @@ object Inferencing { println(s"interpolate non-occurring ${tvar.show} in ${tp.show}") tvar.instantiate(fromBelow = true) } - ctx.typerState.checkConsistent } /** Instantiate undetermined type variables to that type `tp` is diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 8a4ee2d83..0e246480c 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -1084,8 +1084,10 @@ class Typer extends Namer with Applications with Implicits { case poly: PolyType => if (pt.isInstanceOf[PolyProto]) tree else { - val tracked = ctx.track(poly) - val tvars = ctx.newTypeVars(tracked, tree.pos) + val tvars = ctx.typerState.withCheckingDisabled { + val tracked = ctx.track(poly) + ctx.newTypeVars(tracked, tree.pos) + } adapt(tpd.TypeApply(tree, tvars map (tpd.TypeTree(_))), pt) } case wtp => |