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

Enumeration's Value is doing something very strange on Scala 2.8 #2827

Closed
scabug opened this issue Dec 21, 2009 · 3 comments
Closed

Enumeration's Value is doing something very strange on Scala 2.8 #2827

scabug opened this issue Dec 21, 2009 · 3 comments
Assignees
Labels

Comments

@scabug
Copy link

scabug commented Dec 21, 2009

This innocent code has no problems:

object Stooges extends Enumeration {
  type Stooge = Value
  val Larry, Curly, Moe = Value
}

This still innocent code produces the weirdest stuff:

object Stooges extends Enumeration {
  type Stooge = Value
  val Larry, Curly, Moe = Value
  def nextStooge(v:Stooges.Stooge):Stooges.Stooge =
    Stooges((v.id+1) % Stooges.maxId)
}

By weirdest, I mean the following:

scala> Stooges.Larry
java.lang.IllegalArgumentException: wrong number of arguments
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at scala.Enumeration$$$$anonfun$$scala$$Enumeration$$$$nameOf$$2.apply(Enumeration.scala:176)
        at scala.Enumeration$$$$anonfun$$scala$$Enumeration$$$$nameOf$$2.apply(Enumeration.scala:171)
        at scala.collection.TraversableLike$$WithFilter$$$$anonfun$$foreach$$1.apply(TraversableLike.scala:1218)
        at scala.collection.IndexedSeqLike$$class.foreach(IndexedSeqLike.scala:87)
        at scala.collection.mutable.ArrayOps.foreach(ArrayOps.scala:20)
        at scala.collection.TraversableLike$$WithFilter.foreach(TraversableLike.scala:1217)
        at scala.Enumeration.scala$$Enumeration$$$$nameOf(Enumeration.scala:171)
        at scala.Enumeration$$Val.toString(Enumeration.scala:237)
        at scala.runtime.ScalaRunTime$$.stringOf(ScalaRunTime.scala:145)
        at RequestResult$$.<init>(<console>:9)
        at RequestResult$$.<clinit>(<console>)
        at RequestResult$$scala_repl_result(<console>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at scala.tools.nsc.Interpreter$$Request$$$$anonfun$$loadAndRun$$1$$$$anonfun$$apply$$13.apply(Interpreter.scala:798)
        at scala.tools.nsc.Interpreter$$Request$$$$anonfun$$loadAndRun$$1$$$$anonfun$$apply$$13.apply(Interpreter.scala:798)
        at scala.util.control.Exception$$Catch.apply(Exception.scala:79)
        at scala.tools.nsc.Interpreter$$Request$$$$anonfun$$loadAndRun$$1.apply(Interpreter.scala:797)
        at scala.tools.nsc.Interpreter$$Request$$$$anonfun$$loadAndRun$$1.apply(Interpreter.scala:797)
        at scala.util.control.Exception$$Catch.apply(Exception.scala:79)
        at scala.tools.nsc.Interpreter$$Request.loadAndRun(Interpreter.scala:796)
        at scala.tools.nsc.Interpreter.interpret(Interpreter.scala:445)
        at scala.tools.nsc.Interpreter.interpret(Interpreter.scala:435)
        at scala.tools.nsc.InterpreterLoop.interpretStartingWith(InterpreterLoop.scala:345)
        at scala.tools.nsc.InterpreterLoop.command(InterpreterLoop.scala:322)
        at scala.tools.nsc.InterpreterLoop.processLine...
scala> Stooges.Curly
java.lang.IllegalArgumentException: wrong number of arguments
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at scala.Enumeration$$$$anonfun$$scala$$Enumeration$$$$nameOf$$2.apply(Enumeration.scala:176)
        at scala.Enumeration$$$$anonfun$$scala$$Enumeration$$$$nameOf$$2.apply(Enumeration.scala:171)
        at scala.collection.TraversableLike$$WithFilter$$$$anonfun$$foreach$$1.apply(TraversableLike.scala:1218)
        at scala.collection.IndexedSeqLike$$class.foreach(IndexedSeqLike.scala:87)
        at scala.collection.mutable.ArrayOps.foreach(ArrayOps.scala:20)
        at scala.collection.TraversableLike$$WithFilter.foreach(TraversableLike.scala:1217)
        at scala.Enumeration.scala$$Enumeration$$$$nameOf(Enumeration.scala:171)
        at scala.Enumeration$$Val.toString(Enumeration.scala:237)
        at scala.runtime.ScalaRunTime$$.stringOf(ScalaRunTime.scala:145)
        at RequestResult$$.<init>(<console>:9)
        at RequestResult$$.<clinit>(<console>)
        at RequestResult$$scala_repl_result(<console>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at scala.tools.nsc.Interpreter$$Request$$$$anonfun$$loadAndRun$$1$$$$anonfun$$apply$$13.apply(Interpreter.scala:798)
        at scala.tools.nsc.Interpreter$$Request$$$$anonfun$$loadAndRun$$1$$$$anonfun$$apply$$13.apply(Interpreter.scala:798)
        at scala.util.control.Exception$$Catch.apply(Exception.scala:79)
        at scala.tools.nsc.Interpreter$$Request$$$$anonfun$$loadAndRun$$1.apply(Interpreter.scala:797)
        at scala.tools.nsc.Interpreter$$Request$$$$anonfun$$loadAndRun$$1.apply(Interpreter.scala:797)
        at scala.util.control.Exception$$Catch.apply(Exception.scala:79)
        at scala.tools.nsc.Interpreter$$Request.loadAndRun(Interpreter.scala:796)
        at scala.tools.nsc.Interpreter.interpret(Interpreter.scala:445)
        at scala.tools.nsc.Interpreter.interpret(Interpreter.scala:435)
        at scala.tools.nsc.InterpreterLoop.interpretStartingWith(InterpreterLoop.scala:345)
        at scala.tools.nsc.InterpreterLoop.command(InterpreterLoop.scala:322)
        at scala.tools.nsc.InterpreterLoop.processLine...
scala> Stooges.Moe
res2: Stooges.Value = Moe

The Stooge which won't crash has varied in my tests with no discernible pattern I could detect. Granted, I didn't spend much time trying to detect a pattern.

@scabug
Copy link
Author

scabug commented Dec 21, 2009

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

@scabug
Copy link
Author

scabug commented Dec 21, 2009

@harrah said:
The problem is in Enumeration.nameOf:

private def nameOf(i: Int): String = 
[...]
      val methods = getClass.getMethods
      for (m <- methods
                if classOf[Value].isAssignableFrom(m.getReturnType) &&
                   !java.lang.reflect.Modifier.isFinal(m.getModifiers)) {
        val name = m.getName
        // invoke method to obtain actual `Value` instance
        val value = m.invoke(this)
[...]

It iterates over all methods in the Enumeration (here, Stooges), keeping only subclasses of Value. It then invokes these methods on the Enumeration instance (again, Stooges here) without any arguments. The problem is that the crashing Stooges includes an extra method that returns a subclass of Value but accepts arguments.

Fixes should be:

  • add && m.getParameterTypes.isEmpty to the filter
  • Verify that there is a field with the same name and return type as the method to ensure it is a val. Otherwise, a user-defined method might be invoked unnecessarily.
  • Make nameOf synchronized since it modifies nmap, which is mutable.

@scabug
Copy link
Author

scabug commented Mar 19, 2010

@phaller said:
(In r21216) Closes #2827. Review by community.

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

No branches or pull requests

2 participants