Skip to content

Objects extending Enumerations have inaccessible #Value type #3134

Closed
@scabug

Description

@scabug

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions