I was inspecting the byte-code generated by implicit classes and wanted to compare to what is generated when they extend AnyVal.
Without implicit:
object Example1 { class Wrapper(val self: Int) extends AnyVal { def add(n: Int): Int = self + n } def foo(w: Wrapper): Wrapper = new Wrapper(w.add(42)) } The (relevant part of) bytecode:
scala>:javap Example1 [...] public int foo(int); descriptor: (I)I flags: ACC_PUBLIC Code: stack=3, locals=2, args_size=2 0: getstatic #19 // Field Example1$Wrapper$.MODULE$:LExample1$Wrapper$; 3: iload_1 4: bipush 42 6: invokevirtual #23 // Method Example1$Wrapper$.add$extension:(II)I 9: ireturn LocalVariableTable: Start Length Slot Name Signature 0 10 0 this LExample1$; 0 10 1 w I LineNumberTable: line 11: 3 [...] With implicit:
object Example2 { implicit class Wrapper(val self: Int) extends AnyVal { def add(n: Int): Int = self + n } def foo(w: Wrapper): Wrapper = w.add(42) } The (relevant part of) byte-code:
scala>:javap Example2 [...] public int Wrapper(int); descriptor: (I)I flags: ACC_PUBLIC Code: stack=1, locals=2, args_size=2 0: iload_1 1: ireturn LocalVariableTable: Start Length Slot Name Signature 0 2 0 this LExample2$; 0 2 1 self I LineNumberTable: line 9: 0 public int foo(int); descriptor: (I)I flags: ACC_PUBLIC Code: stack=4, locals=2, args_size=2 0: aload_0 1: getstatic #23 // Field Example2$Wrapper$.MODULE$:LExample2$Wrapper$; 4: iload_1 5: bipush 42 7: invokevirtual #27 // Method Example2$Wrapper$.add$extension:(II)I 10: invokevirtual #29 // Method Wrapper:(I)I 13: ireturn LocalVariableTable: Start Length Slot Name Signature 0 14 0 this LExample2$; 0 14 1 w I LineNumberTable: line 12: 0 [...] As a result of extending AnyVal the call to add is invoked on the companion object, and the type Wrapper does not show in the type signature of foo (public int foo(int);) in both versions.
Hovewer, in the second version, there is a call just before return: 10: invokevirtual #29. It calls public int Wrapper(int); which seemingly doesn't do anything. (Although I might be wrong, as I don't have much experience with reading the byte-code)
So the question is, what's the significance of that call? Can't it be omitted?