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

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

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

   ## 
[Codecov](https://app.codecov.io/gh/apache/groovy/pull/3240?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
 Report
   :x: Patch coverage is `88.23529%` with `2 lines` in your changes missing 
coverage. Please review.
   :white_check_mark: Project coverage is 74.1752%. Comparing base 
([`04b8160`](https://app.codecov.io/gh/apache/groovy/commit/04b8160fd112dc086d0785e25ae2f4e6925ec359?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache))
 to head 
([`b39f595`](https://app.codecov.io/gh/apache/groovy/commit/b39f59527c77e458ea75bcdceee5e94384edf8aa?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)).
   
   | [Files with missing 
lines](https://app.codecov.io/gh/apache/groovy/pull/3240?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
 | Patch % | Lines |
   |---|---|---|
   | 
[...a/org/apache/groovy/ast/tools/ExpressionUtils.java](https://app.codecov.io/gh/apache/groovy/pull/3240?src=pr&el=tree&filepath=src%2Fmain%2Fjava%2Forg%2Fapache%2Fgroovy%2Fast%2Ftools%2FExpressionUtils.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-c3JjL21haW4vamF2YS9vcmcvYXBhY2hlL2dyb292eS9hc3QvdG9vbHMvRXhwcmVzc2lvblV0aWxzLmphdmE=)
 | 88.2353% | [1 Missing and 1 partial :warning: 
](https://app.codecov.io/gh/apache/groovy/pull/3240?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
 |
   
   <details><summary>Additional details and impacted files</summary>
   
   
   
   [![Impacted file tree 
graph](https://app.codecov.io/gh/apache/groovy/pull/3240/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/3240?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
   
   ```diff
   @@                Coverage Diff                 @@
   ##               master      #3240        +/-   ##
   ==================================================
   - Coverage     74.1763%   74.1752%   -0.0011%     
   - Complexity      43806      43811         +5     
   ==================================================
     Files            1692       1692                
     Lines          149758     149763         +5     
     Branches        28417      28417                
   ==================================================
   + Hits           111085     111087         +2     
   - Misses          28465      28470         +5     
   + Partials        10208      10206         -2     
   ```
   
   | [Files with missing 
lines](https://app.codecov.io/gh/apache/groovy/pull/3240?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
 | Coverage Δ | |
   |---|---|---|
   | 
[...a/org/apache/groovy/ast/tools/ExpressionUtils.java](https://app.codecov.io/gh/apache/groovy/pull/3240?src=pr&el=tree&filepath=src%2Fmain%2Fjava%2Forg%2Fapache%2Fgroovy%2Fast%2Ftools%2FExpressionUtils.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-c3JjL21haW4vamF2YS9vcmcvYXBhY2hlL2dyb292eS9hc3QvdG9vbHMvRXhwcmVzc2lvblV0aWxzLmphdmE=)
 | `80.0000% <88.2353%> (+0.5882%)` | :arrow_up: |
   
   ... and [10 files with indirect coverage 
changes](https://app.codecov.io/gh/apache/groovy/pull/3240/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>




> Compiler overflows the stack on static final fields whose initializers refer 
> to each other
> ------------------------------------------------------------------------------------------
>
>                 Key: GROOVY-12710
>                 URL: https://issues.apache.org/jira/browse/GROOVY-12710
>             Project: Groovy
>          Issue Type: Bug
>            Reporter: Paul King
>            Priority: Major
>
> h2. Problem
> When {{static final}} fields have initializers that refer back to each other, 
> directly or through other fields, the compiler throws 
> {{java.lang.StackOverflowError}} and the compile is aborted. This happens 
> with ordinary dynamic Groovy; no AST transform or type checking is involved.
> {code:groovy}
> class Cycle {
>     static final String R = S
>     static final String S = R
> }
> println Cycle.R
> {code}
> Actual:
> {noformat}
> Caught: java.lang.StackOverflowError
>         at 
> org.apache.groovy.ast.tools.ExpressionUtils.transformInlineConstants(ExpressionUtils.java)
>         at 
> org.apache.groovy.ast.tools.ExpressionUtils.transformInlineConstants(ExpressionUtils.java)
>         ...
>         at 
> org.codehaus.groovy.classgen.Verifier.addFieldInitialization(Verifier.java)
>         at 
> org.codehaus.groovy.classgen.Verifier.addInitialization(Verifier.java)
>         at org.codehaus.groovy.classgen.Verifier.visitClass(Verifier.java)
> {noformat}
> Every variant below overflows, on 2.5.23, 3.0.25, 4.0.32, 5.1.3, 6.0.0 and 
> master, compiled dynamically, with {{@TypeChecked}} or with 
> {{@CompileStatic}}. For comparison, the Java equivalents with javac:
> ||Fields||Groovy||javac, then running||
> |{{static final String R = S; static final String S = 
> R}}|StackOverflowError|"illegal forward reference"|
> |{{static final String R = Cycle.S; static final String S = 
> Cycle.R}}|StackOverflowError|compiles; prints {{null null}}|
> |{{class A { static final String X = B.Y }}}, {{class B { static final String 
> Y = A.X }}}|StackOverflowError|compiles; prints {{null null}}|
> |{{interface I { String R = J.S }}}, {{interface J { String S = I.R 
> }}}|StackOverflowError|compiles; prints {{null null}}|
> |{{static final String R = R}}|StackOverflowError|"self-reference in 
> initializer"|
> |{{static final String R = Cycle.R}}|StackOverflowError|compiles; prints 
> {{null}}|
> |{{static final int A = Cycle.B + 1; static final int B = Cycle.A + 
> 1}}|StackOverflowError|compiles; prints {{1 2}}|
> Using such a field as an annotation attribute ({{@Ann(Cycle.R)}}) also 
> overflows.
> Instance fields, and {{static}} fields that aren't {{final}}, with the same 
> cyclic initializers compile and run, initialized in declaration order.
> h2. Cause
> {{ExpressionUtils.transformInlineConstants(Expression, ClassNode)}} inlines 
> the value of a {{static final}} field by calling itself on that field's 
> initializer, both for a plain name ({{S}}) and for a qualified one 
> ({{Cycle.S}}). It keeps no record of the fields already being inlined, so a 
> chain of initializers that leads back to an earlier field recurses until the 
> stack overflows. The single-argument {{transformInlineConstants(Expression)}} 
> delegates to it for fields, so it loops the same way.
> Many parts of the compiler use these methods, so the cycle can be reached 
> from several places:
> * class generation ({{Verifier.addFieldInitialization}}), which is where the 
> plain example above fails;
> * annotation handling ({{AnnotationVisitor}}, {{AnnotationConstantsVisitor}});
> * {{ResolveVisitor}} and {{StaticImportVisitor}};
> * {{StaticCompilationTransformer}};
> * the joint-compilation stub generator;
> * groovydoc.
> h2. Proposed fix
> Keep track of the fields being inlined during one call, and when a field is 
> reached again, stop and return the expression unchanged. Its value is then 
> not a compile-time constant, so the field is initialized at runtime in 
> declaration order, as for the non-final case and as in Java. An annotation 
> attribute that refers to such a field then gets the usual error for a value 
> that isn't a constant, instead of overflowing.
> Groovy accepts forward references to static fields, while javac rejects the 
> plain forward reference ({{R = S}}) and the plain self-reference ({{R = R}}). 
> Compiling all the forms, with the runtime values shown above, keeps Groovy 
> consistent with what it already does for non-final fields. Whether to report 
> the plain forms as errors instead, to match Java, is a separate decision.
> h2. Tests
> * Each row of the table above compiles, and gives the value javac's version 
> prints.
> * An annotation attribute referring to a cyclic field reports a 
> constant-expression error and doesn't overflow.
> * A non-cyclic chain ({{static final String R = S}}, {{static final String S 
> = 'x'}}) is still inlined as a constant, for example still usable as an 
> annotation attribute.



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to