Skip to content

Commit 566e8f7

Browse files
authored
Merge pull request #1719 from dotty-staging/fix-#1705
Fix #1707: Survive non-existing positions in parser
2 parents b26af1b + 3d20226 commit 566e8f7

File tree

2 files changed

+67
-33
lines changed

2 files changed

+67
-33
lines changed

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 43 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,15 @@ object Parsers {
8383
def atPos[T <: Positioned](start: Offset)(t: T): T =
8484
atPos(start, start)(t)
8585

86+
def startOffset(t: Positioned): Int =
87+
if (t.pos.exists) t.pos.start else in.offset
88+
89+
def pointOffset(t: Positioned): Int =
90+
if (t.pos.exists) t.pos.point else in.offset
91+
92+
def endOffset(t: Positioned): Int =
93+
if (t.pos.exists) t.pos.end else in.lastOffset
94+
8695
def nameStart: Offset =
8796
if (in.token == BACKQUOTED_IDENT) in.offset + 1 else in.offset
8897

@@ -448,7 +457,7 @@ object Parsers {
448457
val topInfo = opStack.head
449458
opStack = opStack.tail
450459
val od = reduceStack(base, topInfo.operand, 0, true)
451-
return atPos(od.pos.start, topInfo.offset) {
460+
return atPos(startOffset(od), topInfo.offset) {
452461
PostfixOp(od, topInfo.operator)
453462
}
454463
}
@@ -492,7 +501,7 @@ object Parsers {
492501

493502
/** Accept identifier acting as a selector on given tree `t`. */
494503
def selector(t: Tree): Tree =
495-
atPos(t.pos.start, in.offset) { Select(t, ident()) }
504+
atPos(startOffset(t), in.offset) { Select(t, ident()) }
496505

497506
/** Selectors ::= ident { `.' ident()
498507
*
@@ -728,7 +737,7 @@ object Parsers {
728737

729738
def refinedTypeRest(t: Tree): Tree = {
730739
newLineOptWhenFollowedBy(LBRACE)
731-
if (in.token == LBRACE) refinedTypeRest(atPos(t.pos.start) { RefinedTypeTree(t, refinement()) })
740+
if (in.token == LBRACE) refinedTypeRest(atPos(startOffset(t)) { RefinedTypeTree(t, refinement()) })
732741
else t
733742
}
734743

@@ -749,7 +758,7 @@ object Parsers {
749758
def annotType(): Tree = annotTypeRest(simpleType())
750759

751760
def annotTypeRest(t: Tree): Tree =
752-
if (in.token == AT) annotTypeRest(atPos(t.pos.start) { Annotated(t, annot()) })
761+
if (in.token == AT) annotTypeRest(atPos(startOffset(t)) { Annotated(t, annot()) })
753762
else t
754763

755764
/** SimpleType ::= SimpleType TypeArgs
@@ -780,19 +789,19 @@ object Parsers {
780789
val handleSingletonType: Tree => Tree = t =>
781790
if (in.token == TYPE) {
782791
in.nextToken()
783-
atPos(t.pos.start) { SingletonTypeTree(t) }
792+
atPos(startOffset(t)) { SingletonTypeTree(t) }
784793
} else t
785794

786795
private def simpleTypeRest(t: Tree): Tree = in.token match {
787796
case HASH => simpleTypeRest(typeProjection(t))
788-
case LBRACKET => simpleTypeRest(atPos(t.pos.start) { AppliedTypeTree(t, typeArgs(namedOK = true)) })
797+
case LBRACKET => simpleTypeRest(atPos(startOffset(t)) { AppliedTypeTree(t, typeArgs(namedOK = true)) })
789798
case _ => t
790799
}
791800

792801
private def typeProjection(t: Tree): Tree = {
793802
accept(HASH)
794803
val id = typeIdent()
795-
atPos(t.pos.start, id.pos.start) { Select(t, id.name) }
804+
atPos(startOffset(t), startOffset(id)) { Select(t, id.name) }
796805
}
797806

798807
/** NamedTypeArg ::= id `=' Type
@@ -846,7 +855,7 @@ object Parsers {
846855
val t = toplevelTyp()
847856
if (isIdent(nme.raw.STAR)) {
848857
in.nextToken()
849-
atPos(t.pos.start) { PostfixOp(t, nme.raw.STAR) }
858+
atPos(startOffset(t)) { PostfixOp(t, nme.raw.STAR) }
850859
} else t
851860
}
852861

@@ -971,7 +980,7 @@ object Parsers {
971980
val t = expr1(location)
972981
if (in.token == ARROW) {
973982
placeholderParams = saved
974-
closureRest(t.pos.start, location, convertToParams(t))
983+
closureRest(startOffset(t), location, convertToParams(t))
975984
}
976985
else if (isWildcard(t)) {
977986
placeholderParams = placeholderParams ::: saved
@@ -1025,7 +1034,7 @@ object Parsers {
10251034
assert(handlerStart != -1)
10261035
syntaxError(
10271036
new EmptyCatchBlock(body),
1028-
Position(handlerStart, handler.pos.end)
1037+
Position(handlerStart, endOffset(handler))
10291038
)
10301039
case _ =>
10311040
}
@@ -1035,7 +1044,7 @@ object Parsers {
10351044
else {
10361045
if (handler.isEmpty) warning(
10371046
EmptyCatchAndFinallyBlock(body),
1038-
source atPos Position(tryOffset, body.pos.end)
1047+
source atPos Position(tryOffset, endOffset(body))
10391048
)
10401049
EmptyTree
10411050
}
@@ -1057,21 +1066,21 @@ object Parsers {
10571066
case EQUALS =>
10581067
t match {
10591068
case Ident(_) | Select(_, _) | Apply(_, _) =>
1060-
atPos(t.pos.start, in.skipToken()) { Assign(t, expr()) }
1069+
atPos(startOffset(t), in.skipToken()) { Assign(t, expr()) }
10611070
case _ =>
10621071
t
10631072
}
10641073
case COLON =>
10651074
ascription(t, location)
10661075
case MATCH =>
1067-
atPos(t.pos.start, in.skipToken()) {
1076+
atPos(startOffset(t), in.skipToken()) {
10681077
inBraces(Match(t, caseClauses()))
10691078
}
10701079
case _ =>
10711080
t
10721081
}
10731082

1074-
def ascription(t: Tree, location: Location.Value) = atPos(t.pos.start, in.skipToken()) {
1083+
def ascription(t: Tree, location: Location.Value) = atPos(startOffset(t), in.skipToken()) {
10751084
in.token match {
10761085
case USCORE =>
10771086
val uscoreStart = in.skipToken()
@@ -1105,7 +1114,7 @@ object Parsers {
11051114
val id = termIdent()
11061115
val paramExpr =
11071116
if (location == Location.InBlock && in.token == COLON)
1108-
atPos(id.pos.start, in.skipToken()) { Typed(id, infixType()) }
1117+
atPos(startOffset(id), in.skipToken()) { Typed(id, infixType()) }
11091118
else
11101119
id
11111120
closureRest(start, location, convertToParam(paramExpr, mods) :: Nil)
@@ -1194,13 +1203,13 @@ object Parsers {
11941203
in.nextToken()
11951204
simpleExprRest(selector(t), canApply = true)
11961205
case LBRACKET =>
1197-
val tapp = atPos(t.pos.start, in.offset) { TypeApply(t, typeArgs(namedOK = true)) }
1206+
val tapp = atPos(startOffset(t), in.offset) { TypeApply(t, typeArgs(namedOK = true)) }
11981207
simpleExprRest(tapp, canApply = true)
11991208
case LPAREN | LBRACE if canApply =>
1200-
val app = atPos(t.pos.start, in.offset) { Apply(t, argumentExprs()) }
1209+
val app = atPos(startOffset(t), in.offset) { Apply(t, argumentExprs()) }
12011210
simpleExprRest(app, canApply = true)
12021211
case USCORE =>
1203-
atPos(t.pos.start, in.skipToken()) { PostfixOp(t, nme.WILDCARD) }
1212+
atPos(startOffset(t), in.skipToken()) { PostfixOp(t, nme.WILDCARD) }
12041213
case _ =>
12051214
t
12061215
}
@@ -1284,7 +1293,7 @@ object Parsers {
12841293
if (in.token == IF) guard()
12851294
else {
12861295
val pat = pattern1()
1287-
if (in.token == EQUALS) atPos(pat.pos.start, in.skipToken()) { GenAlias(pat, expr()) }
1296+
if (in.token == EQUALS) atPos(startOffset(pat), in.skipToken()) { GenAlias(pat, expr()) }
12881297
else generatorRest(pat)
12891298
}
12901299

@@ -1293,7 +1302,7 @@ object Parsers {
12931302
def generator(): Tree = generatorRest(pattern1())
12941303

12951304
def generatorRest(pat: Tree) =
1296-
atPos(pat.pos.start, accept(LARROW)) { GenFrom(pat, expr()) }
1305+
atPos(startOffset(pat), accept(LARROW)) { GenFrom(pat, expr()) }
12971306

12981307
/** ForExpr ::= `for' (`(' Enumerators `)' | `{' Enumerators `}')
12991308
* {nl} [`yield'] Expr
@@ -1357,7 +1366,7 @@ object Parsers {
13571366
val pattern = () => {
13581367
val pat = pattern1()
13591368
if (isIdent(nme.raw.BAR))
1360-
atPos(pat.pos.start) { Alternative(pat :: patternAlts()) }
1369+
atPos(startOffset(pat)) { Alternative(pat :: patternAlts()) }
13611370
else pat
13621371
}
13631372

@@ -1383,15 +1392,15 @@ object Parsers {
13831392
// compatibility for Scala2 `x @ _*` syntax
13841393
infixPattern() match {
13851394
case pt @ Ident(tpnme.WILDCARD_STAR) =>
1386-
migrationWarningOrError("The syntax `x @ _*' is no longer supported; use `x : _*' instead", p.pos.start)
1387-
atPos(p.pos.start, offset) { Typed(p, pt) }
1395+
migrationWarningOrError("The syntax `x @ _*' is no longer supported; use `x : _*' instead", startOffset(p))
1396+
atPos(startOffset(p), offset) { Typed(p, pt) }
13881397
case p =>
1389-
atPos(p.pos.start, offset) { Bind(name, p) }
1398+
atPos(startOffset(p), offset) { Bind(name, p) }
13901399
}
13911400
case p @ Ident(tpnme.WILDCARD_STAR) =>
13921401
// compatibility for Scala2 `_*` syntax
1393-
migrationWarningOrError("The syntax `_*' is no longer supported; use `x : _*' instead", p.pos.start)
1394-
atPos(p.pos.start) { Typed(Ident(nme.WILDCARD), p) }
1402+
migrationWarningOrError("The syntax `_*' is no longer supported; use `x : _*' instead", startOffset(p))
1403+
atPos(startOffset(p)) { Typed(Ident(nme.WILDCARD), p) }
13951404
case p =>
13961405
p
13971406
}
@@ -1415,7 +1424,7 @@ object Parsers {
14151424
val simplePattern = () => in.token match {
14161425
case IDENTIFIER | BACKQUOTED_IDENT | THIS =>
14171426
path(thisOK = true) match {
1418-
case id @ Ident(nme.raw.MINUS) if isNumericLit => literal(id.pos.start)
1427+
case id @ Ident(nme.raw.MINUS) if isNumericLit => literal(startOffset(id))
14191428
case t => simplePatternRest(t)
14201429
}
14211430
case USCORE =>
@@ -1445,9 +1454,9 @@ object Parsers {
14451454
def simplePatternRest(t: Tree): Tree = {
14461455
var p = t
14471456
if (in.token == LBRACKET)
1448-
p = atPos(t.pos.start, in.offset) { TypeApply(p, typeArgs()) }
1457+
p = atPos(startOffset(t), in.offset) { TypeApply(p, typeArgs()) }
14491458
if (in.token == LPAREN)
1450-
p = atPos(t.pos.start, in.offset) { Apply(p, argumentPatterns()) }
1459+
p = atPos(startOffset(t), in.offset) { Apply(p, argumentPatterns()) }
14511460
p
14521461
}
14531462

@@ -1573,7 +1582,8 @@ object Parsers {
15731582
case Select(qual, name) => cpy.Select(tree)(adjustStart(start)(qual), name)
15741583
case _ => tree
15751584
}
1576-
if (start < tree1.pos.start) tree1.withPos(tree1.pos.withStart(start))
1585+
if (tree1.pos.exists && start < tree1.pos.start)
1586+
tree1.withPos(tree1.pos.withStart(start))
15771587
else tree1
15781588
}
15791589

@@ -1771,7 +1781,7 @@ object Parsers {
17711781
case imp: Import =>
17721782
imp
17731783
case sel @ Select(qual, name) =>
1774-
val selector = atPos(sel.pos.point) { Ident(name) }
1784+
val selector = atPos(pointOffset(sel)) { Ident(name) }
17751785
cpy.Import(sel)(qual, selector :: Nil)
17761786
case t =>
17771787
accept(DOT)
@@ -1804,7 +1814,7 @@ object Parsers {
18041814
def importSelector(): Tree = {
18051815
val from = termIdentOrWildcard()
18061816
if (from.name != nme.WILDCARD && in.token == ARROW)
1807-
atPos(from.pos.start, in.skipToken()) {
1817+
atPos(startOffset(from), in.skipToken()) {
18081818
Thicket(from, termIdentOrWildcard())
18091819
}
18101820
else from
@@ -2085,7 +2095,7 @@ object Parsers {
20852095

20862096
/** Create a tree representing a packaging */
20872097
def makePackaging(start: Int, pkg: Tree, stats: List[Tree]): PackageDef = pkg match {
2088-
case x: RefTree => atPos(start, pkg.pos.point)(PackageDef(x, stats))
2098+
case x: RefTree => atPos(start, pointOffset(pkg))(PackageDef(x, stats))
20892099
}
20902100

20912101
/** Packaging ::= package QualId [nl] `{' TopStatSeq `}'

tests/neg/i1707.scala

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
object DepBug {
2+
class A {
3+
class B
4+
def mkB = new B
5+
def m(b: B) = b
6+
}
7+
trait Dep {
8+
val a: A
9+
val b: a.B
10+
}
11+
val dep = new {
12+
val a = new A
13+
val b = a mkB
14+
}
15+
def useDep(d: Dep) { // error: procedure syntax
16+
import d._
17+
a m (b)
18+
}
19+
{ // error: Null does not take parameters (follow on)
20+
import dep._
21+
a m (b)
22+
}
23+
dep.a m (dep b) // error (follow on)
24+
}

0 commit comments

Comments
 (0)