jamesfredley commented on PR #15558:
URL: https://github.com/apache/grails-core/pull/15558#issuecomment-4445122810

   ## 2026-05-13 audit pass against Groovy 6.0.0-SNAPSHOT build #645
   
   Pulled `apache/groovy` master to commit `0a04376328` ("try to make JMX tests 
more resilient", 2026-05-13 13:20 UTC) and the published `6.0.0-SNAPSHOT` 
snapshot at build #645 (`6.0.0-20260513.133635-645`).
   
   ### Snapshot audit window (build #609 -> build #645)
   
   Diff'd `apache/groovy` master `bc4caccca6..0a04376328` (audit window 
2026-05-08 19:42 UTC -> 2026-05-13 13:20 UTC). **No upstream fixes in this 
window map onto a workaround on this canary.** The window contents:
   
   - AI-readiness skills, javadoc/package-info additions
   - `GROOVY-12001` jline 4.1.0 (already in last audit baseline)
   - `GROOVY-12002` MarkdownSlurper support in groovysh
   - `GROOVY-12003` `/img` command in groovysh
   - `GROOVY-12004` grape command line maven/ivy shorthands
   - `GROOVY-12005` Grape cache-corruption / CDN hardening
   - `GROOVY-12006` Gradle 9.5.x bump (build)
   - `GROOVY-12007` log4j2 2.26.0 bump (test dependency)
   
   None overlap with the remaining workaround inventory.
   
   ### Brought forward from `grails8-groovy5-sb4` (merge `d3384e9395`)
   
   - `0ce8095700` Fix dbmigration GroovyChangeLogSpec: drop env-dependent 
log-capture assertions
   - `9b048e177a` Restore micronaut-jackson-databind for grails-forge-web-netty 
JSON runtime
   - The 5.x audit work in `bda52ad1bb` (`8.0.x` merged back into 
`grails8-groovy5-sb4`)
   
   Conflict-free merge (`dependencies.gradle` kept `groovy.version: 
'6.0.0-SNAPSHOT'` on this canary).
   
   ### Standing position
   
   Zero Groovy-6-only workarounds remain on this canary. The five remaining 
