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

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


The following commit(s) were added to refs/heads/master by this push:
     new 51eb2a0  GROOVY-10328: STC: `List<? super Type>` dot get returns 
Object, not Type
51eb2a0 is described below

commit 51eb2a026a9ce1b4f6232d8ac4414eda586ac3e0
Author: Eric Milles <[email protected]>
AuthorDate: Sat Oct 23 09:54:15 2021 -0500

    GROOVY-10328: STC: `List<? super Type>` dot get returns Object, not Type
---
 .../transform/stc/StaticTypeCheckingSupport.java   | 12 ++---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 27 +---------
 src/test/groovy/bugs/Groovy9074.groovy             | 46 ++++++++--------
 .../transform/stc/TypeInferenceSTCTest.groovy      | 62 ++++++++++++++--------
 4 files changed, 71 insertions(+), 76 deletions(-)

diff --git 
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
 
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
index e30ff75..a7243a2 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -1754,8 +1754,8 @@ public abstract class StaticTypeCheckingSupport {
                 if (ui.isWildcard()) {
                     extractGenericsConnections(connections, 
ui.getLowerBound(), di.getLowerBound());
                     extractGenericsConnections(connections, 
ui.getUpperBounds(), di.getUpperBounds());
-                } else {
-                    ClassNode boundType = getCombinedBoundType(di);
+                } else if (!isUnboundedWildcard(di)) {
+                    ClassNode boundType = di.getLowerBound() != null ? 
di.getLowerBound() : di.getUpperBounds()[0];
                     if (boundType.isGenericsPlaceHolder()) { // GROOVY-9998
                         String placeholderName = boundType.getUnresolvedName();
                         ui = new GenericsType(ui.getType()); 
ui.setWildcard(true);
@@ -1892,11 +1892,11 @@ public abstract class StaticTypeCheckingSupport {
     }
 
     static ClassNode getCombinedBoundType(final GenericsType genericsType) {
-        // TODO: this method should really return some kind of meta ClassNode
-        // representing the combination of all bounds. The code here, just 
picks
-        // something out to be able to proceed and is not actually correct
+        // TODO: This method should really return some kind of meta ClassNode
+        // representing the combination of all bounds. The code here just picks
+        // something out to be able to proceed and is not actually correct.
         if (hasNonTrivialBounds(genericsType)) {
-            if (genericsType.getLowerBound() != null) return 
genericsType.getLowerBound();
+            if (genericsType.getLowerBound() != null) return OBJECT_TYPE; // 
GROOVY-10328
             if (genericsType.getUpperBounds() != null) return 
genericsType.getUpperBounds()[0];
         }
         return genericsType.getType();
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 f7f75c4..376a857 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -3149,36 +3149,11 @@ public class StaticTypeCheckingVisitor extends 
ClassCodeVisitorSupport {
         ClassNode[] inferred = new ClassNode[returnTypeGenerics.length];
         for (int i = 0, n = returnTypeGenerics.length; i < n; i += 1) {
             GenericsType genericsType = returnTypeGenerics[i];
-            ClassNode value = 
createUsableClassNodeFromGenericsType(genericsType);
-            inferred[i] = value;
+            inferred[i] = getCombinedBoundType(genericsType);
         }
         return inferred;
     }
 
-    /**
-     * Given a GenericsType instance, returns a ClassNode which can be used as 
an inferred type.
-     *
-     * @param genericsType a {@link org.codehaus.groovy.ast.GenericsType} 
representing either a type, a placeholder or a wildcard
-     * @return a class node usable as an inferred type
-     */
-    private static ClassNode createUsableClassNodeFromGenericsType(final 
GenericsType genericsType) {
-        // TODO: Merge with 
StaticTypeCheckingSupport#getCombinedBoundType(GenericsType)?
-        ClassNode value = genericsType.getType();
-        if (genericsType.isPlaceholder()) {
-            value = value.isRedirectNode() ? value.redirect() : OBJECT_TYPE;
-        }
-        ClassNode lowerBound = genericsType.getLowerBound();
-        if (lowerBound != null) {
-            value = lowerBound;
-        } else {
-            ClassNode[] upperBounds = genericsType.getUpperBounds();
-            if (upperBounds != null) {
-                value = lowestUpperBound(Arrays.asList(upperBounds));
-            }
-        }
-        return value;
-    }
-
     private static String[] convertToStringArray(final Expression options) {
         if (options == null) {
             return ResolveVisitor.EMPTY_STRING_ARRAY;
diff --git a/src/test/groovy/bugs/Groovy9074.groovy 
b/src/test/groovy/bugs/Groovy9074.groovy
index aac3c9c..f518ee5 100644
--- a/src/test/groovy/bugs/Groovy9074.groovy
+++ b/src/test/groovy/bugs/Groovy9074.groovy
@@ -29,7 +29,7 @@ final class Groovy9074 extends GroovyTestCase {
 
     void _FIXME_testWildcardCapture() {
         def err = shouldFail '''
-            @groovy.transform.CompileStatic
+            @groovy.transform.TypeChecked
             class Main {
                 private static Collection<?> c = new ArrayList<String>()
                 static main(args) {
@@ -46,20 +46,20 @@ final class Groovy9074 extends GroovyTestCase {
         def err = shouldFail '''
             import java.awt.Canvas
             abstract class Shape {
-              abstract void draw(Canvas c)
+                abstract void draw(Canvas c)
             }
             class Circle extends Shape {
-              private int x, y, radius
-              @Override void draw(Canvas c) {}
+                private int x, y, radius
+                @Override void draw(Canvas c) {}
             }
             class Rectangle extends Shape {
-              private int x, y, width, height
-              @Override void draw(Canvas c) {}
+                private int x, y, width, height
+                @Override void draw(Canvas c) {}
             }
 
-            @groovy.transform.CompileStatic
+            @groovy.transform.TypeChecked
             void addRectangle(List<? extends Shape> shapes) {
-              shapes.add(0, new Rectangle()) // TODO: compile-time error!
+                shapes.add(0, new Rectangle()) // TODO: compile-time error!
             }
         '''
 
@@ -71,20 +71,20 @@ final class Groovy9074 extends GroovyTestCase {
         assertScript '''
             import java.awt.Canvas
             abstract class Shape {
-              abstract void draw(Canvas c)
+                abstract void draw(Canvas c)
             }
             class Circle extends Shape {
-              private int x, y, radius
-              @Override void draw(Canvas c) {}
+                private int x, y, radius
+                @Override void draw(Canvas c) {}
             }
             class Rectangle extends Shape {
-              private int x, y, width, height
-              @Override void draw(Canvas c) {}
+                private int x, y, width, height
+                @Override void draw(Canvas c) {}
             }
 
-            @groovy.transform.CompileStatic
+            @groovy.transform.TypeChecked
             void addRectangle(List<? super Shape> shapes) {
-              shapes.add(0, new Rectangle())
+                shapes.add(0, new Rectangle())
             }
 
             List<Shape> list = []
@@ -99,12 +99,12 @@ final class Groovy9074 extends GroovyTestCase {
         new CompilationUnit().with {
             addSource 'Main.groovy', '''
                 class Factory {
-                  def <T> T make(Class<T> type, ... args) {}
+                    def <T> T make(Class<T> type, ... args) {}
                 }
 
-                @groovy.transform.CompileStatic
+                @groovy.transform.TypeChecked
                 void test(Factory fact, Rule rule) {
-                  Type bean = fact.make(rule.type)
+                    Type bean = fact.make(rule.type)
                 }
             '''
 
@@ -124,16 +124,16 @@ final class Groovy9074 extends GroovyTestCase {
         }
     }
 
-    void _FIXME_testWildcardSuper2() {
+    void testWildcardSuper2() {
         new CompilationUnit().with {
             addSource 'Main.groovy', '''
                 class Factory {
-                  def <T> T make(Class<T> type, ... args) {}
+                    def <T> T make(Class<T> type, ... args) {}
                 }
 
-                @groovy.transform.CompileStatic
+                @groovy.transform.TypeChecked
                 void test(Factory fact, Rule rule) {
-                  Type bean = fact.make(rule.type) // can't assign "? super 
Type" to "Type"
+                    Type bean = fact.make(rule.type) // can't assign "? super 
Type" to "Type"
                 }
             '''
 
@@ -152,7 +152,7 @@ final class Groovy9074 extends GroovyTestCase {
             def err = shouldFail {
                 compile CLASS_GENERATION
             }
-            assert err =~ "cannot convert from capture#1-of ? super Type to 
Type"
+            assert err =~ 'Cannot assign value of type java.lang.Object to 
variable of type Type'
         }
     }
 }
diff --git a/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy 
b/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
index 697a866..3e7cff4 100644
--- a/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
+++ b/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
@@ -787,7 +787,7 @@ class TypeInferenceSTCTest extends 
StaticTypeCheckingTestCase {
             def o
             o = 1L
             o = 2
-            @ASTTest(phase=INSTRUCTION_SELECTION, value= {
+            @ASTTest(phase=INSTRUCTION_SELECTION, value={
                 assert 
node.rightExpression.accessedVariable.getNodeMetaData(DECLARATION_INFERRED_TYPE)
 == long_TYPE
             })
             def z = o
@@ -858,10 +858,10 @@ class TypeInferenceSTCTest extends 
StaticTypeCheckingTestCase {
                         returnValue = 1;
                         break;
                 }
-                @ASTTest(phase=INSTRUCTION_SELECTION,value={
-                    def ift = node.getNodeMetaData(INFERRED_TYPE)
-                    assert ift instanceof LUB
-                    assert ift.name == 'java.io.Serializable'
+                @ASTTest(phase=INSTRUCTION_SELECTION, value={
+                    def type = node.getNodeMetaData(INFERRED_TYPE)
+                    assert type instanceof LUB
+                    assert type.name == 'java.io.Serializable'
                 })
                 def val = returnValue
 
@@ -913,8 +913,8 @@ class TypeInferenceSTCTest extends 
StaticTypeCheckingTestCase {
             assertScript """
             $orig b = 65 as $orig
             @ASTTest(phase=INSTRUCTION_SELECTION, value={
-                def rit = node.rightExpression.getNodeMetaData(INFERRED_TYPE)
-                assert rit == make($dest)
+                def type = node.rightExpression.getNodeMetaData(INFERRED_TYPE)
+                assert type == make($dest)
             })
             def pp = ++b
             println '++${orig} -> ' + pp.class + ' ' + pp
@@ -937,8 +937,8 @@ class TypeInferenceSTCTest extends 
StaticTypeCheckingTestCase {
             assertScript """
             $orig b = 65 as $orig
             @ASTTest(phase=INSTRUCTION_SELECTION, value={
-                def rit = node.rightExpression.getNodeMetaData(INFERRED_TYPE)
-                assert rit == make($dest)
+                def type = node.rightExpression.getNodeMetaData(INFERRED_TYPE)
+                assert type == make($dest)
             })
             def pp = b++
             println '${orig}++ -> ' + pp.class + ' ' + pp
@@ -959,11 +959,11 @@ class TypeInferenceSTCTest extends 
StaticTypeCheckingTestCase {
                     callable.call()
                 }
 
-                @ASTTest(phase=INSTRUCTION_SELECTION,value={
+                @ASTTest(phase=INSTRUCTION_SELECTION, value={
                     lookup('test').each {
                         def call = it.expression
-                        def irt = call.getNodeMetaData(INFERRED_TYPE)
-                        assert irt == LIST_TYPE
+                        def type = call.getNodeMetaData(INFERRED_TYPE)
+                        assert type == LIST_TYPE
                     }
                 })
                 static void run() {
@@ -982,7 +982,7 @@ class TypeInferenceSTCTest extends 
StaticTypeCheckingTestCase {
             public <T> T[] intArray(ArrayFactory<T> f) {
                 f.array()
             }
-            @ASTTest(phase=INSTRUCTION_SELECTION,value={
+            @ASTTest(phase=INSTRUCTION_SELECTION, value={
                 assert node.getNodeMetaData(INFERRED_TYPE) == 
Integer_TYPE.makeArray()
             })
             def array = intArray { new Integer[8] }
@@ -998,10 +998,10 @@ class TypeInferenceSTCTest extends 
StaticTypeCheckingTestCase {
                 f.list()
             }
 
-            @ASTTest(phase=INSTRUCTION_SELECTION,value={
-                def irt = node.getNodeMetaData(INFERRED_TYPE)
-                assert irt == LIST_TYPE
-                assert irt.genericsTypes[0].type == Integer_TYPE
+            @ASTTest(phase=INSTRUCTION_SELECTION, value={
+                def type = node.getNodeMetaData(INFERRED_TYPE)
+                assert type == LIST_TYPE
+                assert type.genericsTypes[0].type == Integer_TYPE
             })
             def res = list { new LinkedList<Integer>() }
             assert res.size() == 0
@@ -1042,7 +1042,7 @@ class TypeInferenceSTCTest extends 
StaticTypeCheckingTestCase {
     void testShouldInferPrimitiveBoolean() {
         assertScript '''
             def foo(Boolean o) {
-                @ASTTest(phase=INSTRUCTION_SELECTION,value={
+                @ASTTest(phase=INSTRUCTION_SELECTION, value={
                     assert node.getNodeMetaData(INFERRED_TYPE) == boolean_TYPE
                 })
                 boolean b = o
@@ -1139,15 +1139,15 @@ class TypeInferenceSTCTest extends 
StaticTypeCheckingTestCase {
                 String field
             }
 
-            @ASTTest(phase=INSTRUCTION_SELECTION,value={
+            @ASTTest(phase=INSTRUCTION_SELECTION, value={
                 lookup('second').each {
-                  assert it.expression.getNodeMetaData(INFERRED_TYPE).name == 
'Ann2'
+                    assert it.expression.getNodeMetaData(INFERRED_TYPE).name 
== 'Ann2'
                 }
             })
             def doit(obj, String propName) {
                 def field = obj.getClass().getDeclaredField(propName)
                 if (field) {
-                    @ASTTest(phase=INSTRUCTION_SELECTION,value={
+                    @ASTTest(phase=INSTRUCTION_SELECTION, value={
                         assert node.getNodeMetaData(INFERRED_TYPE).name == 
'Ann1'
                     })
                     def annotation = field.getAnnotation Ann1
@@ -1218,4 +1218,24 @@ class TypeInferenceSTCTest extends 
StaticTypeCheckingTestCase {
             test( [id:'x'] )
         '''
     }
+
+    // GROOVY-10328
+    void testInferredTypeForMapOrList() {
+        assertScript '''
+            @ASTTest(phase=INSTRUCTION_SELECTION, value={
+                for (decl in node.code.statements*.expression) {
+                    assert decl.getNodeMetaData(INFERRED_TYPE) == OBJECT_TYPE
+                }
+            })
+            void test(List<? super String> list, Map<String, ? super String> 
map) {
+                def a = list.first()
+                def b = list.get(0)
+                def c = list[0]
+
+                def x = map.get('foo')
+                def y = map['foo']
+                def z = map.foo
+            }
+        '''
+    }
 }

Reply via email to