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

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

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

   ## 
[Codecov](https://app.codecov.io/gh/apache/groovy/pull/2702?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 69.1155%. Comparing base 
([`86c6648`](https://app.codecov.io/gh/apache/groovy/commit/86c6648d1e61436fe513afaa85d8d0c403de3cda?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache))
 to head 
([`e0fe323`](https://app.codecov.io/gh/apache/groovy/commit/e0fe323119f96a2559ce75bce5dbbd4be302dc17?dropdown=coverage&el=desc&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/2702/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/2702?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
   
   ```diff
   @@                Coverage Diff                 @@
   ##               master      #2702        +/-   ##
   ==================================================
   + Coverage     69.1077%   69.1155%   +0.0077%     
   - Complexity      34235      34239         +4     
   ==================================================
     Files            1537       1537                
     Lines          129356     129356                
     Branches        23503      23503                
   ==================================================
   + Hits            89395      89405        +10     
   + Misses          31941      31933         -8     
   + Partials         8020       8018         -2     
   ```
   
   | [Files with missing 
lines](https://app.codecov.io/gh/apache/groovy/pull/2702?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
 | Coverage Δ | |
   |---|---|---|
   | 
[...in/java/org/codehaus/groovy/classgen/Verifier.java](https://app.codecov.io/gh/apache/groovy/pull/2702?src=pr&el=tree&filepath=src%2Fmain%2Fjava%2Forg%2Fcodehaus%2Fgroovy%2Fclassgen%2FVerifier.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-c3JjL21haW4vamF2YS9vcmcvY29kZWhhdXMvZ3Jvb3Z5L2NsYXNzZ2VuL1ZlcmlmaWVyLmphdmE=)
 | `90.0938% <100.0000%> (ø)` | |
   
   ... and [7 files with indirect coverage 
changes](https://app.codecov.io/gh/apache/groovy/pull/2702/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>




> Covariant bridge methods are emitted in hash order, not the order they are 
> found
> --------------------------------------------------------------------------------
>
>                 Key: GROOVY-12157
>                 URL: https://issues.apache.org/jira/browse/GROOVY-12157
>             Project: Groovy
>          Issue Type: Improvement
>            Reporter: Paul King
>            Assignee: Paul King
>            Priority: Major
>
> h2. Description
> {{Verifier.addCovariantMethods}} collects the bridge methods it needs to 
> generate into unordered maps and then iterates them to emit the methods:
> {code:java}
> // Verifier.java:1679-1680
> Map<String, MethodNode> absInterfaceMethods = new HashMap<>();
> Map<String, MethodNode> allInterfaceMethods = new HashMap<>();
> ...
> // Verifier.java:1719
> Map<String, MethodNode> methodsToAdd = new HashMap<>();
> addCovariantMethods(classNode, declaredMethods, absInterfaceMethods, 
> methodsToAdd, genericsSpec);
> if (!methodsToAdd.isEmpty()) {
>     ...
>     for (Map.Entry<String, MethodNode> entry : methodsToAdd.entrySet()) {
>         // we skip bridge methods implemented in current class already
>         MethodNode mn = declaredMethodsMap.get(entry.getKey());
>         if (mn == null || !mn.getDeclaringClass().equals(classNode)) {
>             addPropertyMethod(entry.getValue());   // <-- emits into the 
> class file
>         }
>     }
> }
> {code}
> The three maps chain into each other — {{allInterfaceMethods}} is iterated to 
> populate {{absInterfaceMethods}} ({{:1699}}), which is iterated as 
> {{interfaceMethods.values()}} ({{:1750}}) to populate {{methodsToAdd}}, which 
> is iterated to call {{addPropertyMethod}}. So *the order of the generated 
> bridge methods in the emitted class file is the hash order of the 
> type-descriptor keys*, not the order in which the methods were discovered.
> h3. Demonstration
> {code:java}
> interface Alpha   { Object alpha()   }
> interface Beta    { Object beta()    }
> interface Gamma   { Object gamma()   }
> interface Delta   { Object delta()   }
> interface Epsilon { Object epsilon() }
> class Sample implements Alpha, Beta, Gamma, Delta, Epsilon {
>     String  alpha()   { null }
>     Integer beta()    { null }
>     Long    gamma()   { null }
>     Double  delta()   { null }
>     Short   epsilon() { null }
> }
> {code}
> {{javap -p Sample.class}} shows the five declared methods in declaration 
> order, followed by the five generated bridges in an arbitrary order:
> {noformat}
> public java.lang.String alpha();
> public java.lang.Integer beta();
> public java.lang.Long gamma();
> public java.lang.Double delta();
> public java.lang.Short epsilon();
> public java.lang.Object alpha();     <-- bridges, in hash order:
> public java.lang.Object gamma();         alpha, gamma, epsilon, beta, delta
> public java.lang.Object epsilon();
> public java.lang.Object beta();
> public java.lang.Object delta();
> {noformat}
> h3. Impact
> The keys are type-descriptor {{String}}s and {{String.hashCode}} is stable, 
> so for a given key set the iteration order is reproducible across JVM runs — 
> this is not, by itself, a live reproducible-builds failure. Two reasons it 
> still matters:
> * The *insertion* order into these maps comes from {{ClassNode.getMethods()}} 
> of the supertypes, which for reflection-configured {{ClassNode}}s is the 
> unspecified JDK reflection order being addressed in GROOVY-12149. Within a 
> colliding bucket, {{HashMap}} chain order follows insertion order, so the 
> emitted bridge order is coupled to that nondeterminism.
> * Even where it is stable, the emitted order is arbitrary rather than 
> meaningful, which makes generated class files harder to diff and reason about.
> h3. Proposed fix
> Use insertion-ordered maps for the three that are iterated to produce output:
> {code:java}
> Map<String, MethodNode> absInterfaceMethods = new LinkedHashMap<>();
> Map<String, MethodNode> allInterfaceMethods = new LinkedHashMap<>();
> ...
> Map<String, MethodNode> methodsToAdd = new LinkedHashMap<>();
> {code}
> Bridge methods are then emitted in the order they are discovered (declaration 
> order in the example above: {{alpha, beta, gamma, delta, epsilon}}). The 
> method *set* is unchanged — only the order.
> {{declaredMethodsMap}} ({{:1724}}) is lookup-only and {{defaultMethods}} 
> ({{:323}}) feeds duplicate-default-method diagnostics only, so neither needs 
> to change.
> h3. Test
> {{src/test/groovy/org/codehaus/groovy/classgen/CovariantBridgeMethodOrderTest.groovy}}
>  compiles the source above via {{CompilationUnit}}, reads the emitted bytes 
> with an ASM {{ClassReader}} (the pattern already used by 
> {{Groovy11776.groovy}}), and asserts the bridge methods appear in declaration 
> order. It fails on the current code with {{['alpha', 'gamma', 'epsilon', 
> 'beta', 'delta']}} and passes with the fix.
> h3. Related
> GROOVY-12149 (nondeterministic reflection order flows into generated 
> bytecode) — feeds the insertion order of these maps. GROOVY-12156 
> (chooseBestMethod returns candidates in identity-hash order) — same class of 
> defect in the static type checker.



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

Reply via email to