workarounds in the description are all inherited from #15557 and reproduce 
identically on Groovy 5.0.6-SNAPSHOT and on Groovy 6.0.0-SNAPSHOT build #645. 
[GROOVY-11985](https://issues.apache.org/jira/browse/GROOVY-11985) is the only 
one with an open upstream ticket and now has a candidate fix in 
[apache/groovy#2529](https://github.com/apache/groovy/pull/2529) - validated 
end-to-end on this canary below.
   
   ---
   
   ## Validation of 
[apache/groovy#2529](https://github.com/apache/groovy/pull/2529) (Paul King, 
GROOVY-11985)
   
   Tested in two independent layers:
   
   ### Layer 1: standalone reproducer
   
   The standalone reproducer at 
[jamesfredley/groovy-trait-static-method-override-bug](https://github.com/jamesfredley/groovy-trait-static-method-override-bug)
 (the minimal extract of the `Validateable` site) was run against both versions 
side-by-side, JDK 21:
   
   | Build | Test 1 (direct call) | Test 2 (`this.defaultNullable()` from trait 
body) | Test 3 (reflection workaround) |
   |---|---|---|---|
   | Apache snapshot **6.0.0-20260513.133635-645** (master HEAD, NO PR #2529) | 
PASS | **FAIL** - override hijacked back to trait helper default | PASS |
   | Local build of 
[apache/groovy#2529](https://github.com/apache/groovy/pull/2529) HEAD 
`9115a3de` rebased on master | PASS | **PASS** - override seen by trait body | 
PASS |
   
   ```
   $ ./gradlew run -PgroovyVersion=6.0.0-20260513.133635-645
   Test 2: trait body sees `this.defaultNullable()` from inside the trait
     result: false   (expected: true if override is honoured, false if hijacked 
by trait helper)
     FAIL - override hijacked back to trait helper default
   
   $ ./gradlew run -PgroovyVersion=6.0.0-SNAPSHOT  # mavenLocal, post-PR-2529 
build
   Test 2: trait body sees `this.defaultNullable()` from inside the trait
     result: true   (expected: true if override is honoured, false if hijacked 
by trait helper)
     PASS - override seen by trait body
   ```
   
   ### Layer 2: real Grails `Validateable` workaround removed, validation tests 
run
   
   Removed the `resolveDefaultNullable(Class<?>)` reflection shim from 
[`grails-validation/.../Validateable.groovy`](https://github.com/apache/grails-core/blob/grails8-groovy6-canary/grails-validation/src/main/groovy/grails/validation/Validateable.groovy#L301-L318)
 and reverted both call sites to direct unqualified `defaultNullable()` calls 
(the natural shape the trait was originally written in):
   
   ```diff
   -            boolean isDefaultNullable = resolveDefaultNullable(this)
   +            boolean isDefaultNullable = defaultNullable()
    ...
   -        boolean isDefaultNullable = resolveDefaultNullable(this.class)
   +        boolean isDefaultNullable = defaultNullable()
    ...
   -    private static boolean resolveDefaultNullable(Class<?> clazz) {
   -        ... // 18-line reflective dispatch helper removed
   -    }
   ```
   
   Then republished the local Groovy build as the unique version 
`6.0.0-PR2529-SNAPSHOT` (so Gradle resolution couldn't fall back to the 
published Apache snapshot of plain `6.0.0-SNAPSHOT`) and pointed 
`dependencies.gradle` at that version. Ran the full `ValidateableTraitSpec` 
suite:
   
   ```
   ./gradlew :grails-validation:compileGroovy :grails-validation:test \
       --tests grails.validation.ValidateableTraitSpec --rerun-tasks --no-daemon
   ```
   
   **Confirmed via build log that the test was executing against 
`6.0.0-PR2529-SNAPSHOT`:**
   
   ```
   Executing Spock 2.4.0-groovy-5.0 with NOT compatible Groovy version 
6.0.0-PR2529-SNAPSHOT
   ```
   
   **Result: 14 of 14 ValidateableTraitSpec tests PASS** (1m 41s, BUILD 
SUCCESSFUL), including the two that fail without Paul's fix when the workaround 
is removed:
   
   | Test | Without workaround, against build #645 (no fix) | Without 
workaround, against PR #2529 |
   |---|---|---|
   | `Test that constraints are nullable by default if overridden and ensure 
nullable:true constraint is not applied when no other constraints were defined 
by user` | **FAIL** - `constraints.size() == 3` got `4`, stray 
`name:nullable:true` from override-not-seen | **PASS** |
   | `Test that properties defined in a class with overridden defaultNullable 
which are not explicitly constrained are not accessed during validation` | 
**FAIL** - `UnsupportedOperationException: getName() should not have been 
called during validation`, override-not-seen forced unconstrained-property 
access | **PASS** |
   | Other 12 ValidateableTraitSpec cases | PASS | PASS |
   
   ### Conclusion
   
   [apache/groovy#2529](https://github.com/apache/groovy/pull/2529) **fully 
resolves** the GROOVY-11985 workaround on this canary. Once it merges to 
`apache/groovy` master and a snapshot publishes containing the fix, the 
`Validateable.resolveDefaultNullable(Class<?>)` reflection shim can be removed 
and both call sites can revert to plain `defaultNullable()`. The local 
validation edit, the unique-version Groovy republish, and the 
`dependencies.gradle` pin were all reverted before this comment; the canary 
tree is back at `d3384e9395`.
   
   Thanks @paulk-asert - this clears the only one of the five remaining 
inherited workarounds that had an open upstream ticket. The other four 
(VariableScopeVisitor canonicalisation NPE, indy=false controller-parameter 
scope loss, ConfigurationBuilder + AbstractConstraint static-init, GROOVY-6362 
/ GROOVY-11817 `g` taglib regression) still need standalone reproducers filed 
against apache/groovy.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to