Skip to content
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

Objects extending Enumerations have inaccessible #Value type #3134

Closed
scabug opened this issue Mar 2, 2010 · 4 comments
Closed

Objects extending Enumerations have inaccessible #Value type #3134

scabug opened this issue Mar 2, 2010 · 4 comments

Comments

@scabug
Copy link

scabug commented Mar 2, 2010

Type-safe generic methods operating on Enumerations and returning a Value need to have signatures of the form

def method[E <: Enumeration](e: E): E#Value

since it is not possible to specify the type of a particular instance:

def cantDoThis[E <: Enumeration](e: E): e.Value

The former is arguably typesafe enough, but unfortunately there is a bug in the implementation of inner class types inside objects:

object BugTestCase {
  object Broken extends Enumeration { val zero = Value }
  def getZero[E <: Enumeration](enum: E): E#Value = enum.withName("zero")
  val correctlyTyped = getZero(Broken)
  val wronglyTyped: Broken.type#Value = null
  // val shouldWork: Broken.type#Value = getZero(Broken)

  class Workaround extends Enumeration { val zero = Value }
  lazy val Working = new Workaround
  val actuallyWorks: Workaround#Value = getZero(Working)
}

Note that the Workaround class/lazy val pair should be equivalent to a companion object, but there is no way to write the correct type signature for the companion object. Although type inference works correctly, the REPL reports:

scala> BugTestCase.correctlyTyped
res0: BugTestCase.Broken#Value = zero

scala> BugTestCase.wronglyTyped
res1: BugTestCase.Broken.Value = null

This makes it necessary to use one's own singleton objects instead of the language-supported ones. Either Broken.type#Value should mean Broken$$#Value (where Broken$$ is the class of the singleton object), or Broken#Value should be valid syntax and mean that, or E#Value should be equivalent to Broken.Value.

@scabug
Copy link
Author

scabug commented Mar 2, 2010

Imported From: https://issues.scala-lang.org/browse/SI-3134?orig=1
Reporter: @Ichoran
See #5211

@scabug
Copy link
Author

scabug commented Mar 2, 2010

@paulp said:
This is as specified. Broken.type#Value does mean what you want it to, but singleton types are not inferred.

  val doesWork: Broken.type#Value = getZero[Broken.type](Broken)

@scabug
Copy link
Author

scabug commented Mar 3, 2010

@Ichoran said:
The request was filed as an "enhancement" instead of a "bug" because the specification, while accurately followed, is awkward. It seems that the correct status would be "wontfix" in that case.

Also, the "invalid" resolution does not address the complaint that the generic applied to a singleton returned a type that I cannot refer to. It inferred something, just not anything that I could specify (see REPL output res0 and compare to res1).

(I do not intend to start a debate, just clarify the original posting; if this matter requires further discussion, I'll pick it up on scala-debate or some other appropriate venue.)

@scabug
Copy link
Author

scabug commented Mar 3, 2010

@paulp said:
Replying to [comment:2 ichoran]:

The request was filed as an "enhancement" instead of a "bug" because the specification, while accurately followed, is awkward. It seems that the correct status would be "wontfix" in that case.

Quite possibly. As singleton type inference had already been closed wontfix in #1208 and duplicate in others since, I figured why not cover the bases.

You may be interested to know that if you use the right command line options, you can define the method as you desire. When or if dependent method types will appear for real I cannot say. And yes, mailing list would be a better place.

% scala -Xexperimental

  // def getZero[E <: Enumeration](enum: E): E#Value = enum.withName("zero")
  def getZero[E <: Enumeration](enum: E): enum.Value = enum.withName("zero")

scala> BugTestCase.correctlyTyped
res0: BugTestCase.Broken.Value = zero
scala> BugTestCase.wronglyTyped
res1: BugTestCase.Broken.Value = null

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

1 participant