Skip to content

Fix #6601: Check that an enum case extends its enum class #8445

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 5, 2020
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
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/transform/PostTyper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase
cpy.Inlined(tree)(callTrace, transformSub(bindings), transform(expansion)(inlineContext(call)))
case templ: Template =>
withNoCheckNews(templ.parents.flatMap(newPart)) {
Checking.checkEnumParentOK(templ.symbol.owner)
forwardParamAccessors(templ)
synthMbr.addSyntheticMembers(
superAcc.wrapTemplate(templ)(
Expand Down
11 changes: 11 additions & 0 deletions compiler/src/dotty/tools/dotc/typer/Checking.scala
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,17 @@ object Checking {
stats.foreach(checkValueClassMember)
}
}

/** Check that an enum case extends its enum class */
def checkEnumParentOK(cls: Symbol)(using ctx: Context): Unit =
val enumCase =
if cls.isAllOf(EnumCase) then cls
else if cls.isAnonymousClass && cls.owner.isAllOf(EnumCase) then cls.owner
else NoSymbol
if enumCase.exists then
val enumCls = enumCase.owner.linkedClass
if !cls.info.parents.exists(_.typeSymbol == enumCls) then
ctx.error(i"enum case does not extend its enum $enumCls", enumCase.sourcePos)
}

trait Checking {
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/internals/syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ yield

```
as derives extension inline on opaque open using
~ * | & + -
* + -
```

## Context-free Syntax
Expand Down
5 changes: 4 additions & 1 deletion docs/docs/reference/enums/desugarEnums.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,9 @@ Cases such as `case C` expand to a `@static val` as opposed to a `val`. This all

### Other Rules

A normal case class which is not produced from an enum case is not allowed to extend
- A normal case class which is not produced from an enum case is not allowed to extend
`scala.Enum`. This ensures that the only cases of an enum are the ones that are
explicitly declared in it.

- If an enum case has an extends clause, the enum class must be one of the
classes that's extended.
10 changes: 10 additions & 0 deletions tests/neg/i6601.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
object GADTs2 {
enum Var[G, A] {
case Z[A, G]() extends Expr[(A, G), A] // error
case X extends AnyRef // error
}
enum Expr[G, A] {
case Lit[G](n: Int) extends Expr[G, Int]
// case S[A, G](x:
}
}