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 2021/02/17 21:05:31 UTC

[groovy] branch GROOVY-9948 created (now 338856d)

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

emilles pushed a change to branch GROOVY-9948
in repository https://gitbox.apache.org/repos/asf/groovy.git.


      at 338856d  GROOVY-9948: infer type arguments for CCE diamond using argument type(s)

This branch includes the following new commits:

     new 338856d  GROOVY-9948: infer type arguments for CCE diamond using argument type(s)

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[groovy] 01/01: GROOVY-9948: infer type arguments for CCE diamond using argument type(s)

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 338856dcce3665bd29c1064e60747ede9dafa3d3
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 3e27826..1c253f2 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()
         '''
     }
 
@@ -1760,17 +1815,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 '''