From 6fe165feff33802da344b8961237cc14e3df4f9b Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 28 Dec 2017 14:25:52 +0100 Subject: [PATCH 1/4] Fix #3703: Various fixes to make printing more robust in face of errors --- compiler/src/dotty/tools/dotc/ast/Trees.scala | 6 +++++- .../src/dotty/tools/dotc/printing/Formatting.scala | 2 +- .../src/dotty/tools/dotc/printing/PlainPrinter.scala | 12 ++++++++++-- .../dotty/tools/dotc/printing/RefinedPrinter.scala | 2 +- tests/pos/i3703.scala | 12 ++++++++++++ 5 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 tests/pos/i3703.scala diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 5229995ae6cb..2c07a71ae904 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -113,7 +113,11 @@ object Trees { */ def withType(tpe: Type)(implicit ctx: Context): ThisTree[Type] = { if (tpe.isInstanceOf[ErrorType]) - assert(!Config.checkUnreportedErrors || ctx.reporter.errorsReported) + assert(!Config.checkUnreportedErrors || + ctx.reporter.errorsReported || + ctx.settings.YshowPrintErrors.value + // under -Yprint-show-errors, errors might arise during printing, but they do not count as reported + ) else if (Config.checkTreesConsistent) checkChildrenTyped(productIterator) withTypeUnchecked(tpe) diff --git a/compiler/src/dotty/tools/dotc/printing/Formatting.scala b/compiler/src/dotty/tools/dotc/printing/Formatting.scala index d16d49e82fac..e9f88523d8b8 100644 --- a/compiler/src/dotty/tools/dotc/printing/Formatting.scala +++ b/compiler/src/dotty/tools/dotc/printing/Formatting.scala @@ -34,7 +34,7 @@ object Formatting { case NonFatal(ex) if !ctx.mode.is(Mode.PrintShowExceptions) && !ctx.settings.YshowPrintErrors.value => - s"[cannot display due to $ex, raw string = $toString]" + s"[cannot display due to $ex, raw string = ${arg.toString}]" } case _ => arg.toString } diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index a6edd2ed7c4d..f5f503207e05 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -196,7 +196,12 @@ class PlainPrinter(_ctx: Context) extends Printer { else toText(tp.origin) } case tp: LazyRef => - "LazyRef(" ~ toTextGlobal(tp.ref) ~ ")" // TODO: only print this during debug mode? + def refTxt = + try toTextGlobal(tp.ref) + catch { + case ex: Throwable => Str("...") + } + "LazyRef(" ~ refTxt ~ ")" case _ => tp.fallbackToText(this) } @@ -217,7 +222,10 @@ class PlainPrinter(_ctx: Context) extends Printer { /** If -uniqid is set, the hashcode of the lambda type, after a # */ protected def lambdaHash(pt: LambdaType): Text = - if (ctx.settings.uniqid.value) "#" + pt.hashCode else "" + if (ctx.settings.uniqid.value) + try "#" + pt.hashCode + catch { case ex: NullPointerException => "" } + else "" /** If -uniqid is set, the unique id of symbol, after a # */ protected def idString(sym: Symbol): String = diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 57587541d036..fddd463e393c 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -501,7 +501,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { typeDefText(tparamsTxt, toText(rhs)) case LambdaTypeTree(tparams, body) => recur(body, tparamsText(tparams)) - case rhs: TypeTree if rhs.tpe.isInstanceOf[TypeBounds] => + case rhs: TypeTree if rhs.typeOpt.isInstanceOf[TypeBounds] => typeDefText(tparamsTxt, toText(rhs)) case rhs => typeDefText(tparamsTxt, optText(rhs)(" = " ~ _)) diff --git a/tests/pos/i3703.scala b/tests/pos/i3703.scala new file mode 100644 index 000000000000..5d767f6280d0 --- /dev/null +++ b/tests/pos/i3703.scala @@ -0,0 +1,12 @@ +package bar { + trait M[F[_]] + class S[XS[_] <: M[XS], A](val x: XS[A]) + object S { + def apply[X[_] <: M[X], A](x: X[A]): S[X, A] = S[X, A](x) + def unapply[X[_] <: M[X], A](p: S[X, A]): S[X, A] = S[X, A](p.x) + // type annotation required for dotc. scalac accepts also `= S(p.x)`. + } +} + + + From bd14d112914433e948de61c8eb1e7603acdf0218 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 28 Dec 2017 14:29:58 +0100 Subject: [PATCH 2/4] Add neg test to show it no longer crashes --- compiler/src/dotty/tools/dotc/ast/Trees.scala | 2 +- tests/neg/i3703.scala | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 tests/neg/i3703.scala diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 2c07a71ae904..429254d6c75c 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -116,7 +116,7 @@ object Trees { assert(!Config.checkUnreportedErrors || ctx.reporter.errorsReported || ctx.settings.YshowPrintErrors.value - // under -Yprint-show-errors, errors might arise during printing, but they do not count as reported + // under -Yshow-print-errors, errors might arise during printing, but they do not count as reported ) else if (Config.checkTreesConsistent) checkChildrenTyped(productIterator) diff --git a/tests/neg/i3703.scala b/tests/neg/i3703.scala new file mode 100644 index 000000000000..e1b299cafde1 --- /dev/null +++ b/tests/neg/i3703.scala @@ -0,0 +1,11 @@ +package bar { + trait M[F[_]] + class S[XS[_] <: M[XS], A](val x: XS[A]) + object S { + def apply[X[_] <: M[X], A](x: X[A]): S[X, A] = S[X, A](x) + def unapply[X[_] <: M[X], A](p: S[X, A]): S[X, A] = S(p.x) // error, scalac allows this but dotty fails to infer the type arguments. + } +} + + + From 9b48d071f982123ccd81c33a8de9a3bf79dcb9d8 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 14 Jan 2018 01:12:54 +0100 Subject: [PATCH 3/4] More test to pos It succeeds now, still worth keeping. --- tests/neg/i3703.scala | 11 ----------- tests/pos/i3703.scala | 4 +--- 2 files changed, 1 insertion(+), 14 deletions(-) delete mode 100644 tests/neg/i3703.scala diff --git a/tests/neg/i3703.scala b/tests/neg/i3703.scala deleted file mode 100644 index e1b299cafde1..000000000000 --- a/tests/neg/i3703.scala +++ /dev/null @@ -1,11 +0,0 @@ -package bar { - trait M[F[_]] - class S[XS[_] <: M[XS], A](val x: XS[A]) - object S { - def apply[X[_] <: M[X], A](x: X[A]): S[X, A] = S[X, A](x) - def unapply[X[_] <: M[X], A](p: S[X, A]): S[X, A] = S(p.x) // error, scalac allows this but dotty fails to infer the type arguments. - } -} - - - diff --git a/tests/pos/i3703.scala b/tests/pos/i3703.scala index 5d767f6280d0..0ee67ef0c8bf 100644 --- a/tests/pos/i3703.scala +++ b/tests/pos/i3703.scala @@ -3,9 +3,7 @@ package bar { class S[XS[_] <: M[XS], A](val x: XS[A]) object S { def apply[X[_] <: M[X], A](x: X[A]): S[X, A] = S[X, A](x) - def unapply[X[_] <: M[X], A](p: S[X, A]): S[X, A] = S[X, A](p.x) - // type annotation required for dotc. scalac accepts also `= S(p.x)`. - } + def unapply[X[_] <: M[X], A](p: S[X, A]): S[X, A] = S(p.x) } From 03c6526eb0c2fc97d64030d7c836c84b5882c30a Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 15 Jan 2018 10:22:12 +0100 Subject: [PATCH 4/4] Fix typo in test --- tests/pos/i3703.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/pos/i3703.scala b/tests/pos/i3703.scala index 0ee67ef0c8bf..9fa67efd330a 100644 --- a/tests/pos/i3703.scala +++ b/tests/pos/i3703.scala @@ -4,6 +4,7 @@ package bar { object S { def apply[X[_] <: M[X], A](x: X[A]): S[X, A] = S[X, A](x) def unapply[X[_] <: M[X], A](p: S[X, A]): S[X, A] = S(p.x) + } }