2012-07-02 6 views
5

que tienen una sencilla aplicación: (. El t2mapper es de this answer)¿Por qué este código de Scala arroja IllegalAccessError en tiempo de ejecución?

object Test extends App { 
    implicit def t2mapper[X, X0 <: X, X1 <: X](t: (X0, X1)) = new { 
    def map[R](f: X => R) = (f(t._1), f(t._2)) 
    } 
    println("Hello!") 
    val (foo, bar) = (1, 2) map (_ * 2) 
    println((foo, bar)) 
} 

El código compila bien:

$ scalac -version 
Scala compiler version 2.9.1 -- Copyright 2002-2011, LAMP/EPFL 
$ scalac -unchecked Test.scala 
$ 

pero cuando es ejecutado, se lanza una IllegalAccessError (antesHello! que se imprime):

 
$ java -version 
java version "1.6.0_24" 
OpenJDK Runtime Environment (IcedTea6 1.11.1) (6b24-1.11.1-4ubuntu3) 
OpenJDK Server VM (build 20.0-b12, mixed mode) 
$ scala Test 
java.lang.IllegalAccessError: tried to access field Test$.reflParams$Cache1 from class Test$delayedInit$body 
     at Test$delayedInit$body.(Test.scala:6) 
     at Test$.(Test.scala:1) 
     at Test$.(Test.scala) 
     at Test.main(Test.scala) 
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
     at java.lang.reflect.Method.invoke(Method.java:616) 
     at scala.tools.nsc.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:78) 
     at scala.tools.nsc.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:24) 
     at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:88) 
     at scala.tools.nsc.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:78) 
     at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:101) 
     at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:33) 
     at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:40) 
     at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:56) 
     at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:80) 
     at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:89) 
     at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala) 

Tenga en cuenta que con las dos últimas líneas reemplazados por

println((1, 2) map (_ * 2)) 

o

val (foo, bar) = (2, 4) 
    println((foo, bar)) 

o

val intermediate = (1, 2) map (_ * 2) 
    val (foo, bar) = intermediate 
    println((foo, bar)) 

imprime (2,4) como se esperaba. Pero cuando se envuelve en un bloque

{ 
    val intermediate = (1, 2) map (_ * 2) 
    val (foo, bar) = intermediate 
    println((foo, bar)) 
    } 

o

private val blah = { 
    val intermediate = (1, 2) map (_ * 2) 
    val (foo, bar) = intermediate 
    println((foo, bar)) 
    } 

se produce la excepción.

¿Por qué la primera y última forma provoque una JVM para lanzar un error en tiempo de ejecución?

+0

He informado esto como un problema en https://issues.scala-lang.org/browse/SI-6019. –

Respuesta

4

Parece que hay algunos errores abiertos relevantes. Por ejemplo, éste podría estar relacionada:

https://issues.scala-lang.org/browse/SI-5251?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel

Nota También puede crear un método en lugar de extender Appmain y funcionará.

EDIT:

Cuando se utiliza esta línea (I amplió la implícita):

val (foo, bar) = t2mapper((1, 2)) map (_ * 2) 

Y luego pasa el ratón foo o bar en Eclipse, que muestra private[this] val foo.

Por lo tanto, parece muy similar al IS-5251.

+0

No creo que sea un error, porque en mi primer ejemplo todo es público. –

+0

De todos modos, ¿crees que es solo un error del compilador? –

+0

@Mechanicalsnail - creo que es probablemente una variación del error 5251 que he mencionado. Ver mi edición por la razón. – david

Cuestiones relacionadas