You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2026/03/30 05:33:29 UTC
(groovy) 01/01: GROOVY-11889: STC: instanceof check rejects UnionTypeClassNode members as incompatible types
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 <pa...@asert.com.au>
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) {