Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion compiler/src/dotty/tools/dotc/cc/SafeRefs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import Symbols.*
import Annotations.*
import util.Spans.NoSpan
import util.{Property, SrcPos}
import Contexts.Context
import Contexts.{Context, ctx}
import Constants.Constant
import Decorators.*
import ast.tpd.*
import SymDenotations.*
import Flags.*
import Types.*
import Names.Name
import NameOps.isReplWrapperName
import config.Printers.capt

/** Check whether references from safe mode should be allowed */
Expand Down Expand Up @@ -172,6 +174,10 @@ object SafeRefs {
rejectSafe("scala.runtime.LazyUnit")
}

/** Allow name in safe mode even though it contains `$` characters */
def allowDollarIn(name: Name)(using Context): Boolean =
name.isReplWrapperName && ctx.mode.is(Mode.Interactive)

private def fail(sym: Symbol, reason: String, pos: SrcPos)(using Context) =
report.error(em"Cannot refer to ${sym.sanitizedDescription}${sym.showExtendedLocation} from safe code since $reason", pos)
false
Expand Down
6 changes: 5 additions & 1 deletion compiler/src/dotty/tools/dotc/parsing/Scanners.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import config.Feature.{migrateTo3, sourceVersion}
import config.SourceVersion.{`3.0`, `3.0-migration`}
import config.MigrationVersion
import reporting.*
import cc.SafeRefs

import java.util.Objects
import dotty.tools.dotc.reporting.Message.rewriteNotice
Expand Down Expand Up @@ -146,8 +147,11 @@ object Scanners {
* If `target` is different from `this`, don't treat identifiers as end tokens.
*/
def finishNamedToken(idtoken: Token, target: TokenData): Unit =
target.name = termName(litBuf.chars, 0, litBuf.length)
val name = termName(litBuf.chars, 0, litBuf.length)
target.name = name
litBuf.clear()
if name.contains('$') && Feature.safeEnabled && !SafeRefs.allowDollarIn(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.nn)
Expand Down
3 changes: 3 additions & 0 deletions compiler/test/dotc/neg-best-effort-pickling.excludelist
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,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
8 changes: 8 additions & 0 deletions tests/neg/unsafe-dollar-in-name-2.check
Original file line number Diff line number Diff line change
@@ -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
5 changes: 5 additions & 0 deletions tests/neg/unsafe-dollar-in-name-2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//> using options -language:experimental.safe

object Foo$ // error

class `Bar$` // error
8 changes: 8 additions & 0 deletions tests/neg/unsafe-dollar-in-name.check
Original file line number Diff line number Diff line change
@@ -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
5 changes: 5 additions & 0 deletions tests/neg/unsafe-dollar-in-name.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import language.experimental.safe

object Foo$ // error

class `Bar$` // error
8 changes: 8 additions & 0 deletions tests/neg/wildcard-imports.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-- [E049] Reference Error: tests/neg/wildcard-imports/Test.scala:7:12 --------------------------------------------------
7 | val bar = foo // error
| ^^^
| Reference to foo is ambiguous.
| It is both imported by import test.A._
| and imported subsequently by import test.B._
|
| longer explanation available when compiling with `-explain`
4 changes: 4 additions & 0 deletions tests/neg/wildcard-imports/A.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package test

object A:
def foo: Int = 0
4 changes: 4 additions & 0 deletions tests/neg/wildcard-imports/B.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package test

object B:
def foo: Int = 0
8 changes: 8 additions & 0 deletions tests/neg/wildcard-imports/Test.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package test

import A.*
import B.*

object Test:
val bar = foo // error

Loading