Skip to content

Commit

Permalink
Fix selecting terms using _root_ (#18335)
Browse files Browse the repository at this point in the history
  • Loading branch information
dwijnand authored Aug 14, 2023
2 parents 3b91996 + 9a41716 commit 2be692d
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 6 deletions.
5 changes: 1 addition & 4 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1073,10 +1073,7 @@ object Parsers {

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

/** Accept identifier and return Ident with its name as a type name. */
def typeIdent(): Ident =
Expand Down
5 changes: 5 additions & 0 deletions compiler/src/dotty/tools/dotc/typer/Checking.scala
Original file line number Diff line number Diff line change
Expand Up @@ -968,6 +968,11 @@ trait Checking {
em"Implementation restriction: ${path.tpe.classSymbol} is not a valid prefix for a wildcard export, as it is a package",
path.srcPos)

/** Check that the definition name isn't root. */
def checkNonRootName(name: Name, nameSpan: Span)(using Context): Unit =
if name == nme.ROOTPKG then
report.error(em"Illegal use of root package name.", ctx.source.atSpan(nameSpan))

/** Check that module `sym` does not clash with a class of the same name
* that is concurrently compiled in another source file.
*/
Expand Down
6 changes: 6 additions & 0 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2472,6 +2472,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer

def typedValDef(vdef: untpd.ValDef, sym: Symbol)(using Context): Tree = {
val ValDef(name, tpt, _) = vdef
checkNonRootName(vdef.name, vdef.nameSpan)
completeAnnotations(vdef, sym)
if (sym.isOneOf(GivenOrImplicit)) checkImplicitConversionDefOK(sym)
if sym.is(Module) then checkNoModuleClash(sym)
Expand Down Expand Up @@ -2505,6 +2506,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
// hence we special case it until `erased` is no longer experimental.
sym.setFlag(Erased)
val DefDef(name, paramss, tpt, _) = ddef
checkNonRootName(ddef.name, ddef.nameSpan)
completeAnnotations(ddef, sym)
val paramss1 = paramss.nestedMapConserve(typed(_)).asInstanceOf[List[ParamClause]]
for case ValDefs(vparams) <- paramss1 do
Expand Down Expand Up @@ -2853,6 +2855,10 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
val pkg = pid1.symbol
pid1 match
case pid1: RefTree if pkg.is(Package) =>
if ctx.owner != defn.RootClass // valid top-level "package _root_"
&& ctx.owner != defn.EmptyPackageClass // valid "package _root_" after parser's "package <empty>" wrapper
then
checkNonRootName(pid1.name, pid1.span)
inContext(ctx.packageContext(tree, pkg)) {
// If it exists, complete the class containing the top-level definitions
// before typing any statement in the package to avoid cycles as in i13669.scala
Expand Down
4 changes: 2 additions & 2 deletions tests/neg/i18020.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ package p {
}

// scala/bug#12508
package _root_ { // error
package _root_ { // ok
class C {
val _root_ = 42 // error
}
}
package _root_.p { // error
package _root_.p { // ok
class C
}

Expand Down
8 changes: 8 additions & 0 deletions tests/pos/i18275.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package foo

enum MyEnum derives _root_.foo.Eq:
case One

trait Eq[T]
object Eq:
inline def derived[T](using m: scala.deriving.Mirror.Of[T]): Eq[T] = ???

0 comments on commit 2be692d

Please sign in to comment.