diff options
author | Martin Odersky <odersky@gmail.com> | 2014-10-26 15:46:38 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2014-10-26 16:24:02 +0100 |
commit | 70946d7e2f8f3ca69b2ebba63f7afe34a53946a6 (patch) | |
tree | 39df50c33520939fc0484cdf3d0df42359da6244 /src | |
parent | f459bf085d743c801fe724089438c0082014121f (diff) | |
download | dotty-70946d7e2f8f3ca69b2ebba63f7afe34a53946a6.tar.gz dotty-70946d7e2f8f3ca69b2ebba63f7afe34a53946a6.tar.bz2 dotty-70946d7e2f8f3ca69b2ebba63f7afe34a53946a6.zip |
Better tests and bugfix for named args
The original problem was that in an expression
f(x = bar(y = z))
only the outer named arg was eliminated by FirstTransform.
The first error was that the postcondition in FirstTransform did not get to the named arg, because
it got called from the overrdden typed method in TreeChecker, yet function arguments were evaluated
with typedUnadapted.
action: change Retyper and TreeChecker to override typedUndapped instead of typed.
This flushed out the second error: transformOther in FirstTransform needs to recursively transform the argument
of a NamedArg, because the framework itself does not handle NamedArg nodes.
Now, all tests pass except that TreeChecker itself fails -Ycheck:gettersSetters due to a problem
with handling by-name function types. This should be fixed in a separate PR.
Diffstat (limited to 'src')
-rw-r--r-- | src/dotty/tools/dotc/Compiler.scala | 3 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/FirstTransform.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/TreeChecker.scala | 26 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/ReTyper.scala | 4 |
4 files changed, 23 insertions, 12 deletions
diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala index ec899ebb8..d141b7488 100644 --- a/src/dotty/tools/dotc/Compiler.scala +++ b/src/dotty/tools/dotc/Compiler.scala @@ -53,7 +53,8 @@ class Compiler { new Literalize, new GettersSetters), List(new Erasure), - List(new CapturedVars, new Constructors), + List(new CapturedVars, + new Constructors), List(new LambdaLift) ) diff --git a/src/dotty/tools/dotc/transform/FirstTransform.scala b/src/dotty/tools/dotc/transform/FirstTransform.scala index 05255c982..fed47b160 100644 --- a/src/dotty/tools/dotc/transform/FirstTransform.scala +++ b/src/dotty/tools/dotc/transform/FirstTransform.scala @@ -123,7 +123,7 @@ class FirstTransform extends MiniPhaseTransform with IdentityDenotTransformer { override def transformOther(tree: Tree)(implicit ctx: Context, info: TransformerInfo) = tree match { case tree: Import => EmptyTree - case tree: NamedArg => tree.arg + case tree: NamedArg => transform(tree.arg) case AppliedTypeTree(tycon, args) => val tparams = tycon.tpe.typeSymbol.typeParams Checking.checkBounds( diff --git a/src/dotty/tools/dotc/transform/TreeChecker.scala b/src/dotty/tools/dotc/transform/TreeChecker.scala index 7ba570bea..4a7d280e5 100644 --- a/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -54,7 +54,13 @@ class TreeChecker { val checkingCtx = ctx.fresh .setTyperState(ctx.typerState.withReporter(new ThrowingReporter(ctx.typerState.reporter))) val checker = new Checker(previousPhases(phasesToRun.toList)(ctx)) - checker.typedExpr(ctx.compilationUnit.tpdTree)(checkingCtx) + try checker.typedExpr(ctx.compilationUnit.tpdTree)(checkingCtx) + catch { + case ex: Throwable => + implicit val ctx: Context = checkingCtx + println(i"*** error while checking after phase ${checkingCtx.phase.prev} ***") + throw ex + } } class Checker(phasesToCheck: Seq[Phase]) extends ReTyper { @@ -84,17 +90,17 @@ class TreeChecker { if (tree.symbol.maybeOwner.isTerm) assert(definedSyms contains tree.symbol, i"undefined symbol ${tree.symbol}") - override def typed(tree: untpd.Tree, pt: Type)(implicit ctx: Context) = { + override def typedUnadapted(tree: untpd.Tree, pt: Type)(implicit ctx: Context): tpd.Tree = { val res = tree match { case _: untpd.UnApply => // can't recheck patterns tree.asInstanceOf[tpd.Tree] case _: untpd.TypedSplice | _: untpd.Thicket | _: EmptyValDef[_] => - super.typed(tree) + super.typedUnadapted(tree) case _ if tree.isType => promote(tree) case _ => - val tree1 = super.typed(tree, pt) + val tree1 = super.typedUnadapted(tree, pt) def isSubType(tp1: Type, tp2: Type) = (tp1 eq tp2) || // accept NoType / NoType (tp1 <:< tp2) @@ -106,9 +112,10 @@ class TreeChecker { |After checking: ${tree1.show} |Why different : """.stripMargin + core.TypeComparer.explained((tp1 <:< tp2)(_)) - assert(isSubType(tree1.tpe, tree.typeOpt), divergenceMsg(tree1.tpe, tree.typeOpt)) + if (tree.hasType) // it might not be typed because Typer sometimes constructs new untyped trees and resubmits them to typedUnadapted + assert(isSubType(tree1.tpe, tree.typeOpt), divergenceMsg(tree1.tpe, tree.typeOpt)) tree1 - } + } phasesToCheck.foreach(_.checkPostCondition(res)) res } @@ -183,10 +190,13 @@ class TreeChecker { override def adapt(tree: Tree, pt: Type, original: untpd.Tree = untpd.EmptyTree)(implicit ctx: Context) = { def isPrimaryConstructorReturn = ctx.owner.isPrimaryConstructor && pt.isRef(ctx.owner.owner) && tree.tpe.isRef(defn.UnitClass) - if (ctx.mode.isExpr && !isPrimaryConstructorReturn && !pt.isInstanceOf[FunProto]) + if (ctx.mode.isExpr && + !tree.isEmpty && + !isPrimaryConstructorReturn && + !pt.isInstanceOf[FunProto]) assert(tree.tpe <:< pt, s"error at ${sourcePos(tree.pos)}\n" + - err.typeMismatchStr(tree.tpe, pt)) + err.typeMismatchStr(tree.tpe, pt) + "tree = " + tree) tree } } diff --git a/src/dotty/tools/dotc/typer/ReTyper.scala b/src/dotty/tools/dotc/typer/ReTyper.scala index f36e8e2fd..713549840 100644 --- a/src/dotty/tools/dotc/typer/ReTyper.scala +++ b/src/dotty/tools/dotc/typer/ReTyper.scala @@ -87,8 +87,8 @@ class ReTyper extends Typer { super.handleUnexpectedFunType(tree, fun) } - override def typed(tree: untpd.Tree, pt: Type)(implicit ctx: Context) = - try super.typed(tree, pt) + override def typedUnadapted(tree: untpd.Tree, pt: Type)(implicit ctx: Context) = + try super.typedUnadapted(tree, pt) catch { case ex: Throwable => println(i"exception while typing $tree of class ${tree.getClass} # ${tree.uniqueId}") |