GROOVY-11998: Better support of intersection types#2518
Open
paulk-asert wants to merge 7 commits intoapache:masterfrom
Open
GROOVY-11998: Better support of intersection types#2518paulk-asert wants to merge 7 commits intoapache:masterfrom
paulk-asert wants to merge 7 commits intoapache:masterfrom
Conversation
Grammar + AST. intersectionType rule, IntersectionTypeClassNode, AstBuilder updates. Includes parser tests; no semantic impact (ResolveVisitor errors out on it).
Resolution + STC. ResolveVisitor resolves components; StaticTypeCheckingVisitor.visitCastExpression validates and propagates. LAMBDA_MARKERS metadata. Static error messages.
Bytecode for lambdas/method refs. writeFunctionalInterfaceIndy markers, altMetafactory flags. Static parity with Java's (R & S) ()->….
as coercion. Closure asType overload, ProxyGenerator plumbing, dynamic castToType(Object, Class[]).
Closure literal native intersection. StaticTypesClosureWriter generates a class implementing all components for (R & S) { -> ... }, docs.
…tstrap and user classloaders
There was a problem hiding this comment.
Pull request overview
This PR implements parser/AST, type-checking, and codegen/runtime support for intersection-type cast and as coercion (GROOVY-11998), including marker-interface threading for lambdas/method references and a runtime fallback path for non-functional sources. It also includes a related fix for proxy generation when mixing bootstrap-loaded and user-loaded interfaces (GROOVY-11999), plus extensive tests and spec documentation updates.
Changes:
- Extend the ANTLR grammar + AST builder to parse intersection types in cast targets and
ascoercion targets, producing anIntersectionTypeClassNode. - Add resolution + STC support for intersection targets and propagate marker-interface metadata into indy lambda/method-reference generation.
- Route non-functional intersection casts/coercions through a new runtime helper and harden proxy generation against
null(bootstrap) classloaders.
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| src/antlr/GroovyParser.g4 | Grammar changes: intersection types in cast parens and coercionType for as/!instanceof. |
| src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java | Builds IntersectionTypeClassNode, rejects duplicate intersection components, adjusts as and !instanceof handling. |
| src/main/java/org/codehaus/groovy/ast/IntersectionTypeClassNode.java | New ClassNode representing user-written intersection cast targets with component ordering + reclassification. |
| src/main/java/org/codehaus/groovy/control/ResolveVisitor.java | Resolves intersection components and reclassifies class-vs-interface parts post-resolution. |
| src/main/java/org/codehaus/groovy/transform/stc/StaticTypesMarker.java | Adds markers to carry intersection functional target + marker interfaces through compilation. |
| src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java | Validates/applies intersection-cast behavior in STC and teaches checkCast to decompose intersections. |
| src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java | Emits indy no-op for lambda/methodref intersection casts and invokes runtime helper for other intersection casts/coercions. |
| src/main/java/org/codehaus/groovy/runtime/IntersectionCastSupport.java | New runtime helper for intersection cast/coercion (castTo / asType). |
| src/main/java/org/codehaus/groovy/runtime/ProxyGeneratorAdapter.java | Fixes NPE risk by avoiding storing bootstrap (null) classloaders in internal loader lists. |
| src/main/java/org/codehaus/groovy/classgen/asm/sc/AbstractFunctionalInterfaceWriter.java | Adds marker-aware altMetafactory bootstrap argument construction for intersection targets. |
| src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesLambdaWriter.java | Collects intersection markers and passes them to indy bootstrap for lambdas. |
| src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesMethodReferenceExpressionWriter.java | Threads intersection markers + serializable flag into method-reference indy generation. |
| src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesClosureWriter.java | Adds marker interfaces to statically-compiled closure literal classes when safe. |
| src/spec/doc/core-semantics.adoc | Documents intersection casts/coercion semantics and examples. |
| src/spec/doc/core-differences-java.adoc | Documents Java-difference: intersection casts on lambdas/method refs and Groovy as form. |
| src/spec/test/CoercionTest.groovy | Adds spec tests/examples for intersection casts/coercion. |
| src/test/groovy/org/apache/groovy/parser/antlr4/IntersectionCastParserTest.groovy | Parser-level tests ensuring intersection targets become IntersectionTypeClassNode and invalid cases error. |
| src/test/groovy/groovy/transform/stc/IntersectionCastSTCTest.groovy | STC tests for intersection functional target selection, metadata, and validation errors. |
| src/test/groovy/groovy/lang/IntersectionCastE2ETest.groovy | End-to-end runtime tests for statically compiled intersection lambdas/method references (incl. serialization). |
| src/test/groovy/groovy/lang/IntersectionCoercionTest.groovy | Runtime tests for dynamic intersection cast/coercion on non-functional sources (Closure/Map/value/null). |
| src/test/groovy/groovy/lang/IntersectionClosureLiteralTest.groovy | Tests native marker-interface addition for statically compiled closure literals under intersection casts. |
| src/test/groovy/groovy/util/ProxyGeneratorAdapterTest.groovy | Regression tests for mixing bootstrap + user classloaders in proxy interface lists (GROOVY-11999). |
✅ All tests passed ✅Test Summary
🏷️ Commit: b154bbc Test Failures (first 5 of 10)ExpectedToFailTest > outerOrdering_failurePropagatesFromForkAndIsInverted() (:groovy-test-junit6:test in Build and test / lts (17, macos-latest))ForkedJvmTest > failureInChildJvmPropagatesToParent() (:groovy-test-junit6:test in Build and test / lts (17, macos-latest))ExpectedToFailTest > outerOrdering_failurePropagatesFromForkAndIsInverted() (:groovy-test-junit6:test in Build and test / lts (17, ubuntu-latest))ForkedJvmTest > failureInChildJvmPropagatesToParent() (:groovy-test-junit6:test in Build and test / lts (17, ubuntu-latest))ExpectedToFailTest > outerOrdering_failurePropagatesFromForkAndIsInverted() (:groovy-test-junit6:test in Build and test / lts (17, windows-latest, 1))Learn more about TestLens at testlens.app. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.