Skip to content

java style enums should not allow mixins in cases #9162

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

Closed
bishabosha opened this issue Jun 11, 2020 · 7 comments
Closed

java style enums should not allow mixins in cases #9162

bishabosha opened this issue Jun 11, 2020 · 7 comments

Comments

@bishabosha
Copy link
Member

bishabosha commented Jun 11, 2020

Minimized code

There is no syntax for an individual java enum case to implement a new interface, e.g. the following is an error

public enum Foo {
  Red implements java.util.Function<Integer, Boolean> {
    public Boolean apply(Integer i){
      return i > 3 ;
    }
  },
  Green,
  Blue
}

Note: you can make a Java enum case as an anonymous subclass, it just can't add new parents to what the enum already implements. e.g.

public enum Foo implements java.util.Function<Integer, Boolean> {
  case One {
    public Boolean apply(Integer i){
      return i == 1 ;
    }
  }
  case Two {
    public Boolean apply(Integer i){
      return i == 2 ;
    }
  }
}

Expectation

so therefore the following should be an error in dotty:

object FancyColours {
  sealed trait Pretty { self: Colour => }
  sealed trait Dull { self: Colour => }
  enum Colour extends java.lang.Enum[Colour] {
    case Pink extends Colour with Pretty
    case Red extends Colour with Dull
  }
}

This prevents any optimisation of typing java enums as an EnumTag Constant

@anatoliykmetyuk
Copy link
Contributor

What are the implications of allowing inheritance of Scala 3 java-compat enum cases?

@bishabosha
Copy link
Member Author

I don't think it should cause any issues in java, it just means you can't type it as if it were a java enum, e.g. there is an optimisation in Scala 2 that for java enums just uses the symbol of the parent class for all type checking

@anatoliykmetyuk
Copy link
Contributor

Does that mean we'll get issues with Scala 2 interop if we allow this flexibility?

@bishabosha
Copy link
Member Author

bishabosha commented Jun 11, 2020

This was opened just to decide on what it means to be java style enum from a static type point of view, as in Scala, Constants referring to Java enums compiled by Java make optimisations that forgets any precise type

@bishabosha
Copy link
Member Author

this wont cause problems in scala 2 compat either way

@anatoliykmetyuk
Copy link
Contributor

If the situation doesn't cause any problems but changing it might, why try to change it?

@bishabosha
Copy link
Member Author

bishabosha commented Jun 11, 2020

Overall, I think that unlike #7499, it is safe to allow mixins for individual cases because the enum API is all final and defined in java.lang.Enum, and does not check interfaces of runtime classes. As a benefit, mixins can actually be used to provide the behaviour that java allows with anonymous subclasses for enum cases:

trait OneImpl extends (Int => Boolean) {
  def apply(v1: Int): Boolean = v1 == 1
}
trait TwoImpl extends (Int => Boolean) {
  def apply(v1: Int): Boolean = v1 == 2
}
enum Foo extends java.lang.Enum[Foo] with (Int => Boolean) {
  case One extends Foo with OneImpl
  case Two extends Foo with TwoImpl
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants