This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch groovy11889
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 14ed80064d5ffe09a2debe8d11e927b57f55d660
Author: Paul King <[email protected]>
AuthorDate: Mon Mar 30 11:29:51 2026 +1000

    GROOVY-11889: STC: instanceof check rejects UnionTypeClassNode members as 
incompatible types
---
 .../groovy/transform/stc/StaticTypeCheckingVisitor.java       | 11 ++++++++++-
 .../groovy/groovy/transform/stc/TypeInferenceSTCTest.groovy   |  4 ++--
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git 
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
 
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index fb35f16fce..5e2eaa5a65 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -982,7 +982,16 @@ public class StaticTypeCheckingVisitor extends 
ClassCodeVisitorSupport {
             } else if (op == KEYWORD_INSTANCEOF) {
                 rType = rightExpression.getType();
                 if (lType instanceof 
WideningCategories.LowestUpperBoundClassNode) lType = 
lType.getUnresolvedSuperClass();
-                if (!lType.isInterface() && !rType.isInterface() && 
!(lType.isDerivedFrom(rType) || rType.isDerivedFrom(lType))) {
+                if (lType instanceof UnionTypeClassNode union) {
+                    boolean compatible = rType.isInterface();
+                    for (int i = 0; !compatible && i < 
union.getDelegates().length; i += 1) {
+                        ClassNode delegate = union.getDelegates()[i];
+                        compatible = delegate.isInterface() || 
delegate.isDerivedFrom(rType) || rType.isDerivedFrom(delegate);
+                    }
+                    if (!compatible) {
+                        addError("Incompatible instanceof types: " + 
prettyPrintTypeName(lType) + " and " + prettyPrintTypeName(rType), expression);
+                    }
+                } else if (!lType.isInterface() && !rType.isInterface() && 
!(lType.isDerivedFrom(rType) || rType.isDerivedFrom(lType))) {
                     addError("Incompatible instanceof types: " + 
prettyPrintTypeName(lType) + " and " + prettyPrintTypeName(rType), expression);
                 }
                 pushInstanceOfTypeInfo(leftExpression, rightExpression);
diff --git a/src/test/groovy/groovy/transform/stc/TypeInferenceSTCTest.groovy 
b/src/test/groovy/groovy/transform/stc/TypeInferenceSTCTest.groovy
index 4adea4b051..3bf71668a3 100644
--- a/src/test/groovy/groovy/transform/stc/TypeInferenceSTCTest.groovy
+++ b/src/test/groovy/groovy/transform/stc/TypeInferenceSTCTest.groovy
@@ -537,8 +537,8 @@ class TypeInferenceSTCTest extends 
StaticTypeCheckingTestCase {
         '''
     }
 
-    // GROOVY-7971: negated || instanceof — re-check instanceof in else branch
-    @Test @org.junit.jupiter.api.Disabled('requires instanceof compatibility 
fix for UnionTypeClassNode')
+    // GROOVY-11889: negated || instanceof — re-check instanceof in else branch
+    @Test
     void testInstanceOf25() {
         assertScript '''
             void test(Object x) {

Reply via email to