diff --git a/compiler/src/dotty/tools/dotc/cc/SafeRefs.scala b/compiler/src/dotty/tools/dotc/cc/SafeRefs.scala index 52a799161361..f4fcee85f4f2 100644 --- a/compiler/src/dotty/tools/dotc/cc/SafeRefs.scala +++ b/compiler/src/dotty/tools/dotc/cc/SafeRefs.scala @@ -7,7 +7,7 @@ import Symbols.* import Annotations.* import util.Spans.NoSpan import util.SrcPos -import Contexts.Context +import Contexts.{Context, ctx} import Constants.Constant import Decorators.* import ast.tpd.* @@ -15,6 +15,8 @@ import SymDenotations.* import Flags.* import Types.* import config.Feature +import NameOps.isReplWrapperName +import Names.Name import typer.ProtoTypes.SelectionProto /** Check whether references from safe mode should be allowed */ @@ -160,4 +162,8 @@ object SafeRefs { case _ => if Feature.safeEnabled then tree.tpe.foreachPart(checkAnnotatedType(_)) + + /** Allow name in safe mode even though it contains `$` characters */ + def allow(name: Name)(using Context): Boolean = + name.isReplWrapperName && ctx.mode.is(Mode.Interactive) } diff --git a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala index b8ebab3b91c2..1a2f8bf431d8 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala @@ -21,6 +21,7 @@ import config.Feature.{migrateTo3, sourceVersion} import config.SourceVersion.{`3.0`, `3.0-migration`} import config.MigrationVersion import reporting.{NoProfile, Profile, Message} +import cc.SafeRefs import java.util.Objects import dotty.tools.dotc.reporting.Message.rewriteNotice @@ -150,6 +151,8 @@ object Scanners { def finishNamedToken(idtoken: Token, target: TokenData): Unit = target.name = termName(litBuf.chars, 0, litBuf.length) litBuf.clear() + if target.name.contains('$') && Feature.safeEnabled && !SafeRefs.allow(name) then + report.error(em"Identifier may not contain '$$' in safe mode", sourcePos()) target.token = idtoken if idtoken == IDENTIFIER then val converted = toToken(target.name) diff --git a/compiler/test/dotc/neg-best-effort-pickling.excludelist b/compiler/test/dotc/neg-best-effort-pickling.excludelist index 52371ecf17a5..834972b4cbe1 100644 --- a/compiler/test/dotc/neg-best-effort-pickling.excludelist +++ b/compiler/test/dotc/neg-best-effort-pickling.excludelist @@ -20,5 +20,8 @@ i974.scala # cyclic reference i13864.scala # missing symbol in pickling type-params.scala # recursion limit exceeded +unsafe-dollar-in-name.scala # missing owner in unpickler +unsafe-dollar-in-name-2.scala # missing owner in unpickler + # semantic db generation fails in the first compilation i15158.scala # cyclic reference - stack overflow diff --git a/tests/neg/unsafe-dollar-in-name-2.check b/tests/neg/unsafe-dollar-in-name-2.check new file mode 100644 index 000000000000..b8926a0bc821 --- /dev/null +++ b/tests/neg/unsafe-dollar-in-name-2.check @@ -0,0 +1,8 @@ +-- Error: tests/neg/unsafe-dollar-in-name-2.scala:3:7 ------------------------------------------------------------------ +3 |object Foo$ // error + | ^ + | Identifier may not contain '$' in safe mode +-- Error: tests/neg/unsafe-dollar-in-name-2.scala:5:6 ------------------------------------------------------------------ +5 |class `Bar$` // error + | ^ + | Identifier may not contain '$' in safe mode diff --git a/tests/neg/unsafe-dollar-in-name-2.scala b/tests/neg/unsafe-dollar-in-name-2.scala new file mode 100644 index 000000000000..787c696e5d02 --- /dev/null +++ b/tests/neg/unsafe-dollar-in-name-2.scala @@ -0,0 +1,5 @@ +//> using options -language:experimental.safe + +object Foo$ // error + +class `Bar$` // error diff --git a/tests/neg/unsafe-dollar-in-name.check b/tests/neg/unsafe-dollar-in-name.check new file mode 100644 index 000000000000..e0c1f179e284 --- /dev/null +++ b/tests/neg/unsafe-dollar-in-name.check @@ -0,0 +1,8 @@ +-- Error: tests/neg/unsafe-dollar-in-name.scala:3:7 -------------------------------------------------------------------- +3 |object Foo$ // error + | ^ + | Identifier may not contain '$' in safe mode +-- Error: tests/neg/unsafe-dollar-in-name.scala:5:6 -------------------------------------------------------------------- +5 |class `Bar$` // error + | ^ + | Identifier may not contain '$' in safe mode diff --git a/tests/neg/unsafe-dollar-in-name.scala b/tests/neg/unsafe-dollar-in-name.scala new file mode 100644 index 000000000000..687479164c9c --- /dev/null +++ b/tests/neg/unsafe-dollar-in-name.scala @@ -0,0 +1,5 @@ +import language.experimental.safe + +object Foo$ // error + +class `Bar$` // error