From ea2596071b366a5aaa64fbc0f3f412b956be72e5 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 21 Jul 2017 16:38:31 +0200 Subject: [PATCH 1/4] Survive empty list in handlePositional --- compiler/src/dotty/tools/dotc/typer/Applications.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 284e954a423e..5e56a9bbea40 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -284,7 +284,8 @@ trait Applications extends Compatibility { self: Typer with Dynamic => case (arg: NamedArg @unchecked) :: _ => val nameAssocs = for (arg @ NamedArg(name, _) <- args) yield (name, arg) handleNamed(pnames, args, nameAssocs.toMap, Set()) - case arg :: args1 => arg :: handlePositional(pnames.tail, args1) + case arg :: args1 => + arg :: handlePositional(if (pnames.isEmpty) Nil else pnames.tail, args1) case Nil => Nil } From e5b891acc8ca87aa451407ccb202029dc14138c6 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 25 Jul 2017 14:17:21 +0200 Subject: [PATCH 2/4] Allow trees to get error types in IDE even if no errors were reported. --- compiler/src/dotty/tools/dotc/ast/Trees.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 271058a270a3..40aea19da8f6 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -115,7 +115,7 @@ object Trees { */ def withType(tpe: Type)(implicit ctx: Context): ThisTree[Type] = { if (tpe.isInstanceOf[ErrorType]) - assert(ctx.reporter.errorsReported) + assert(ctx.mode.is(Mode.Interactive) || ctx.reporter.errorsReported) else if (Config.checkTreesConsistent) checkChildrenTyped(productIterator) withTypeUnchecked(tpe) From 87f375c2cac31ef4ee01a2cb3c72bb7280ccf2f6 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 26 Jul 2017 13:50:32 +0200 Subject: [PATCH 3/4] Guard against completions in wrong runs We get sometimes stake symbol error because a completer is run in its creation context, which comes from a previous run. This should not happen. Adding an assert to flag the erronenous completion when it happens. --- compiler/src/dotty/tools/dotc/typer/Namer.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 2e84a2389a9f..7dd741666cdb 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -756,6 +756,7 @@ class Namer { typer: Typer => else levels(c.outer) + 1 completions.println(s"!!!completing ${denot.symbol.showLocated} in buried typerState, gap = ${levels(ctx)}") } + assert(ctx.runId == creationContext.runId, "completing $denot in wrong run ${ctx.runId}, was created in ${creationContext.runId}") completeInCreationContext(denot) } From 4af2401fdda48fef2be063146e9b2a794e5254e9 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 29 Jul 2017 18:39:18 +0200 Subject: [PATCH 4/4] Avoid infinite loop in parser Parser could get into an infinite loop because `acceptStatSepUnlessAtEnd` did not make progress. I believe the concrete example was a string interpolator where we encounter a `{ ... )`. --- compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 11 ++++++++++- tests/neg/i1779.scala | 4 ++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index b553e00f3740..0541c13f81d8 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -284,7 +284,16 @@ object Parsers { } def acceptStatSepUnlessAtEnd(altEnd: Token = EOF) = - if (!isStatSeqEnd && in.token != altEnd) acceptStatSep() + if (!isStatSeqEnd) + in.token match { + case EOF => + case `altEnd` => + case NEWLINE | NEWLINES => in.nextToken() + case SEMI => in.nextToken() + case _ => + in.nextToken() // needed to ensure progress; otherwise we might cycle forever + accept(SEMI) + } def errorTermTree = atPos(in.offset) { Literal(Constant(null)) } diff --git a/tests/neg/i1779.scala b/tests/neg/i1779.scala index 92100fa06230..cce32b57c89e 100644 --- a/tests/neg/i1779.scala +++ b/tests/neg/i1779.scala @@ -8,6 +8,6 @@ object Test { def f = { val _parent = 3 q"val hello = $_parent" - q"class $_" // error // error - } + q"class $_" // error + } // error }