Skip to content

Fix #5008: forbid any class extending enums #5031

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
Jan 27, 2019

Conversation

Blaisorblade
Copy link
Contributor

@Blaisorblade Blaisorblade commented Aug 26, 2018

Forbid any class from extending enums. However, keep allowing to extend Enum by hand (per current testcase). Thanks to @allanrenucci for the suggesting how.

Building on top of #5028, and alternative to it.

I'm not sure that's a good idea — there's a testcase from 2017 about this (from d3b2c37, 0ee3281), but it doesn't seem in the spirit of the current restricted enums.

/cc @hrhino.

ctx.error(em"normal case $cls in ${cls.owner} cannot extend an enum", cdef.pos)
if (!cdef.mods.isEnumCase && !isEnumAnonCls) {
if (cls.is(Case))
ctx.error(em"normal case $cls in ${cls.owner} cannot extend an enum", cdef.pos)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we don't need a special error message for case class anymore

@@ -1,20 +0,0 @@
abstract sealed class List[T] extends Enum
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this test removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It appears to be entirely about the feature we’re removing, which is why I asked about it.

else if (firstParent != defn.EnumClass && firstParent.derivesFrom(defn.EnumClass) && !cdef.mods.isEnumCase && !isEnumAnonCls)
// Since enums are classes and Namer checks that classes don't extend multiple classes, we only check the class
// parent.
//Tricky to phrase; language taken from "case-to-case inheritance is prohibited".
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment irelevant

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the messages should be evolved together, so it’s relevant for maintainers. I can make that clearer tho.

// Since enums are classes and Namer checks that classes don't extend multiple classes, we only check the class
// parent.
//Tricky to phrase; language taken from "case-to-case inheritance is prohibited".
ctx.error(s"${cls.name} has enum ancestor ${firstParent.name}, but inheriting from enums is prohibited", cdef.pos)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not simply: ${cls.name} inherits from enum ${firstParent.name}, ...?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because that doesn’t say that inheriting from an enum is a problem. We explain that even for case classes, as the “irrelevant” comment points out.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't mean to remove the part after the comma, just rephrase the first part:

"${cls.name} inherits from enum ${firstParent.name}, but inheriting from enums is prohibited"

I find it weird to talk about ancestor when it really is the first parent. Ideally enum should be treated as effectively final and we should report errors similarly to final inheritance rather than case to case inheritance. Ideally something like:

enum Foo { case F }
class Bar extends Foo
class Bat extends Bar

shoud report similar errors as:

final class Foo
class Bar extends Foo // error: class Bar cannot extend final class Foo
class Bat extends Bar // no error here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Memo to self: using the flag would not be transitive, so it would also avoid this double reporting.

@allanrenucci
Copy link
Contributor

allanrenucci commented Aug 28, 2018

And the two commits should be squashed since the second commit pretty much reverts the first one

@allanrenucci
Copy link
Contributor

I'm not sure that's a good idea — there's a testcase from 2017 about this (from d3b2c37, 0ee3281), but it doesn't seem in the spirit of the current restricted enums.

I think we can differentiate between extending enums and extending the trait Enum. The former would be an error but the latter would be OK (I believe it is similar in Java). Testing if the first parent has the Enum flag instead of doing a subclass check (i.e. derivesFrom(defn.EnumClass)) should do the trick

@odersky
Copy link
Contributor

odersky commented Jan 12, 2019

@Blaisorblade This has been inactive for a month. Let's finish it now.

@Blaisorblade Blaisorblade force-pushed the fix-5008-any-extends-enum branch from c599de2 to 2dfd81a Compare January 22, 2019 15:22
@Blaisorblade Blaisorblade merged commit 7b583e6 into scala:master Jan 27, 2019
@Blaisorblade Blaisorblade deleted the fix-5008-any-extends-enum branch January 27, 2019 14:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants