Consider the following code:
object Impls {
trait ConcreteImpl {
type Foo = Int
def foo = 1
}
}
trait Base {
type Foo
def foo: Foo
}
I am interested in the expression
(new Base with Impls.ConcreteImpl).foo
When I paste the above code in the REPL, or run it in a worksheet, and then try the expression -- no problem, it prints res0: Int = 1
, as expected.
When I put the code in a file, compile it with scalac
, and then use the compiled class files from the REPL in the same directory, I get the same result.
However, when I use the compiled files, and then say from the REPL
import Impls._
(new Base with ConcreteImpl).foo
it throws
java.lang.AbstractMethodError: $anon$1.foo()I
If I paste all code in the REPL, and use the import variant, this does not happen.
What is happening here? Is this even expected behaviour? If relevant, I am using
Scala version 2.11.5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_45)
It's clearly a bug.
If you:
java.lang.AbstractMethodError: $line13.$read$$iw$$iw$$iw$$iw$$iw$$iw$$anon$1.foo()I
... 33 elided
scala> :javap -p $line13.$read$$iw$$iw$$iw$$iw$$iw$$iw$$anon$1
Compiled from "<console>"
public final class $line13.$read$$iw$$iw$$iw$$iw$$iw$$iw$$anon$1 implements p.Base,p.Impls$ConcreteImpl {
public java.lang.Object foo();
public $line13.$read$$iw$$iw$$iw$$iw$$iw$$iw$$anon$1();
}
It doesn't have a foo with result type Int.
Offhand, I can't imagine the difference in the REPL, but we're about to watch a movie... You can try it in Ammonite, however.
Most such bugs are due to the fact that REPL is a resident compiler, but it's not obvious how that affects compilation with existing class files.
Edit:
It works the first time using fully-qualified names, but then after exhibiting the failure, fully-qualified fails again.
scala> (new p.Base with p.Impls.ConcreteImpl).foo // show
//works
res0: Int = 1
scala> import p._
import p._
scala> import Impls._
import Impls._
scala> (new Base with ConcreteImpl).foo // show
// fails
java.lang.AbstractMethodError: $anon$1.foo()I
... 33 elided
scala> (new p.Base with p.Impls.ConcreteImpl).foo // show
// also fails
java.lang.AbstractMethodError: $anon$1.foo()I
... 33 elided
That's clearly a resident compiler bug. (The classes are in package p here.)
Edit: Actually SI-9689.
来源:https://stackoverflow.com/questions/30698560/abstractmethoderror-when-mixing-in-trait-nested-in-object-only-when-compiled-a