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/27 21:30:02 UTC

[groovy] branch GROOVY-9956 created (now 55da4fb)

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

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


      at 55da4fb  GROOVY-6232, GROOVY-9956: check LHS type witness for diamond constructor

This branch includes the following new commits:

     new 55da4fb  GROOVY-6232, GROOVY-9956: check LHS type witness for diamond constructor

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-6232, GROOVY-9956: check LHS type witness for diamond constructor

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

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

commit 55da4fb3594c5830b421e07a19877a957d105760
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Feb 27 15:29:44 2021 -0600

    GROOVY-6232, GROOVY-9956: check LHS type witness for diamond constructor
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 15 ++++++
 .../groovy/transform/stc/GenericsSTCTest.groovy    | 57 +++++++++++-----------
 2 files changed, 43 insertions(+), 29 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 0a77404..1ef88a0 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -1028,6 +1028,20 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 ClassNode type = GenericsUtils.parameterizeType(cceType, cceType);
                 type = inferReturnTypeGenerics(type, constructor, argumentList);
                 if (type.isUsingGenerics()) {
+                    // GROOVY-6232, GROOVY-9956: if cce not assignment compatible, process target as additional type witness
+                    if (checkCompatibleAssignmentTypes(lType, type, cce) && !GenericsUtils.buildWildcardType(lType).isCompatibleWith(type)) {
+                        // allow covariance of each type parameter, but maintain semantics for nested generics
+
+                        ClassNode pType = GenericsUtils.parameterizeType(lType, type);
+                        GenericsType[] lhs = pType.getGenericsTypes(), rhs = type.getGenericsTypes();
+                        if (lhs == null || rhs == null || lhs.length != rhs.length) throw new GroovyBugError(
+                                "Parameterization failed: " + prettyPrintType(pType) + " ~ " + prettyPrintType(type));
+
+                        if (java.util.stream.IntStream.range(0, lhs.length).allMatch(i ->
+                                GenericsUtils.buildWildcardType(getCombinedBoundType(lhs[i])).isCompatibleWith(getCombinedBoundType(rhs[i])))) {
+                            type = pType; // lType proved to be a viable type witness
+                        }
+                    }
                     inferredType = type;
                 }
             }
@@ -3100,6 +3114,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
      * @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 = OBJECT_TYPE;
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index 12b5e70..4c28a82 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -223,9 +223,9 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
     }
 
     void testDiamondInferrenceFromConstructor3() {
-        shouldFailWithMessages '''
+        assertScript '''
             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 '''
@@ -241,16 +241,13 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
 
     // GROOVY-6232
     void testDiamondInferrenceFromConstructor5() {
-        [/*'"a",new Object()',*/ 'new Object(),"b"', /*'"a","b"'*/].each { args ->
+        ['"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()
+                C<Object> c = new C<>($args)
             """
         }
     }
@@ -265,11 +262,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
                 }
             }
 
-            void test() {
-                C<Integer> c = new C<>(1)
-                assert c.p < 10
-            }
-            test()
+            C<Integer> c = new C<>(1)
+            assert c.p < 10
         '''
     }
 
@@ -281,15 +275,12 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
                 T p
             }
 
-            void test() {
-                C<Integer> c = new C<>(1)
-                assert c.p < 10
-            }
-            test()
+            C<Integer> c = new C<>(1)
+            assert c.p < 10
         '''
     }
 
-    @NotYetImplemented // GROOVY-9956
+    // GROOVY-9956
     void testDiamondInferrenceFromConstructor8() {
         assertScript '''
             @groovy.transform.TupleConstructor
@@ -299,16 +290,11 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
             interface I { }
             class D implements I { }
 
-            void test() {
-                C<I> ci;
-                ci = new C<I>(new D())
-                ci = new C<>(new D()) // infers C<D> on RHS
-            }
-            test()
+            C<I> ci = new C<I>(new D())
+            ci = new C<>(new D()) // infers C<D> on RHS
         '''
     }
 
-    @NotYetImplemented
     void testDiamondInferrenceFromConstructor9() {
         assertScript '''
             abstract class A<X> { }
@@ -319,11 +305,24 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
             interface I { }
             class D implements I { }
 
-            void test() {
-                A<I> ai = new C<>(new D())
-            }
-            test()
+            A<I> ai = new C<>(new D())
         '''
+
+        shouldFailWithMessages '''
+            abstract class A<X> { }
+            @groovy.transform.TupleConstructor
+            class C<T> extends A<T> {
+                T p
+            }
+            interface I { }
+            class D implements I { }
+
+            A<String> ax = new C<>(new D())
+        ''', 'Incompatible generic argument types. Cannot assign C <D> to: A <String>'
+
+        shouldFailWithMessages '''
+            Set<List<String>> strings = new HashSet<>([new ArrayList<Number>()])
+        ''', 'Incompatible generic argument types. Cannot assign java.util.HashSet <java.util.ArrayList> to: java.util.Set <List>'
     }
 
     void testLinkedListWithListArgument() {