From 3c8545b8293b903ffe9178060ad1b630f19762f1 Mon Sep 17 00:00:00 2001 From: "Paolo G. Giarrusso" Date: Tue, 1 May 2018 23:38:49 +0200 Subject: [PATCH 1/4] Prevent position errors on Ident(nme.ERROR) ``` Exception in thread "main" java.lang.AssertionError: assertion failed: position error: position not set for Ident() # 24 at dotty.DottyPredef$.assertFail(DottyPredef.scala:36) at dotty.tools.dotc.ast.Positioned.check$1(Positioned.scala:178) at dotty.tools.dotc.ast.Positioned.check$5$$anonfun$4(Positioned.scala:203) ``` --- compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 12 ++++++++++-- tests/neg/parser-stability-23.scala | 3 +++ 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 tests/neg/parser-stability-23.scala diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index edaf6850d8cf..5a8cfd3a4bea 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -518,8 +518,16 @@ object Parsers { } /** Accept identifier and return Ident with its name as a term name. */ - def termIdent(): Ident = atPos(in.offset) { - makeIdent(in.token, ident()) + def termIdent(): Ident = { + val start = in.offset + val id = makeIdent(in.token, ident()) + if (id.name != nme.ERROR) { + atPos(start)(id) + } else { + // error identifiers don't consume any characters, so atPos(start)(id) wouldn't set a position. + // Some testcases would then fail in Positioned.checkPos. Set a position anyway! + atPos(start, start, in.lastOffset)(id) + } } /** Accept identifier and return Ident with its name as a type name. */ diff --git a/tests/neg/parser-stability-23.scala b/tests/neg/parser-stability-23.scala new file mode 100644 index 000000000000..b8db4d937f25 --- /dev/null +++ b/tests/neg/parser-stability-23.scala @@ -0,0 +1,3 @@ +object i0 { + import Ordering.{ implicitly => } (true: Boolean) match { case _: i1 => true } // error // error +} From ad04880cd3f1af0e7e147e7fc31499c26ee7207f Mon Sep 17 00:00:00 2001 From: "Paolo G. Giarrusso" Date: Wed, 2 May 2018 18:10:31 +0200 Subject: [PATCH 2/4] Revert parts of "Prevent position errors on Ident(nme.ERROR)" This reverts commit 0f7b1b0bba2f644141796be5217c3019ee643b2f but keeps the testcase. --- compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 5a8cfd3a4bea..edaf6850d8cf 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -518,16 +518,8 @@ object Parsers { } /** Accept identifier and return Ident with its name as a term name. */ - def termIdent(): Ident = { - val start = in.offset - val id = makeIdent(in.token, ident()) - if (id.name != nme.ERROR) { - atPos(start)(id) - } else { - // error identifiers don't consume any characters, so atPos(start)(id) wouldn't set a position. - // Some testcases would then fail in Positioned.checkPos. Set a position anyway! - atPos(start, start, in.lastOffset)(id) - } + def termIdent(): Ident = atPos(in.offset) { + makeIdent(in.token, ident()) } /** Accept identifier and return Ident with its name as a type name. */ From 83610bb6fe4bd12e15b1462dd819bdb6bb079c4c Mon Sep 17 00:00:00 2001 From: "Paolo G. Giarrusso" Date: Wed, 2 May 2018 18:06:37 +0200 Subject: [PATCH 3/4] Alternative fix --- .../src/dotty/tools/dotc/parsing/Parsers.scala | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index edaf6850d8cf..4afea33c5798 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1975,11 +1975,24 @@ object Parsers { /** ImportSelector ::= id [`=>' id | `=>' `_'] */ def importSelector(): Tree = { + val start = in.offset val from = termIdentOrWildcard() if (from.name != nme.WILDCARD && in.token == ARROW) atPos(startOffset(from), in.skipToken()) { - Thicket(from, termIdentOrWildcard()) + val start2 = in.offset + val to = termIdentOrWildcard() + val toWithPos = + if (to.name == nme.ERROR) + // error identifiers don't consume any characters, so atPos(start)(id) wouldn't set a position. + // Some testcases would then fail in Positioned.checkPos. Set a position anyway! + atPos(start2, start2, in.lastOffset)(to) + else + to + Thicket(from, toWithPos) } + else if (from.name == nme.ERROR) { + atPos(start, start, in.lastOffset)(from) + } else from } From 78afe8a3e81eb45da95c8164945c5d26e8237f86 Mon Sep 17 00:00:00 2001 From: "Paolo G. Giarrusso" Date: Wed, 2 May 2018 18:13:47 +0200 Subject: [PATCH 4/4] Simplify fix --- compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 4afea33c5798..18e10817477f 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1975,24 +1975,20 @@ object Parsers { /** ImportSelector ::= id [`=>' id | `=>' `_'] */ def importSelector(): Tree = { - val start = in.offset val from = termIdentOrWildcard() if (from.name != nme.WILDCARD && in.token == ARROW) atPos(startOffset(from), in.skipToken()) { - val start2 = in.offset + val start = in.offset val to = termIdentOrWildcard() val toWithPos = if (to.name == nme.ERROR) // error identifiers don't consume any characters, so atPos(start)(id) wouldn't set a position. // Some testcases would then fail in Positioned.checkPos. Set a position anyway! - atPos(start2, start2, in.lastOffset)(to) + atPos(start, start, in.lastOffset)(to) else to Thicket(from, toWithPos) } - else if (from.name == nme.ERROR) { - atPos(start, start, in.lastOffset)(from) - } else from }