Skip to content

Commit 2be692d

Browse files
authored
Fix selecting terms using _root_ (#18335)
2 parents 3b91996 + 9a41716 commit 2be692d

File tree

5 files changed

+22
-6
lines changed

5 files changed

+22
-6
lines changed

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,10 +1073,7 @@ object Parsers {
10731073

10741074
/** Accept identifier and return Ident with its name as a term name. */
10751075
def termIdent(): Ident =
1076-
val t = makeIdent(in.token, in.offset, ident())
1077-
if t.name == nme.ROOTPKG then
1078-
syntaxError(em"Illegal use of root package name.")
1079-
t
1076+
makeIdent(in.token, in.offset, ident())
10801077

10811078
/** Accept identifier and return Ident with its name as a type name. */
10821079
def typeIdent(): Ident =

compiler/src/dotty/tools/dotc/typer/Checking.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -968,6 +968,11 @@ trait Checking {
968968
em"Implementation restriction: ${path.tpe.classSymbol} is not a valid prefix for a wildcard export, as it is a package",
969969
path.srcPos)
970970

971+
/** Check that the definition name isn't root. */
972+
def checkNonRootName(name: Name, nameSpan: Span)(using Context): Unit =
973+
if name == nme.ROOTPKG then
974+
report.error(em"Illegal use of root package name.", ctx.source.atSpan(nameSpan))
975+
971976
/** Check that module `sym` does not clash with a class of the same name
972977
* that is concurrently compiled in another source file.
973978
*/

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2472,6 +2472,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
24722472

24732473
def typedValDef(vdef: untpd.ValDef, sym: Symbol)(using Context): Tree = {
24742474
val ValDef(name, tpt, _) = vdef
2475+
checkNonRootName(vdef.name, vdef.nameSpan)
24752476
completeAnnotations(vdef, sym)
24762477
if (sym.isOneOf(GivenOrImplicit)) checkImplicitConversionDefOK(sym)
24772478
if sym.is(Module) then checkNoModuleClash(sym)
@@ -2505,6 +2506,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
25052506
// hence we special case it until `erased` is no longer experimental.
25062507
sym.setFlag(Erased)
25072508
val DefDef(name, paramss, tpt, _) = ddef
2509+
checkNonRootName(ddef.name, ddef.nameSpan)
25082510
completeAnnotations(ddef, sym)
25092511
val paramss1 = paramss.nestedMapConserve(typed(_)).asInstanceOf[List[ParamClause]]
25102512
for case ValDefs(vparams) <- paramss1 do
@@ -2853,6 +2855,10 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
28532855
val pkg = pid1.symbol
28542856
pid1 match
28552857
case pid1: RefTree if pkg.is(Package) =>
2858+
if ctx.owner != defn.RootClass // valid top-level "package _root_"
2859+
&& ctx.owner != defn.EmptyPackageClass // valid "package _root_" after parser's "package <empty>" wrapper
2860+
then
2861+
checkNonRootName(pid1.name, pid1.span)
28562862
inContext(ctx.packageContext(tree, pkg)) {
28572863
// If it exists, complete the class containing the top-level definitions
28582864
// before typing any statement in the package to avoid cycles as in i13669.scala

tests/neg/i18020.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,12 @@ package p {
4747
}
4848

4949
// scala/bug#12508
50-
package _root_ { // error
50+
package _root_ { // ok
5151
class C {
5252
val _root_ = 42 // error
5353
}
5454
}
55-
package _root_.p { // error
55+
package _root_.p { // ok
5656
class C
5757
}
5858

tests/pos/i18275.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package foo
2+
3+
enum MyEnum derives _root_.foo.Eq:
4+
case One
5+
6+
trait Eq[T]
7+
object Eq:
8+
inline def derived[T](using m: scala.deriving.Mirror.Of[T]): Eq[T] = ???

0 commit comments

Comments
 (0)