I was wondering if the compiler is supposed to opt...
# kontributors
u
I was wondering if the compiler is supposed to optimize away the following `when`:
Copy code
typealias NumberType = Double

inline fun Number.toNumberType() = when (NumberType::class) {
    Double::class -> this.toDouble() as NumberType
    Float::class -> this.toFloat() as NumberType
    Long::class -> this.toLong() as NumberType
    Int::class -> this.toInt() as NumberType
    Short::class -> this.toShort() as NumberType
    Byte::class -> this.toByte() as NumberType
    else -> throw IllegalArgumentException("NumberType must be in [Double, Float, Long, Int, Short, Byte]")
}
Looking at the decompiled java code, it generates all
when
branches, not noticing, that only one will ever be selected. Is this expected or should i report? Slack Conversation
o
Please report, it’s a new feature for JVM backend optimisations. /cc @dmitry.petrov
d
Probably not the best use of abstractions, performance-wise. Note that you can also do something like:
Copy code
typealias NumberType = Double
typealias NumberHelper = DoubleHelper

object DoubleHelper {
    fun Number.toNumberType() = toDouble()
}
o
Looks more or less like dead code elimination to me
d
Yes, sure. I see two things here: 1) when by a constant value 2) when by class literal (might be worth optimizing)
It's somewhat self-assuring to see that 1.1.x does not wrap any of those class literals into KClasses 🙂
u
Thanks
@dmitry.petrov the task at hand was to enable me to switch the numeric type with a single change. That's why toDouble is not hardcoded. And i was hoping for the whole when clause to collapse to toDouble
d
Yes, I see. I just pointed out that you can group such operations depending on type specialization into objects, and use typealias for an object. Just curious, in what kind of context you need such kind of generic code?
u
@dmitry.petrov i was writing code to experiment with performance of using different number types and was looking reduce the work of switching the type as far as possible. I don't think, it was an important usecase, but was surprised to see this optimization was not implemented and thought, it might be of general use. After thinking about it, a better abstraction would be something like this:
Copy code
typealias NumberType = Double

inline fun Number.toNumberType() = numericConvert(this, NumberType::class)

inline fun numericConvert(value: Number, type: KClass<Double>) = value.toDouble()
inline fun numericConvert(value: Number, type: KClass<Float>) = value.toFloat()
inline fun numericConvert(value: Number, type: KClass<Long>) = value.toLong()
inline fun numericConvert(value: Number, type: KClass<Int>) = value.toInt()
inline fun numericConvert(value: Number, type: KClass<Short>) = value.toShort()
inline fun numericConvert(value: Number, type: KClass<Byte>) = value.toByte()
But still with optimization in place both should compile down to
toDouble()