Does Scala's specialization compose?
I was under the impression that specialization composes, but in the following example that doesn't seem to be the case:
trait Key [@specialized(Int) A] { def up(k: A): Unit } class Test[@specialized(Int) A](key: Key[A], value: A) { key.up(value) }
If I dump this in the Scala REPL with :javap -v Test, it seems that the call to key.up still boxes the primitive:
public Test(Key, java.lang.Object); Code: Stack=2, Locals=3, Args_size=3 0: aload_0 1: aload_1 2: putfield #17; //Field key:LKey; 5: aload_0 6: aload_2 7: putfield #19; //Field value:Ljava/lang/Object; 10: aload_0 11: invokespecial #24; //Method java/lang/Object."<init>":()V 14: aload_0 15: getfield #17; //Field key:LKey; 18: aload_0 19: getfield #19; //Field value:Ljava/lang/Object; 22: invokeinterface #30, 2; //InterfaceMethod Key.up:(Ljava/lang/Object;)V 27: return
So is specialization completely useless for developing generic implementations? In my case, data structures, it would completely undermine the effort to develop concise modular code. So I hope I am missing something...
Answers
You are looking at the unspecialized version of the class.
When I try I see another class Test$mcI$sp that is the specialized compiled version. This is kind of the point, it must create a separate class that is specialized for the primitive you specify.
Edit: if looking for the specialized class in the REPL you need to get the full class name. By default, the REPL trims the actual context where the class is stored, so you need to get it by println eg:
scala> println(new Test(1).getClass.getName) $line1.$read$$iw$$iw$Test$mcI$sp scala> :javap $line1.$read$$iw$$iw$Test$mcI$sp …