New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Universal traits shouldn't add allocation to a value class #9731
Comments
Imported From: https://issues.scala-lang.org/browse/SI-9731?orig=1 |
@lrytz said: |
@lrytz said: trait T extends Any {
def s: String
def t1 = s.toUpperCase
} This universal trait needs to be compiled into a valid interface. We don't know that
Now we introduce a value class class C(val s: String) extends AnyVal with T If we don't want to break separate compilation (change the body of T.t1, re-compile T, also C should get the new impl) then we have no choice but to invoke T.t1, which requires an instance. Now there's a few possibilities. We can get actually already quite close just with inlining, but it (currently, 2.12.0-M4) requires an trait T extends Any {
def s: String
@inline final def t1 = s.toUpperCase
}
class C(val s: String) extends AnyVal with T
class A { def f1(c: C) = c.t1 } gives
We're planning to extend our box-unbox optimization to value classes (currently supports tuples and primitive boxes), which would eliminate the allocation. This will probably not happen for 2.12.0, unfortunately - there's not much time left. Note that the JVM's escape analysis will probably also eliminate the box. Other options I see:
the second of this ideas is related to inlining (code is duplicated), also related to what dimitry is researching for dotty (creating specialized copies of methods). |
@lrytz said: |
@lrytz said: |
@DarkDimius said (edited on Apr 26, 2016 8:37:01 AM UTC): trait StringVal extends Any { def value: String ; final override def toString = value } becomes trait StringVal extends Any { def value: String ; final override def toString = StringVal$.toString_extension(this) }
object StringVal { final override def toString_extension[T <: StringVal](t: T): String = t.value } This would allow to pass a value class to the value class to the extension method. object StringVal { // specialized
final override def toString_extension[T <: StringVal](t: T): String = t.value
final override def toString_extension_spec$1[T = Foo](t: T): String = t.value
} This would mean that the normal boxing elimination of value classes would kick-in. object StringVal { // erased
final override def toString_extension(t: StringVal): String = t.value
final override def toString_extension_spec$1(t: String): String = Foo$.value_extension(t)
} |
David Bouyssie (crumbpicker) said: This would be a strong requirement but I think it could help to know the list of possible implementations of the universal trait. |
Sorry for the late reply. @lrytz: I understand that it's not possible to anticipate the nature of the different implementations of a given universal trait. But my question was relative to the use of "sealed universal traits". In this context we can determine exactly the list of implementations. |
Given
javap
shows a difference in bytecode:For more context see https://gitter.im/scala/scala?at=56fd99f0d9b73e635f6823bb where I discovered this with @Ichoran.
(meta: Unsure if to classify this as a bug or an improvement, I've opted for bug)
(meta: Also unsure how best to detail this ticket in the summary)
The text was updated successfully, but these errors were encountered: