You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2021/02/19 18:26:32 UTC

[groovy] branch master updated: GROOVY-9948: infer type arguments for CCE diamond using argument type(s)

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

sunlan 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 566c832  GROOVY-9948: infer type arguments for CCE diamond using argument type(s)
566c832 is described below

commit 566c832c02c036a46e356ce0edb19f852b540c97
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed Feb 17 15:05:15 2021 -0600

    GROOVY-9948: infer type arguments for CCE diamond using argument type(s)
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 22 +++---
 .../groovy/transform/stc/GenericsSTCTest.groovy    | 82 +++++++++++++++++-----
 2 files changed, 74 insertions(+), 30 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 fc30121..f3eb159 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -1019,20 +1019,20 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     protected void inferDiamondType(final ConstructorCallExpression cce, final ClassNode lType) {
+        ClassNode cceType = cce.getType(), inferredType = lType;
         // check if constructor call expression makes use of the diamond operator
-        ClassNode node = cce.getType();
-        if (node.isUsingGenerics() && node.getGenericsTypes() != null && node.getGenericsTypes().length == 0) {
-            ArgumentListExpression argumentListExpression = InvocationWriter.makeArgumentList(cce.getArguments());
-            if (argumentListExpression.getExpressions().isEmpty()) {
-                adjustGenerics(lType, node);
-            } else {
-                ClassNode type = getType(argumentListExpression.getExpression(0));
+        if (cceType.getGenericsTypes() != null && cceType.getGenericsTypes().length == 0) {
+            ArgumentListExpression argumentList = InvocationWriter.makeArgumentList(cce.getArguments());
+            ConstructorNode constructor = cce.getNodeMetaData(DIRECT_METHOD_CALL_TARGET);
+            if (!argumentList.getExpressions().isEmpty() && constructor != null) {
+                ClassNode type = GenericsUtils.parameterizeType(cceType, cceType);
+                type = inferReturnTypeGenerics(type, constructor, argumentList);
                 if (type.isUsingGenerics()) {
-                    adjustGenerics(type, node);
+                    inferredType = type;
                 }
             }
-            // store inferred type on CCE
-            storeType(cce, node);
+            adjustGenerics(inferredType, cceType);
+            storeType(cce, cceType);
         }
     }
 
@@ -5096,7 +5096,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
      * @return parameterized, infered, class node
      */
     protected ClassNode inferReturnTypeGenerics(final ClassNode receiver, final MethodNode method, final Expression arguments, final GenericsType[] explicitTypeHints) {
-        ClassNode returnType = method.getReturnType();
+        ClassNode returnType = method instanceof ConstructorNode ? method.getDeclaringClass() : method.getReturnType();
         if (getGenericsWithoutArray(returnType) == null) {
             return returnType;
         }
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index 2bab61d..b57f77f 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -210,27 +210,82 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
-    void testDiamondInferrenceFromConstructor() {
+    void testDiamondInferrenceFromConstructor1() {
         assertScript '''
-            Set< Long > s2 = new HashSet<>()
+            Set<Long> set = new HashSet<>()
         '''
     }
 
-    void testDiamondInferrenceFromConstructorWithoutAssignment() {
+    void testDiamondInferrenceFromConstructor2() {
         assertScript '''
-            new HashSet<>(Arrays.asList(0L,0L));
+            new HashSet<>(Arrays.asList(0L))
         '''
     }
 
-    void testDiamondInferrenceFromConstructor2() {
+    void testDiamondInferrenceFromConstructor3() {
         shouldFailWithMessages '''
-            Set< Number > s3 = new HashSet<>(Arrays.asList(0L,0L));
+            Set<Number> set = new HashSet<>(Arrays.asList(0L))
         ''', 'Cannot assign java.util.HashSet <java.lang.Long> to: java.util.Set <Number>'
+
+        // not diamond inference, but tests compatible assignment
+        assertScript '''
+            Set<Number> set = new HashSet<Number>(Arrays.asList(0L))
+        '''
     }
 
-    void testDiamondInferrenceFromConstructor3() {
+    void testDiamondInferrenceFromConstructor4() {
+        assertScript '''
+            Set<? extends Number> set = new HashSet<>(Arrays.asList(0L))
+        '''
+    }
+
+    // GROOVY-6232
+    void testDiamondInferrenceFromConstructor5() {
+        [/*'"a",new Object()',*/ 'new Object(),"b"', /*'"a","b"'*/].each { args ->
+            assertScript """
+                class C<T> {
+                    C(T x, T y) {
+                    }
+                }
+                void test() {
+                    C<Object> c = new C<>($args)
+                }
+                test()
+            """
+        }
+    }
+
+    // GROOVY-9948
+    void testDiamondInferrenceFromConstructor6() {
+        assertScript '''
+            class C<T> {
+                T p
+                C(T p) {
+                    this.p = p
+                }
+            }
+
+            void test() {
+                C<Integer> c = new C<>(1)
+                assert c.p < 10
+            }
+            test()
+        '''
+    }
+
+    // GROOVY-9948
+    void testDiamondInferrenceFromConstructor7() {
         assertScript '''
-            Set<Number> s4 = new HashSet<Number>(Arrays.asList(0L,0L))
+            @groovy.transform.TupleConstructor
+            class C<T> {
+                T p
+            }
+
+            void test() {
+                C<Integer> c = new C<>(1)
+                assert c.p < 10
+            }
+            test()
         '''
     }
 
@@ -1777,17 +1832,6 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
-    // GROOVY-6232
-    void testDiamond() {
-        assertScript '''
-            class Foo<T>{  Foo(T a, T b){} }
-            def bar() {
-                Foo<Object> f = new Foo<>("a",new Object())
-            }
-            bar()
-        '''
-    }
-
     // GROOVY-6233
     void testConstructorArgumentsAgainstGenerics() {
         shouldFailWithMessages '''