Value classes and universal traits

Hi there,

If I understood the Scala documentation correctly “Value classes” can extend universal traits but extending traits requires to allocate memory (Universal traits allow basic inheritance of methods for value classes, but they incur the overhead of allocation).
What is not clear in the documentation is the circumstances where the memory allocation is required (systematically or when a method of the trait is called). So I think the documentation could be more detailed on this specific point.

Now my question: I was wondering if the boxing/instantiation of value class could be avoided when the universal trait is sealed.
It would allow to have multiple value classes extending a fixed set of methods. The methods of the “sealed universal trait” could eventually inlined in the singleton generated by the compiler.

Thanks!

David

That’s strange. I thought instantiation wasn’t necessary as long as the static type of the variable on which you invoke a method is a value class. But indeed:

scala> trait Foo extends Any { def foo = 42 }
defined trait Foo

scala> class MyInt(val a: Int) extends AnyVal with Foo
defined class MyInt

scala> object Bar { def bar(i: MyInt) = i.foo }
defined object Bar

scala> :javap -cp -filter Bar
......
  public int bar(int);
    Code:
       0: new           #14                 // class MyInt
       3: dup
       4: iload_1
       5: invokespecial #35                 // Method MyInt."<init>":(I)V
       8: invokevirtual #39                 // Method MyInt.foo:()I
      11: ireturn
......

But when you override foo it does work:

scala> class MyInt(val a: Int) extends AnyVal with Foo { override def foo = super.foo }
defined class MyInt

scala> object Bar { def bar(i: MyInt) = i.foo }
defined object Bar

scala> :javap -cp -filter Bar
.......
  public int bar(int);
    Code:
       0: getstatic     #35                 // Field MyInt$.MODULE$:LMyInt$;
       3: iload_1
       4: invokevirtual #38                 // Method MyInt$.foo$extension:(I)I
       7: ireturn
........

I would think enough information is available at compile time to generate the necessary forwarder methods in both cases.

EDIT

Oh wait, there’s still boxing I see:

  public final int foo$extension(int);
    Code:
       0: new           #14                 // class MyInt
       3: dup
       4: iload_1
       5: invokespecial #29                 // Method MyInt."<init>":(I)V
       8: invokevirtual #33                 // Method MyInt.$line13$$read$MyInt$$super$foo:()I
      11: ireturn

In hindsight, I guess it’s probably not possible to generate the $extension method in the general case, because the implementation of foo is not always available to the compiler. The sealed trait thing is probably not the worst idea then.

Will TASTY change anything in that respect?

See also https://issues.scala-lang.org/browse/SI-9731

@Jasper: on my machine “:javap -cp -filter Bar” does not work but I have similar results when executing “:javap -c Bar.class” or “:javap -c MyInt$.class”

@lrytz: thank you for the link to this issue.