Hey! In 2.0.0-RC1 JS IR, floating-point string rep...
# k2-adopters
c
Hey! In 2.0.0-RC1 JS IR, floating-point string representation has changed inconsistently. Reproduction code (playground link):
Copy code
println("Float: ${2f}")
println("Double: ${2.0}")
    
println("Float in map: ${mapOf("float" to 2f)}")
println("Double in map: ${mapOf("double" to 2.0)}")
Output with 1.9.23:
Copy code
Float: 2
Double: 2
Float in map: {float=2}
Double in map: {double=2}
Output with 2.0.0-RC1
Copy code
Float: 2.0
Double: 2.0
Float in map: {float=2}
Double in map: {double=2}
For reference, the JVM equivalent (unchanged between both versions):
Copy code
Float: 2.0
Double: 2.0
Float in map: {float=2.0}
Double in map: {double=2.0}
This is inconvenient. Because the representation is different on JS and JVM, I had a test I had to fix with something similar to:
Copy code
assertEquals(
    mapOf(
        "float" to "${9.0}", // JVM will print "9.0", JS will print "9"
    ),
    …
)
but now, this workaround doesn't work anymore, since the string representation of floating values is not consistent with a map which contains them's representation. If it is a conscious decision to overall floating-point string representation in 2.0.0, I personally would prefer to always use the
2.0
notation to have the same behavior on JS and JVM.
youtrack 2
👀 1
p
I think it is duplicate of this. It would be partially fixed in RC2. Unfortunately we have no much options exepct using jvm version in const vals and annotation parameters (it actually worked like that in before). But everything else would be consistent with js.
e
So the TLDR is we can expect this case to be fixed soon. And the
toString
representation to align to the JVM one. Correct?
p
No, optosite. It would be rallbacked to how it behaved in 1.9.20 (i.e. as js native toString()) in all cases except this two, where unfortunately jvm behaviour would persist.
Copy code
// 1 case (const vals)
const val x = 1.0.toString() // evaluated at compile time -> "1.0"
val x = 1.0.toString() // evaluated at runtime -> "1"
// 2 case (annotation arguments)
@Deprated(level = DeprecationLevel.WARNING, message = "${1.0}") // evaluated at compile time -> "1.0" in error message
fun foo()
We expect people not to use .toString() in constants much, so this looks like much smaller issue (and it already happened in 1.9.20 in some random cases) What is fixed, is this "compile time behaviour" was removed from normal strings in code as in your example. As for fixing behaviour to be consistent with jvm, we don't have any specific plans yet, it probably can't be done without significant perfomance penalty.
gratitude thank you 1
e
I'm happy to have a behavior consistent with the JS platform. But this case
Copy code
const val x = 1.0.toString() // evaluated at compile time -> "1.0"
val x = 1.0.toString() // evaluated at runtime -> "1"
Seems very problematic. I would totally expect the same representation here, that is
1
(and not
1.0
)
p
I agree, that it is problematic, as it is really counter-intuitive. But I wouldn't it's very often, as probably, if you have string constant, you can just have this string constant as value, not
.toString()
of something. I hope we would either eventually either make it consistent, or prohibit it with some reasonable error.
c
My problem was in unit tests. The expected value is a hardcoded string, but the actual value comes from a function, and in 2.0.0-RC1 they are different.
I would prefer if all platforms were consistent with each other, but I'm happy as long as platforms are consistent with themselves.
p
With hardcoded string everything would work in 2.0.0-RC2. The only problematic case should still work strange in 2.0.0-RC2 is
const val
initializer.
👍 2
e
I'm happy as long as platforms are consistent with themselves
I'd prefer this path to be honest. All consistent with the JS spec.