Skip to content

Commit 7c81959

Browse files
committed
SI-8459 fix incorrect positions for incomplete selection trees
The mentioned issue is a presentation compiler issue, but its root cause is a bug in the parser which incorrectly assigned positions to incomplete selection trees (i.e. selections that lack an indentifier after dot and have some whitespace instead). In detail: for such incomplete selection trees, the "point" of the position should be immediately after the dot but instead was at the start of next token after the dot. For range positions, this caused a pathological situation where the "point" was greater than the "end" of the position. This position is later used by the typechecker during resolution of dynamic calls and causes it to crash. Of course, because a syntactically incorrect code is required for the bug to manifest, it only happens in the presentation compiler.
1 parent 190c672 commit 7c81959

File tree

4 files changed

+32
-1
lines changed

4 files changed

+32
-1
lines changed

src/compiler/scala/tools/nsc/ast/parser/Parsers.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1059,7 +1059,7 @@ self =>
10591059
def identOrMacro(): Name = if (isMacro) rawIdent() else ident()
10601060

10611061
def selector(t: Tree): Tree = {
1062-
val point = in.offset
1062+
val point = if(isIdent) in.offset else in.lastOffset //SI-8459
10631063
//assert(t.pos.isDefined, t)
10641064
if (t != EmptyTree)
10651065
Select(t, ident(skipIt = false)) setPos r2p(t.pos.start, point, in.lastOffset)

test/files/presentation/t8459.check

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
reload: IncompleteDynamicSelect.scala
2+
3+
askType at IncompleteDynamicSelect.scala(12,2)
4+
================================================================================
5+
[response] askTypeAt (12,2)
6+
scala.AnyRef {
7+
def <init>(): Foo = {
8+
Foo.super.<init>();
9+
()
10+
};
11+
private[this] val bar: F = new F();
12+
Foo.this.bar.<selectDynamic: error>("<error>")
13+
}
14+
================================================================================
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import scala.tools.nsc.interactive.tests.InteractiveTest
2+
3+
object Test extends InteractiveTest
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import scala.language.dynamics
2+
3+
class F extends Dynamic {
4+
def applyDynamic(name: String)(args: Any*) =
5+
s"method '$name' called with arguments ${args.mkString("'", "', '", "'")}"
6+
}
7+
8+
class Foo {
9+
val bar = new F
10+
11+
bar. //note whitespace after dot
12+
/*?*/ //force typechecking
13+
}
14+

0 commit comments

Comments
 (0)