[ https://issues.apache.org/jira/browse/GROOVY-9094?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16831064#comment-16831064 ]
Eric Milles edited comment on GROOVY-9094 at 5/1/19 3:33 PM: ------------------------------------------------------------- See also GROOVY-9011 and GROOVY-8948 was (Author: emilles): See also GROOVY-9011 > Coercion to primitive double from primitive integer produces different > results in dynamic and static compilation > ---------------------------------------------------------------------------------------------------------------- > > Key: GROOVY-9094 > URL: https://issues.apache.org/jira/browse/GROOVY-9094 > Project: Groovy > Issue Type: Bug > Components: bytecode, Compiler > Affects Versions: 3.0.0-alpha-4, 2.5.6 > Reporter: Szymon Stępniak > Priority: Major > > Ticket created based on the following question on Stack Overflow - > https://stackoverflow.com/questions/55789411/groovy-primitive-double-arithmetic > It seems like primitive double coercion is unstable. Consider the following > example: > {code:groovy} > void ex1() { > double x = 255 / 2 > println x > } > void ex2() { > Double x = 255 / 2 > println x > } > void ex3() { > def x = 255 / 2 > println x > } > void ex4() { > println 255 / 2 > } > ex1() > ex2() > ex3() > ex4() > {code} > It produces the following output: > {code:bash} > 127.0 > 127.5 > 127.5 > 127.5 > {code} > I checked the generated bytecode and here is what the {{ex1}} method > implementation looks like: > {code:java} > public void ex1() { > CallSite[] var1 = $getCallSiteArray(); > double x = 0.0D; > if (BytecodeInterface8.isOrigInt() && BytecodeInterface8.isOrigD() && > !__$stMC && !BytecodeInterface8.disabledStandardMetaClass()) { > int var5 = 255 / 2; > x = (double)var5; > } else { > Object var4 = var1[5].call(255, 2); > x = DefaultTypeTransformation.doubleUnbox(var4); > } > var1[6].callCurrent(this, x); > } > {code} > And here is what {{ex2}} method's bytecode looks like: > {code:java} > public void ex2() { > CallSite[] var1 = $getCallSiteArray(); > Double x = null; > if (BytecodeInterface8.isOrigInt() && !__$stMC && > !BytecodeInterface8.disabledStandardMetaClass()) { > Object var4 = var1[8].call(255, 2); > x = (Double)ScriptBytecodeAdapter.castToType(var4, Double.class); > } else { > Object var3 = var1[7].call(255, 2); > x = (Double)ScriptBytecodeAdapter.castToType(var3, Double.class); > } > var1[9].callCurrent(this, x); > } > {code} > If we compile statically the first method, it will produce {{127.5}} output, > and will generate the following bytecode: > {code:java} > public void ex1() { > double x = > DefaultTypeTransformation.doubleUnbox(NumberNumberDiv.div(255, 2)); > ((qweqwe23)this).println(x); > Object var10000 = null; > } > {code} > But the weirdest thing happens if we try to use type checking. My first > impression was that this unstable coercion could be avoided if we use type > checking. However, it doesn't work. If I add {{@TypeChecked}} annotation to > {{ex1}} method, it does not make any effect - the code runs and it still > produces {{127.0}} output. But when I add {{@TypeChecked}} to {{ex2}} method, > it does not run and produces the following compilation error. > {code:bash} > Error:(10, 20) Groovyc: [Static type checking] - Cannot assign value of type > java.math.BigDecimal to variable of type java.lang.Double > {code} -- This message was sent by Atlassian JIRA (v7.6.3#76005)