2012-07-02 13 views
5

Ho una semplice applicazione: (. Il t2mapper da this answer)Perché il codice Scala lancia IllegalAccessError in fase di runtime?

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)) 
} 

Il codice compila bene:

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

ma quando viene eseguito, viene generata IllegalAccessError (primaHello! viene stampato):

 
$ 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) 

Nota che, con le ultime due righe sostituiti con

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)) 

esso stampa (2,4) come previsto. Ma quando avvolto in un blocco

{ 
    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)) 
    } 

si genera l'eccezione.

Perché il primo e l'ultimo modo causano a JVM di generare un errore in fase di esecuzione?

+0

Ho segnalato questo come un problema a https://issues.scala-lang.org/browse/SI-6019. –

risposta

4

Sembra che ci siano alcuni bug aperti rilevanti. Per esempio, questo potrebbe essere correlato:

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

Nota è anche possibile creare un metodo, invece di estendere Appmain e funzionerà.

EDIT:

Quando si utilizza questa linea (ho ampliato l'implicito):

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

E poi mouseover foo o bar in Eclipse, mostra private[this] val foo.

Pertanto, sembra molto simile a SI-5251.

+0

Non penso che sia un bug, perché nel mio primo esempio tutto è pubblico. –

+0

In ogni caso, pensi che sia solo un bug del compilatore? –

+0

@Mechanicalsnail - Penso che sia probabilmente una variazione del bug 5251 di cui ho parlato. Vedi la mia modifica per il motivo. – david

Problemi correlati