From baade1cf48d6d78f3c5ec48a0cdb3ae2ede83300 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 2 Jan 2018 18:07:38 +0100 Subject: [PATCH 1/2] Fix #3383: Don't fail on unreported errors #3383 shows that there are valid cases where an error type is assigned to a tree before the error is reported. The error will then be reported later in `adapt`. --- compiler/src/dotty/tools/dotc/ast/Trees.scala | 6 +++--- compiler/src/dotty/tools/dotc/config/Config.scala | 12 ++++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index cb99e87407c1..1f538e4bfb06 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -112,9 +112,9 @@ object Trees { * type. (Overridden by empty trees) */ def withType(tpe: Type)(implicit ctx: Context): ThisTree[Type] = { - if (tpe.isInstanceOf[ErrorType]) - assert(ctx.mode.is(Mode.Interactive) || ctx.reporter.errorsReported) - else if (Config.checkTreesConsistent) + if (Config.checkUnreportedErrors) + if (tpe.isInstanceOf[ErrorType]) assert(ctx.reporter.errorsReported) + if (Config.checkTreesConsistent) checkChildrenTyped(productIterator) withTypeUnchecked(tpe) } diff --git a/compiler/src/dotty/tools/dotc/config/Config.scala b/compiler/src/dotty/tools/dotc/config/Config.scala index 60108d51d236..8abbb81bae85 100644 --- a/compiler/src/dotty/tools/dotc/config/Config.scala +++ b/compiler/src/dotty/tools/dotc/config/Config.scala @@ -106,6 +106,18 @@ object Config { */ final val checkTypeRefCycles = false + /** If this flag is set, we check that types assigned to trees are error types only + * if some error was already reported. There are complicicated scenarios where this + * is not true. An example is TestNonCyclic in posTwice. If we remove the + * first (unused) import `import dotty.tools.dotc.core.Types.Type` in `CompilationUnit`, + * we end up assigning a CyclicReference error type to an import expression `annotation` + * before the cyclic reference is reported. What happens is that the error was reported + * as a result of a completion in a not-yet committed typerstate. So we cannot enforce + * this in all circumstances. But since it is almost always true it is useful to + * keep the Config option for debugging. + */ + final val checkUnreportedErrors = false + /** If this flag is set, it is checked that class type parameters are * only references with NoPrefix or ThisTypes as prefixes. This option * is usally disabled, because there are still some legitimate cases where From 8afd9b3d7252acf24c97c45afe256f0d2c9c878e Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 3 Jan 2018 11:01:11 +0100 Subject: [PATCH 2/2] Change check logic to address reviewer's comments --- compiler/src/dotty/tools/dotc/ast/Trees.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 1f538e4bfb06..5229995ae6cb 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -112,9 +112,9 @@ object Trees { * type. (Overridden by empty trees) */ def withType(tpe: Type)(implicit ctx: Context): ThisTree[Type] = { - if (Config.checkUnreportedErrors) - if (tpe.isInstanceOf[ErrorType]) assert(ctx.reporter.errorsReported) - if (Config.checkTreesConsistent) + if (tpe.isInstanceOf[ErrorType]) + assert(!Config.checkUnreportedErrors || ctx.reporter.errorsReported) + else if (Config.checkTreesConsistent) checkChildrenTyped(productIterator) withTypeUnchecked(tpe) }