diff options
-rw-r--r-- | compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 71 | ||||
-rw-r--r-- | tests/neg/i1705.scala | 24 |
2 files changed, 64 insertions, 31 deletions
diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index fa0576c7a..838f7514c 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -83,6 +83,14 @@ object Parsers { def atPos[T <: Positioned](start: Offset)(t: T): T = atPos(start, start)(t) + /** Defensive version of Position#start */ + def startPos(t: Positioned): Int = + if (t.pos.exists) t.pos.start else in.offset + + /** Defensive version of Position#end */ + def endPos(t: Positioned): Int = + if (t.pos.exists) t.pos.end else in.lastOffset + def nameStart: Offset = if (in.token == BACKQUOTED_IDENT) in.offset + 1 else in.offset @@ -448,7 +456,7 @@ object Parsers { val topInfo = opStack.head opStack = opStack.tail val od = reduceStack(base, topInfo.operand, 0, true) - return atPos(od.pos.start, topInfo.offset) { + return atPos(startPos(od), topInfo.offset) { PostfixOp(od, topInfo.operator) } } @@ -492,7 +500,7 @@ object Parsers { /** Accept identifier acting as a selector on given tree `t`. */ def selector(t: Tree): Tree = - atPos(t.pos.start, in.offset) { Select(t, ident()) } + atPos(startPos(t), in.offset) { Select(t, ident()) } /** Selectors ::= ident { `.' ident() * @@ -728,7 +736,7 @@ object Parsers { def refinedTypeRest(t: Tree): Tree = { newLineOptWhenFollowedBy(LBRACE) - if (in.token == LBRACE) refinedTypeRest(atPos(t.pos.start) { RefinedTypeTree(t, refinement()) }) + if (in.token == LBRACE) refinedTypeRest(atPos(startPos(t)) { RefinedTypeTree(t, refinement()) }) else t } @@ -749,7 +757,7 @@ object Parsers { def annotType(): Tree = annotTypeRest(simpleType()) def annotTypeRest(t: Tree): Tree = - if (in.token == AT) annotTypeRest(atPos(t.pos.start) { Annotated(t, annot()) }) + if (in.token == AT) annotTypeRest(atPos(startPos(t)) { Annotated(t, annot()) }) else t /** SimpleType ::= SimpleType TypeArgs @@ -780,19 +788,19 @@ object Parsers { val handleSingletonType: Tree => Tree = t => if (in.token == TYPE) { in.nextToken() - atPos(t.pos.start) { SingletonTypeTree(t) } + atPos(startPos(t)) { SingletonTypeTree(t) } } else t private def simpleTypeRest(t: Tree): Tree = in.token match { case HASH => simpleTypeRest(typeProjection(t)) - case LBRACKET => simpleTypeRest(atPos(t.pos.start) { AppliedTypeTree(t, typeArgs(namedOK = true)) }) + case LBRACKET => simpleTypeRest(atPos(startPos(t)) { AppliedTypeTree(t, typeArgs(namedOK = true)) }) case _ => t } private def typeProjection(t: Tree): Tree = { accept(HASH) val id = typeIdent() - atPos(t.pos.start, id.pos.start) { Select(t, id.name) } + atPos(startPos(t), startPos(id)) { Select(t, id.name) } } /** NamedTypeArg ::= id `=' Type @@ -846,7 +854,7 @@ object Parsers { val t = toplevelTyp() if (isIdent(nme.raw.STAR)) { in.nextToken() - atPos(t.pos.start) { PostfixOp(t, nme.raw.STAR) } + atPos(startPos(t)) { PostfixOp(t, nme.raw.STAR) } } else t } @@ -971,7 +979,7 @@ object Parsers { val t = expr1(location) if (in.token == ARROW) { placeholderParams = saved - closureRest(t.pos.start, location, convertToParams(t)) + closureRest(startPos(t), location, convertToParams(t)) } else if (isWildcard(t)) { placeholderParams = placeholderParams ::: saved @@ -1025,7 +1033,7 @@ object Parsers { assert(handlerStart != -1) syntaxError( new EmptyCatchBlock(body), - Position(handlerStart, handler.pos.end) + Position(handlerStart, endPos(handler)) ) case _ => } @@ -1035,7 +1043,7 @@ object Parsers { else { if (handler.isEmpty) warning( EmptyCatchAndFinallyBlock(body), - source atPos Position(tryOffset, body.pos.end) + source atPos Position(tryOffset, endPos(body)) ) EmptyTree } @@ -1057,21 +1065,21 @@ object Parsers { case EQUALS => t match { case Ident(_) | Select(_, _) | Apply(_, _) => - atPos(t.pos.start, in.skipToken()) { Assign(t, expr()) } + atPos(startPos(t), in.skipToken()) { Assign(t, expr()) } case _ => t } case COLON => ascription(t, location) case MATCH => - atPos(t.pos.start, in.skipToken()) { + atPos(startPos(t), in.skipToken()) { inBraces(Match(t, caseClauses())) } case _ => t } - def ascription(t: Tree, location: Location.Value) = atPos(t.pos.start, in.skipToken()) { + def ascription(t: Tree, location: Location.Value) = atPos(startPos(t), in.skipToken()) { in.token match { case USCORE => val uscoreStart = in.skipToken() @@ -1105,7 +1113,7 @@ object Parsers { val id = termIdent() val paramExpr = if (location == Location.InBlock && in.token == COLON) - atPos(id.pos.start, in.skipToken()) { Typed(id, infixType()) } + atPos(startPos(id), in.skipToken()) { Typed(id, infixType()) } else id closureRest(start, location, convertToParam(paramExpr, mods) :: Nil) @@ -1194,13 +1202,13 @@ object Parsers { in.nextToken() simpleExprRest(selector(t), canApply = true) case LBRACKET => - val tapp = atPos(t.pos.start, in.offset) { TypeApply(t, typeArgs(namedOK = true)) } + val tapp = atPos(startPos(t), in.offset) { TypeApply(t, typeArgs(namedOK = true)) } simpleExprRest(tapp, canApply = true) case LPAREN | LBRACE if canApply => - val app = atPos(t.pos.start, in.offset) { Apply(t, argumentExprs()) } + val app = atPos(startPos(t), in.offset) { Apply(t, argumentExprs()) } simpleExprRest(app, canApply = true) case USCORE => - atPos(t.pos.start, in.skipToken()) { PostfixOp(t, nme.WILDCARD) } + atPos(startPos(t), in.skipToken()) { PostfixOp(t, nme.WILDCARD) } case _ => t } @@ -1284,7 +1292,7 @@ object Parsers { if (in.token == IF) guard() else { val pat = pattern1() - if (in.token == EQUALS) atPos(pat.pos.start, in.skipToken()) { GenAlias(pat, expr()) } + if (in.token == EQUALS) atPos(startPos(pat), in.skipToken()) { GenAlias(pat, expr()) } else generatorRest(pat) } @@ -1293,7 +1301,7 @@ object Parsers { def generator(): Tree = generatorRest(pattern1()) def generatorRest(pat: Tree) = - atPos(pat.pos.start, accept(LARROW)) { GenFrom(pat, expr()) } + atPos(startPos(pat), accept(LARROW)) { GenFrom(pat, expr()) } /** ForExpr ::= `for' (`(' Enumerators `)' | `{' Enumerators `}') * {nl} [`yield'] Expr @@ -1357,7 +1365,7 @@ object Parsers { val pattern = () => { val pat = pattern1() if (isIdent(nme.raw.BAR)) - atPos(pat.pos.start) { Alternative(pat :: patternAlts()) } + atPos(startPos(pat)) { Alternative(pat :: patternAlts()) } else pat } @@ -1383,15 +1391,15 @@ object Parsers { // compatibility for Scala2 `x @ _*` syntax infixPattern() match { case pt @ Ident(tpnme.WILDCARD_STAR) => - migrationWarningOrError("The syntax `x @ _*' is no longer supported; use `x : _*' instead", p.pos.start) - atPos(p.pos.start, offset) { Typed(p, pt) } + migrationWarningOrError("The syntax `x @ _*' is no longer supported; use `x : _*' instead", startPos(p)) + atPos(startPos(p), offset) { Typed(p, pt) } case p => - atPos(p.pos.start, offset) { Bind(name, p) } + atPos(startPos(p), offset) { Bind(name, p) } } case p @ Ident(tpnme.WILDCARD_STAR) => // compatibility for Scala2 `_*` syntax - migrationWarningOrError("The syntax `_*' is no longer supported; use `x : _*' instead", p.pos.start) - atPos(p.pos.start) { Typed(Ident(nme.WILDCARD), p) } + migrationWarningOrError("The syntax `_*' is no longer supported; use `x : _*' instead", startPos(p)) + atPos(startPos(p)) { Typed(Ident(nme.WILDCARD), p) } case p => p } @@ -1415,7 +1423,7 @@ object Parsers { val simplePattern = () => in.token match { case IDENTIFIER | BACKQUOTED_IDENT | THIS => path(thisOK = true) match { - case id @ Ident(nme.raw.MINUS) if isNumericLit => literal(id.pos.start) + case id @ Ident(nme.raw.MINUS) if isNumericLit => literal(startPos(id)) case t => simplePatternRest(t) } case USCORE => @@ -1445,9 +1453,9 @@ object Parsers { def simplePatternRest(t: Tree): Tree = { var p = t if (in.token == LBRACKET) - p = atPos(t.pos.start, in.offset) { TypeApply(p, typeArgs()) } + p = atPos(startPos(t), in.offset) { TypeApply(p, typeArgs()) } if (in.token == LPAREN) - p = atPos(t.pos.start, in.offset) { Apply(p, argumentPatterns()) } + p = atPos(startPos(t), in.offset) { Apply(p, argumentPatterns()) } p } @@ -1573,7 +1581,8 @@ object Parsers { case Select(qual, name) => cpy.Select(tree)(adjustStart(start)(qual), name) case _ => tree } - if (start < tree1.pos.start) tree1.withPos(tree1.pos.withStart(start)) + if (tree1.pos.exists && start < tree1.pos.start) + tree1.withPos(tree1.pos.withStart(start)) else tree1 } @@ -1804,7 +1813,7 @@ object Parsers { def importSelector(): Tree = { val from = termIdentOrWildcard() if (from.name != nme.WILDCARD && in.token == ARROW) - atPos(from.pos.start, in.skipToken()) { + atPos(startPos(from), in.skipToken()) { Thicket(from, termIdentOrWildcard()) } else from diff --git a/tests/neg/i1705.scala b/tests/neg/i1705.scala new file mode 100644 index 000000000..801adb4b7 --- /dev/null +++ b/tests/neg/i1705.scala @@ -0,0 +1,24 @@ +object DepBug { + class A { + class B + def mkB = new B + def m(b: B) = b + } + trait Dep { + val a: A + val b: a.B + } + val dep = new { + val a = new A + val b = a mkB + } + def useDep(d: Dep) { // error: procedure syntax + import d._ + a m (b) + } + { // error: Null does not take parameters (follow on) + import dep._ + a m (b) + } + dep.a m (dep b) // error (follow on) +} |