Skip to content

Commit

Permalink
Fix scala#15514 in Parser
Browse files Browse the repository at this point in the history
There was a missing set of parentheses in parser which caused a lookahead
from INTERPOLATIONID, which should be illegal, since the lookahead then
migth set the next TokenData which is subsequently overwritten by reset.

We now demand that lookahead cannot be called if the current token is
a INTERPOLATIONID.

There were two many variants `lookahead` in the Scanner, which only differered
in camelCase or not. Rename one to`peekAhead` to make the code clearer.
  • Loading branch information
odersky committed Jun 25, 2022
1 parent 0059d1d commit 35d159a
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 12 deletions.
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3957,8 +3957,8 @@ object Parsers {
*/
def selfType(): ValDef =
if (in.isIdent || in.token == THIS)
&& in.lookahead.isColon && followingIsSelfType()
|| in.lookahead.token == ARROW
&& (in.lookahead.isColon && followingIsSelfType()
|| in.lookahead.token == ARROW)
then
atSpan(in.offset) {
val selfName =
Expand Down
23 changes: 13 additions & 10 deletions compiler/src/dotty/tools/dotc/parsing/Scanners.scala
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,7 @@ object Scanners {
true
else token == COLONfollow && (inTemplate || fewerBracesEnabled)
if enabled then
lookAhead()
peekAhead()
val atEOL = isAfterLineEnd || token == EOF
reset()
if atEOL then token = COLONeol
Expand Down Expand Up @@ -690,15 +690,14 @@ object Scanners {
insert(OUTDENT, offset)
case _ =>

def lookAhead() =
def peekAhead() =
prev.copyFrom(this)
getNextToken(token)
if token == END && !isEndMarker then token = IDENTIFIER

def reset() = {
def reset() =
next.copyFrom(this)
this.copyFrom(prev)
}

def closeIndented() = currentRegion match
case r: Indented if !r.isOutermost => insert(OUTDENT, offset)
Expand All @@ -717,12 +716,12 @@ object Scanners {
}
(token: @switch) match {
case CASE =>
lookAhead()
peekAhead()
if (token == CLASS) fuse(CASECLASS)
else if (token == OBJECT) fuse(CASEOBJECT)
else reset()
case SEMI =>
lookAhead()
peekAhead()
if (token != ELSE) reset()
case COMMA =>
def isEnclosedInParens(r: Region): Boolean = r match
Expand All @@ -733,7 +732,7 @@ object Scanners {
case r: Indented if isEnclosedInParens(r.outer) =>
insert(OUTDENT, offset)
case _ =>
lookAhead()
peekAhead()
if isAfterLineEnd
&& currentRegion.commasExpected
&& (token == RPAREN || token == RBRACKET || token == RBRACE || token == OUTDENT)
Expand Down Expand Up @@ -1083,11 +1082,14 @@ object Scanners {
* The token is computed via fetchToken, so complex two word
* tokens such as CASECLASS are not recognized.
* Newlines and indent/unindent tokens are skipped.
*
* Restriction: `lookahead` is illegal if the current token is INTERPOLATIONID
*/
def lookahead: TokenData =
def lookahead: TokenData =
if next.token == EMPTY then
lookAhead()
assert(token != INTERPOLATIONID)
// INTERPOLATONIDs are followed by a string literal, which can set next
// in peekAhead(). In that case, the following reset() would forget that token.
peekAhead()
reset()
next

Expand Down Expand Up @@ -1279,6 +1281,7 @@ object Scanners {
putChar(ch) ; nextRawChar()
loopRest()
else
assert(next.token == EMPTY)
finishNamedToken(IDENTIFIER, target = next)
end loopRest
setStrVal()
Expand Down
4 changes: 4 additions & 0 deletions tests/pos/i15514.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

object Main { s"Hello $Main.toStr!" }

object Alt { s"Hello ${Alt}.toStr!" }

0 comments on commit 35d159a

Please sign in to comment.