[ 
https://issues.apache.org/jira/browse/GROOVY-12355?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18111776#comment-18111776
 ] 

ASF GitHub Bot commented on GROOVY-12355:
-----------------------------------------

codecov-commenter commented on PR #2878:
URL: https://github.com/apache/groovy/pull/2878#issuecomment-5548513618

   ## 
[Codecov](https://app.codecov.io/gh/apache/groovy/pull/2878?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
 Report
   :white_check_mark: All modified and coverable lines are covered by tests.
   :white_check_mark: Project coverage is 71.0844%. Comparing base 
([`8d6d4d7`](https://app.codecov.io/gh/apache/groovy/commit/8d6d4d7086e190e94ad654685e318d9f14780be4?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache))
 to head 
([`9b45718`](https://app.codecov.io/gh/apache/groovy/commit/9b45718852df68d9b25175338202ab31233089ed?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)).
   :warning: Report is 4 commits behind head on master.
   
   <details><summary>Additional details and impacted files</summary>
   
   
   
   [![Impacted file tree 
graph](https://app.codecov.io/gh/apache/groovy/pull/2878/graphs/tree.svg?width=650&height=150&src=pr&token=1r45138NfQ&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)](https://app.codecov.io/gh/apache/groovy/pull/2878?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
   
   ```diff
   @@                Coverage Diff                 @@
   ##               master      #2878        +/-   ##
   ==================================================
   + Coverage     71.0832%   71.0844%   +0.0012%     
   - Complexity      37312      37330        +18     
   ==================================================
     Files            1578       1579         +1     
     Lines          135392     135453        +61     
     Branches        25086      25095         +9     
   ==================================================
   + Hits            96241      96286        +45     
   - Misses          30473      30487        +14     
   - Partials         8678       8680         +2     
   ```
   
   | [Files with missing 
lines](https://app.codecov.io/gh/apache/groovy/pull/2878?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
 | Coverage Δ | |
   |---|---|---|
   | 
[...roovy/transform/stc/StaticTypeCheckingVisitor.java](https://app.codecov.io/gh/apache/groovy/pull/2878?src=pr&el=tree&filepath=src%2Fmain%2Fjava%2Forg%2Fcodehaus%2Fgroovy%2Ftransform%2Fstc%2FStaticTypeCheckingVisitor.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-c3JjL21haW4vamF2YS9vcmcvY29kZWhhdXMvZ3Jvb3Z5L3RyYW5zZm9ybS9zdGMvU3RhdGljVHlwZUNoZWNraW5nVmlzaXRvci5qYXZh)
 | `87.2386% <100.0000%> (+0.0635%)` | :arrow_up: |
   
   ... and [11 files with indirect coverage 
changes](https://app.codecov.io/gh/apache/groovy/pull/2878/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
   </details>
   <details><summary> :rocket: New features to boost your workflow: </summary>
   
   - :snowflake: [Test 
Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, 
report on failures, and find test suite problems.
   - :package: [JS Bundle 
Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save 
yourself from yourself by tracking and limiting bundle sizes in JS merges.
   </details>




> STC infers BigDecimal for division of Number or wrapper Double/Float operands
> -----------------------------------------------------------------------------
>
>                 Key: GROOVY-12355
>                 URL: https://issues.apache.org/jira/browse/GROOVY-12355
>             Project: Groovy
>          Issue Type: Bug
>    Affects Versions: 6.0.0-RC-1, 5.1.2
>            Reporter: Paul King
>            Assignee: Paul King
>            Priority: Major
>
> Under {{@CompileStatic}} (and {{@TypeChecked}}), the static type checker 
> infers {{BigDecimal}} as the result of a division whenever neither operand is 
> a *primitive* {{float}} or {{double}}. This is wrong in two cases:
> * wrapper {{Double}}/{{Float}} operands, e.g. {{Double / Integer}}, which 
> dynamic Groovy evaluates to a {{Double}}
> * operands whose static type is {{Number}} (or another non-leaf numeric 
> type), where the runtime category is unknown
> In {{StaticTypeCheckingVisitor.getMathResultType}}, the {{DIVIDE}} branch 
> uses {{isFloatingCategory}}, which only recognises primitives, and otherwise 
> falls back to {{BigDecimal_TYPE}}. Group operations ({{+}}, {{-}}, {{*}}) 
> already fall back to {{Number_TYPE}} via {{getGroupOperationResultType}}; 
> division should do the same, i.e. infer the LUB {{Number}} when the operand 
> category can't be determined, and {{Double}} when either operand is a wrapper 
> floating type. This matches the runtime signature {{NumberMath.divide(Number, 
> Number): Number}}.
> The wrong inference is masked in a simple assignment, because the assignment 
> path runs {{castToType}} which converts a {{Double}} to a {{BigDecimal}}. So 
> {{def q = a / b}} silently returns a different type to dynamic Groovy. In a 
> chained expression the compiler emits a {{CHECKCAST}} to {{BigDecimal}} and 
> the code throws {{ClassCastException}}.
> h3. Reproducer
> {code:groovy}
> import groovy.transform.CompileStatic
> @CompileStatic
> class P {
>     static Object nn(Number a, Number b) { a / b }
>     static Object nnChain(Number a, Number b) { ((a / b) * 8).intValue() }
>     static Object di(Double a, Integer b) { a / b }
>     static Object diChain(Double a, Integer b) { ((a / b) * 8).intValue() }
> }
> class D { // dynamic, for comparison
>     static Object nn(Number a, Number b) { a / b }
>     static Object nnChain(Number a, Number b) { ((a / b) * 8).intValue() }
> }
> assert D.nn(1.5d, 2) instanceof Double        // 0.75
> assert D.nnChain(1.5d, 2) == 6
> assert P.nn(1.5d, 2) instanceof BigDecimal    // differs from dynamic
> assert P.di(1.5d, 2) instanceof BigDecimal    // differs from dynamic
> P.nnChain(1.5d, 2)  // ClassCastException: Double cannot be cast to BigDecimal
> P.diChain(1.5d, 2)  // ClassCastException: Double cannot be cast to BigDecimal
> {code}
> Results, called with {{(1.5d, 2)}}:
> ||expression||dynamic||@CompileStatic||
> |{{Number / Number}}|{{Double}} 0.75|{{BigDecimal}} 0.75|
> |{{Double / Integer}}|{{Double}} 0.75|{{BigDecimal}} 0.75|
> |{{((Number / Number) * 8).intValue()}}|6|{{ClassCastException}}|
> |{{((Double / Integer) * 8).intValue()}}|6|{{ClassCastException}}|
> |{{double / int}}|{{Double}}|{{double}}|
> Behaviour is identical on 4.0.33, 5.1.1 and 6.0.0-beta-3, so this is 
> long-standing rather than a regression.
> h3. Real-world impact
> {{org.codehaus.groovy.util.StringUtil.bar(Number x, Number min, Number max, 
> int width)}} (added in 5.0.0) is compiled statically and contains exactly the 
> chained shape above:
> {code:groovy}
> int barWidth = ((x - min) / interval * fracWidth).intValue()
> {code}
> so {{bar(0.45d, 0, 2)}} (or any {{Double}}/{{Float}} argument) throws 
> {{ClassCastException}}, while {{bar(0.45, 0, 2)}} with a {{BigDecimal}} 
> literal works. Fixing the inference makes {{bar}} work without changes, since 
> every intermediate becomes {{Number}}.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to