File tree Expand file tree Collapse file tree
main/java/org/codehaus/groovy/transform/stc
test/groovy/groovy/transform/stc Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -982,7 +982,16 @@ && isAssignment(enclosingBinaryExpression.getOperation().getType())) {
982982 } else if (op == KEYWORD_INSTANCEOF ) {
983983 rType = rightExpression .getType ();
984984 if (lType instanceof WideningCategories .LowestUpperBoundClassNode ) lType = lType .getUnresolvedSuperClass ();
985- if (!lType .isInterface () && !rType .isInterface () && !(lType .isDerivedFrom (rType ) || rType .isDerivedFrom (lType ))) {
985+ if (lType instanceof UnionTypeClassNode union ) {
986+ boolean compatible = rType .isInterface ();
987+ for (int i = 0 ; !compatible && i < union .getDelegates ().length ; i += 1 ) {
988+ ClassNode delegate = union .getDelegates ()[i ];
989+ compatible = delegate .isInterface () || delegate .isDerivedFrom (rType ) || rType .isDerivedFrom (delegate );
990+ }
991+ if (!compatible ) {
992+ addError ("Incompatible instanceof types: " + prettyPrintTypeName (lType ) + " and " + prettyPrintTypeName (rType ), expression );
993+ }
994+ } else if (!lType .isInterface () && !rType .isInterface () && !(lType .isDerivedFrom (rType ) || rType .isDerivedFrom (lType ))) {
986995 addError ("Incompatible instanceof types: " + prettyPrintTypeName (lType ) + " and " + prettyPrintTypeName (rType ), expression );
987996 }
988997 pushInstanceOfTypeInfo (leftExpression , rightExpression );
Original file line number Diff line number Diff line change @@ -537,8 +537,8 @@ class TypeInferenceSTCTest extends StaticTypeCheckingTestCase {
537537 '''
538538 }
539539
540- // GROOVY-7971 : negated || instanceof — re-check instanceof in else branch
541- @Test @org.junit.jupiter.api.Disabled ( ' requires instanceof compatibility fix for UnionTypeClassNode ' )
540+ // GROOVY-11889 : negated || instanceof — re-check instanceof in else branch
541+ @Test
542542 void testInstanceOf25 () {
543543 assertScript '''
544544 void test(Object x) {
@@ -569,6 +569,52 @@ class TypeInferenceSTCTest extends StaticTypeCheckingTestCase {
569569 '''
570570 }
571571
572+ // GROOVY-11889: instanceof interface check on union type
573+ @Test
574+ void testInstanceOf27 () {
575+ assertScript '''
576+ void test(Object x) {
577+ if (x instanceof String || x instanceof Integer) {
578+ if (x instanceof Serializable) {
579+ assert true
580+ }
581+ }
582+ }
583+ test('hello')
584+ test(42)
585+ '''
586+ }
587+
588+ // GROOVY-11889: union containing interface delegate
589+ @Test
590+ void testInstanceOf28 () {
591+ assertScript '''
592+ void test(Object x) {
593+ if (x instanceof Serializable || x instanceof String) {
594+ if (x instanceof String) {
595+ assert true
596+ }
597+ }
598+ }
599+ test('hello')
600+ '''
601+ }
602+
603+ // GROOVY-11889: incompatible instanceof on union type should produce error
604+ @Test
605+ void testInstanceOf29 () {
606+ shouldFailWithMessages '''
607+ void test(Object x) {
608+ if (x instanceof String || x instanceof Integer) {
609+ if (x instanceof Long) {
610+ // unreachable - neither String nor Integer is related to Long
611+ }
612+ }
613+ }
614+ ''' ,
615+ ' Incompatible instanceof types'
616+ }
617+
572618 // GROOVY-5226
573619 @Test
574620 void testNestedInstanceOf1 () {
You can’t perform that action at this time.
0 commit comments