You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2020/09/25 18:16:45 UTC

[groovy] 02/02: GROOVY-9454: STC: check for instanceof type before using the field type

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

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

commit e9173a9b9115721aba818ba9caa4b7f7339a7bec
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Sep 25 13:11:48 2020 -0500

    GROOVY-9454: STC: check for instanceof type before using the field type
---
 .../transform/stc/StaticTypeCheckingVisitor.java   |  7 +++-
 .../transform/stc/TypeInferenceSTCTest.groovy      | 38 ++++++++++++++++++----
 2 files changed, 38 insertions(+), 7 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 e3d802e..d66d3a0 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -643,7 +643,12 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             } else {
                 checkOrMarkPrivateAccess(vexp, fieldNode, isLHSOfEnclosingAssignment(vexp));
 
-                storeType(vexp, getType(vexp));
+                ClassNode inferredType = getInferredTypeFromTempInfo(vexp, null);
+                if (inferredType != null && !inferredType.equals(OBJECT_TYPE)) {
+                    vexp.putNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE, inferredType);
+                } else {
+                    storeType(vexp, getType(vexp));
+                }
             }
         }
 
diff --git a/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy b/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
index 74af5b2..e81e5d5 100644
--- a/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
+++ b/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
@@ -18,16 +18,16 @@
  */
 package groovy.transform.stc
 
+import org.codehaus.groovy.ast.ClassHelper
+import org.codehaus.groovy.ast.ClassNode
 import org.codehaus.groovy.ast.MethodNode
-import org.codehaus.groovy.control.customizers.CompilationCustomizer
+import org.codehaus.groovy.ast.tools.WideningCategories
+import org.codehaus.groovy.classgen.GeneratorContext
 import org.codehaus.groovy.control.CompilationUnit
 import org.codehaus.groovy.control.CompilePhase
 import org.codehaus.groovy.control.SourceUnit
-import org.codehaus.groovy.classgen.GeneratorContext
-import org.codehaus.groovy.ast.ClassNode
-import org.codehaus.groovy.ast.ClassHelper
+import org.codehaus.groovy.control.customizers.CompilationCustomizer
 import org.codehaus.groovy.transform.stc.StaticTypesMarker
-import org.codehaus.groovy.ast.tools.WideningCategories
 
 /**
  * Unit tests for static type checking : type inference.
@@ -143,6 +143,32 @@ class TypeInferenceSTCTest extends StaticTypeCheckingTestCase {
         ''', 'Cannot find matching method java.lang.Object#toUpperCase()'
     }
 
+    // GROOVY-9454
+    void testInstanceOfOnGenericProperty() {
+        assertScript '''
+            interface Face {
+            }
+            class Impl implements Face {
+                String something
+            }
+            class Task<R extends Face> implements java.util.concurrent.Callable<String> {
+                R request
+                @Override
+                String call() {
+                    if (request instanceof Impl) {
+                        def thing = request.something // No such property: something for class: R
+                        def lower = thing.toLowerCase()
+                    } else {
+                        // ...
+                        return null
+                    }
+                }
+            }
+            def task = new Task<Impl>(request: new Impl(something: 'Hello World'))
+            assert task.call() == 'hello world'
+        '''
+    }
+
     void testMultipleInstanceOf() {
         assertScript '''
             class A {
@@ -482,7 +508,7 @@ class TypeInferenceSTCTest extends StaticTypeCheckingTestCase {
             keys*.toUpperCase()
             values*.toUpperCase()
         '''
-        
+
         shouldFailWithMessages '''
             List values = [x:1,y:2,z:3]*.value
             values*.toUpperCase()