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) {
