Skip to content

Commit 8aa24ac

Browse files
committed
Also check unselected this references in enum cases.
1 parent 48b7656 commit 8aa24ac

File tree

3 files changed

+32
-16
lines changed

3 files changed

+32
-16
lines changed

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

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -745,18 +745,27 @@ trait Checking {
745745

746746
/** Check that all non-synthetic references of the form `<ident>` or
747747
* `this.<ident>` in `tree` that refer to a member of `badOwner` are
748-
* `allowed`.
748+
* `allowed`. Also check that there are no other explicit `this` references
749+
* to `badOwner`.
749750
*/
750751
def checkRefsLegal(tree: tpd.Tree, badOwner: Symbol, allowed: (Name, Symbol) => Boolean, where: String)(implicit ctx: Context): Unit = {
751-
tree.foreachSubTree { tree =>
752-
tree match {
753-
case Ident(_) | Select(This(_), _) if tree.pos.isSourceDerived =>
754-
val sym = tree.symbol
755-
if (sym.maybeOwner == badOwner && !allowed(tree.asInstanceOf[RefTree].name, sym))
756-
ctx.error(i"illegal reference to $sym from $where: $tree // ${tree.toString}", tree.pos)
757-
case _ =>
752+
val checker = new TreeTraverser {
753+
def traverse(t: Tree)(implicit ctx: Context) = {
754+
def check(owner: Symbol, checkedSym: Symbol) =
755+
if (t.pos.isSourceDerived && owner == badOwner)
756+
t match {
757+
case t: RefTree if allowed(t.name, checkedSym) =>
758+
case _ => ctx.error(i"illegal reference to $checkedSym from $where", t.pos)
759+
}
760+
val sym = t.symbol
761+
t match {
762+
case Ident(_) | Select(This(_), _) => check(sym.maybeOwner, sym)
763+
case This(_) => check(sym, sym)
764+
case _ => traverseChildren(t)
765+
}
758766
}
759767
}
768+
checker.traverse(tree)
760769
}
761770

762771
/** Check that all case classes that extend `scala.Enum` are `enum` cases */

docs/docs/reference/enums/desugarEnums.md

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -173,14 +173,11 @@ Companion objects that contain at least one simple case define in addition:
173173

174174
### Scopes for Enum Cases
175175

176-
A case in an `enum` is treated similarly to a secondary constructor. It cannot access
177-
with simple identifiers value parameters or instance members of the enclosing `enum`.
178-
179-
Even though translated enum cases are located in the enum's companion object, they
180-
cannot access with simple identifiers any members defined locally in the enclosing
181-
object either. The compiler is free to typecheck enum cases in the scope of the
182-
enclosing companion object but it must then flag any illegal accesses to the object's
183-
members.
176+
A case in an `enum` is treated similarly to a secondary constructor. It can access neither the enclosing `enum` using `this`, nor its value parameters or instance members using simple
177+
identifiers.
178+
179+
Even though translated enum cases are located in the enum's companion object, referencing
180+
this object or its members via `this` or a simple identifier is also illegal. The compiler typechecks enum cases in the scope of the enclosing companion object but flags any such illegal accesses as errors.
184181

185182
### Other Rules
186183

tests/neg/enumsAccess.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,13 @@ object test6 {
8484
val defaultX = 2
8585
}
8686
}
87+
88+
object test7 {
89+
90+
trait Arg
91+
92+
enum E(x: Arg) {
93+
case C extends E(this) // error: illegal reference to `this`
94+
}
95+
object E extends Arg
96+
}

0 commit comments

Comments
 (0)