From 7694a5cb45b98617073d36d739b705b5175b5140 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Wed, 1 Sep 2021 18:40:19 -0700 Subject: [PATCH 1/4] Avoid shadowing of name 'name' --- .../dotty/tools/dotc/parsing/Scanners.scala | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala index 84a181769e3b..e36773d4f61d 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala @@ -242,24 +242,17 @@ object Scanners { /** A buffer for comments */ private val commentBuf = CharBuffer() - private def handleMigration(keyword: Token): Token = - if scala3keywords.contains(keyword) && migrateTo3 then treatAsIdent() - else keyword - - private def treatAsIdent(): Token = - val name0 = name // don't capture the `name` var in the message closure, it may be null later - report.errorOrMigrationWarning( - i"$name0 is now a keyword, write `$name0` instead of $name0 to keep it as an identifier", - sourcePos()) - patch(source, Span(offset), "`") - patch(source, Span(offset + name.length), "`") - IDENTIFIER - - def toToken(name: SimpleName): Token = { - val idx = name.start + def toToken(identifier: SimpleName): Token = + def handleMigration(keyword: Token): Token = + if scala3keywords.contains(keyword) && migrateTo3 then + report.errorOrMigrationWarning(i"$identifier is now a keyword, write `$identifier` instead of $identifier to keep it as an identifier", sourcePos()) + patch(source, Span(offset), "`") + patch(source, Span(offset + identifier.length), "`") + IDENTIFIER + else keyword + val idx = identifier.start if (idx >= 0 && idx <= lastKeywordStart) handleMigration(kwArray(idx)) else IDENTIFIER - } def newTokenData: TokenData = new TokenData {} From 59f81dd2f916190c01871f799e094eb061327073 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Wed, 1 Sep 2021 20:00:05 -0700 Subject: [PATCH 2/4] Use tokenString --- compiler/src/dotty/tools/dotc/parsing/Scanners.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala index e36773d4f61d..7e9362af5493 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala @@ -245,7 +245,8 @@ object Scanners { def toToken(identifier: SimpleName): Token = def handleMigration(keyword: Token): Token = if scala3keywords.contains(keyword) && migrateTo3 then - report.errorOrMigrationWarning(i"$identifier is now a keyword, write `$identifier` instead of $identifier to keep it as an identifier", sourcePos()) + val what = tokenString(keyword) + report.errorOrMigrationWarning(i"$what is now a keyword, write `$what` instead of $what to keep it as an identifier", sourcePos()) patch(source, Span(offset), "`") patch(source, Span(offset + identifier.length), "`") IDENTIFIER From 1f47f644c87cf65780ff088d454aa3e131f11a84 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Wed, 1 Sep 2021 20:13:35 -0700 Subject: [PATCH 3/4] Distinguish simple finishNamed from fiddly finishNamedToken --- .../src/dotty/tools/dotc/parsing/Scanners.scala | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala index 7e9362af5493..0fa71dd02a8b 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala @@ -135,10 +135,13 @@ object Scanners { */ protected def putChar(c: Char): Unit = litBuf.append(c) - /** Clear buffer and set name and token - * If `target` is different from `this`, don't treat identifiers as end tokens + /** Finish an IDENTIFIER with `this.name`. */ + inline def finishNamed(): Unit = finishNamedToken(IDENTIFIER, this) + + /** Clear buffer and set name and token. + * If `target` is different from `this`, don't treat identifiers as end tokens. */ - def finishNamed(idtoken: Token = IDENTIFIER, target: TokenData = this): Unit = + def finishNamedToken(idtoken: Token, target: TokenData): Unit = target.name = termName(litBuf.chars, 0, litBuf.length) litBuf.clear() target.token = idtoken @@ -996,7 +999,7 @@ object Scanners { getLitChars('`') if (ch == '`') { nextChar() - finishNamed(BACKQUOTED_IDENT) + finishNamedToken(BACKQUOTED_IDENT, target = this) if (name.length == 0) error("empty quoted identifier") else if (name == nme.WILDCARD) @@ -1162,7 +1165,7 @@ object Scanners { nextRawChar() ch != SU && Character.isUnicodeIdentifierPart(ch) do () - finishNamed(target = next) + finishNamedToken(IDENTIFIER, target = next) } else error("invalid string interpolation: `$$`, `$\"`, `$`ident or `$`BlockExpr expected") From fd4be37abb0dca516faa7309a0bab4b6bfae3b2f Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Wed, 1 Sep 2021 21:53:31 -0700 Subject: [PATCH 4/4] Test interpolation of keyword --- tests/neg-custom-args/fatal-warnings/i13440.check | 12 ++++++++++-- tests/neg-custom-args/fatal-warnings/i13440.scala | 6 +++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/tests/neg-custom-args/fatal-warnings/i13440.check b/tests/neg-custom-args/fatal-warnings/i13440.check index 0e9dd7dd5e50..fde8133419b6 100644 --- a/tests/neg-custom-args/fatal-warnings/i13440.check +++ b/tests/neg-custom-args/fatal-warnings/i13440.check @@ -1,4 +1,12 @@ --- Error: tests/neg-custom-args/fatal-warnings/i13440.scala:3:13 ------------------------------------------------------- -3 |case class A(enum: List[Int] = Nil) // error +-- Error: tests/neg-custom-args/fatal-warnings/i13440.scala:3:4 -------------------------------------------------------- +3 |def given = 42 // error + | ^ + | given is now a keyword, write `given` instead of given to keep it as an identifier +-- Error: tests/neg-custom-args/fatal-warnings/i13440.scala:5:13 ------------------------------------------------------- +5 |case class C(enum: List[Int] = Nil) { // error | ^ | enum is now a keyword, write `enum` instead of enum to keep it as an identifier +-- Error: tests/neg-custom-args/fatal-warnings/i13440.scala:6:11 ------------------------------------------------------- +6 | val s = s"$enum" // error + | ^ + | enum is now a keyword, write `enum` instead of enum to keep it as an identifier diff --git a/tests/neg-custom-args/fatal-warnings/i13440.scala b/tests/neg-custom-args/fatal-warnings/i13440.scala index 8e3af76ad3fa..6cb4956e7434 100644 --- a/tests/neg-custom-args/fatal-warnings/i13440.scala +++ b/tests/neg-custom-args/fatal-warnings/i13440.scala @@ -1,3 +1,7 @@ import language.`3.0-migration` -case class A(enum: List[Int] = Nil) // error +def given = 42 // error + +case class C(enum: List[Int] = Nil) { // error + val s = s"$enum" // error +}