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 2022/05/16 19:32:23 UTC

[groovy] branch GROOVY_3_0_X updated (44801fbde2 -> 7f3c77d73c)

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

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


    from 44801fbde2 GROOVY-10363: STC: fix target type check for type parameter
     new e6016c634d GROOVY-7419, GROOVY-9948, GROOVY-9956: STC: infer <> from argument types
     new ec404abebb GROOVY-9963: resolve ctor call diamond for attribute/property expression
     new 7f3c77d73c GROOVY-10343: STC: resolve type parameter bounded by a type parameter

The 3 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.


Summary of changes:
 .../transform/stc/StaticTypeCheckingSupport.java   | 28 ++++++-----
 .../transform/stc/StaticTypeCheckingVisitor.java   | 35 +++++++++----
 .../groovy/transform/stc/GenericsSTCTest.groovy    | 57 ++++++++++------------
 3 files changed, 68 insertions(+), 52 deletions(-)


[groovy] 03/03: GROOVY-10343: STC: resolve type parameter bounded by a type parameter

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

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

commit 7f3c77d73cdd90d1cffa12e2281b3e5de7853efa
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon May 16 11:58:56 2022 -0500

    GROOVY-10343: STC: resolve type parameter bounded by a type parameter
---
 .../transform/stc/StaticTypeCheckingSupport.java   | 28 ++++++++++++----------
 .../groovy/transform/stc/GenericsSTCTest.groovy    | 17 +++++++++++++
 2 files changed, 32 insertions(+), 13 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 ebbf3945c2..2fdbb432b0 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -1606,22 +1606,24 @@ public abstract class StaticTypeCheckingSupport {
         }
     }
 
-    private static ClassNode extractType(final GenericsType gt) {
+    private static ClassNode extractType(GenericsType gt) {
+        ClassNode cn;
         if (!gt.isPlaceholder()) {
-            return gt.getType();
-        }
-        // For a placeholder, a type based on the generics type is used for the compatibility check, to match on
-        // the actual bounds and not the name of the placeholder.
-        ClassNode replacementType = gt.getType().redirect();
-        if (gt.getType().getGenericsTypes() != null) {
-            GenericsType realGt = gt.getType().getGenericsTypes()[0];
-            if (realGt.getLowerBound() != null) {
-                replacementType = realGt.getLowerBound();
-            } else if (realGt.getUpperBounds() != null && realGt.getUpperBounds().length > 0) {
-                replacementType = realGt.getUpperBounds()[0];
+            cn = gt.getType();
+        } else {
+            // discard the placeholder
+            cn = gt.getType().redirect();
+
+            if (gt.getType().getGenericsTypes() != null)
+                gt = gt.getType().getGenericsTypes()[0];
+
+            if (gt.getLowerBound() != null) {
+                cn = gt.getLowerBound();
+            } else if (asBoolean(gt.getUpperBounds())) {
+                cn = gt.getUpperBounds()[0];
             }
         }
-        return replacementType;
+        return cn;
     }
 
     private static boolean equalIncludingGenerics(final GenericsType orig, final GenericsType copy) {
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index 2622f7303a..ef74410951 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -1219,6 +1219,23 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-10343
+    void testDiamondInferrenceFromConstructor27() {
+        assertScript '''
+            class C<T1, T2 extends T1> {
+                T1 p
+                C(T1 p) { this.p = p }
+                T2 m() { return null }
+            }
+            void test(Integer x) {
+                def c = new C<>(x) // type witness for T1 can also help bound T2
+                def y = c.m()
+                Integer z = y // Cannot assign value of type Object to variable of type Integer
+            }
+            test(1234)
+        '''
+    }
+
     // GROOVY-10280
     void testTypeArgumentPropagation() {
         assertScript '''


[groovy] 02/03: GROOVY-9963: resolve ctor call diamond for attribute/property expression

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

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

commit ec404abebb928a30cd27de69482ccb6bbe020832
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon May 16 14:13:34 2022 -0500

    GROOVY-9963: resolve ctor call diamond for attribute/property expression
---
 .../org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java   | 3 +++
 src/test/groovy/transform/stc/GenericsSTCTest.groovy                   | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

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 35f6cd29d4..ca216361da 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -1472,6 +1472,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
         Expression objectExpression = pexp.getObjectExpression();
         ClassNode objectExpressionType = getType(objectExpression);
+        if (objectExpression instanceof ConstructorCallExpression) {
+            inferDiamondType((ConstructorCallExpression) objectExpression, objectExpressionType);
+        }
         List<ClassNode> enclosingTypes = typeCheckingContext.getEnclosingClassNodes();
 
         boolean staticOnlyAccess = isClassClassNodeWrappingConcreteType(objectExpressionType);
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index 461bcd0cae..2622f7303a 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -888,7 +888,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         'Incompatible generic argument types. Cannot assign C<? extends java.lang.Object> to: C<D>'
     }
 
-    @NotYetImplemented // GROOVY-9963
+    // GROOVY-9963
     void testDiamondInferrenceFromConstructor10() {
         assertScript '''
             @groovy.transform.TupleConstructor(defaults=false)


[groovy] 01/03: GROOVY-7419, GROOVY-9948, GROOVY-9956: STC: infer <> from argument types

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

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

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

    GROOVY-7419, GROOVY-9948, GROOVY-9956: STC: infer <> from argument types
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 32 +++++++++++++-----
 .../groovy/transform/stc/GenericsSTCTest.groovy    | 38 +++++-----------------
 2 files changed, 32 insertions(+), 38 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 3631754ce6..35f6cd29d4 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -1051,19 +1051,33 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     protected void inferDiamondType(final ConstructorCallExpression cce, final ClassNode lType) {
-        ClassNode cceType = cce.getType();
+        ClassNode cceType = cce.getType(), inferredType = lType;
         // check if constructor call expression makes use of the diamond operator
         if (cceType.getGenericsTypes() != null && cceType.getGenericsTypes().length == 0) {
-            ArgumentListExpression argumentListExpression = InvocationWriter.makeArgumentList(cce.getArguments());
-            if (argumentListExpression.getExpressions().isEmpty()) {
-                adjustGenerics(lType, cceType);
-            } else {
-                ClassNode type = getType(argumentListExpression.getExpression(0));
-                if (type.isUsingGenerics()) {
-                    adjustGenerics(type, cceType);
+            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 (lType.getGenericsTypes() != null // GROOVY-10367: nothing to inspect
+                        // GROOVY-6232, GROOVY-9956: if cce not assignment compatible, process target as additional type witness
+                        && 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(rhs[i].getType()))) {
+                        type = pType; // lType proved to be a viable type witness
+                    }
                 }
+                inferredType = type;
             }
-            // store inferred type on CCE
+
+            adjustGenerics(inferredType, cceType);
             storeType(cce, cceType);
         }
     }
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index 2582791dfa..461bcd0cae 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -494,7 +494,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
     // GROOVY-8638
     void testReturnTypeInferenceWithMethodGenerics18() {
         assertScript '''
-            @Grab('com.google.guava:guava:30.1.1-jre')
+            @Grab('com.google.guava:guava:31.1-jre')
             import com.google.common.collect.*
 
             ListMultimap<String, Integer> mmap = ArrayListMultimap.create()
@@ -633,21 +633,13 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
             new HashSet<>(Arrays.asList(0L))
         '''
 
-        // not diamond inference, but tests compatible assignment
         assertScript '''
-            Set<Number> set = new HashSet<Number>(Arrays.asList(0L))
-        '''
-
-        shouldFailWithMessages '''
             Set<Number> set = new HashSet<>(Arrays.asList(0L))
-        ''',
-        'Cannot assign java.util.HashSet <java.lang.Long> to: java.util.Set <Number>'
-    }
+        '''
 
-    @NotYetImplemented
-    void testDiamondInferrenceFromConstructor3a() {
+        // not diamond inference, but tests compatible assignment
         assertScript '''
-            Set<Number> set = new HashSet<>(Arrays.asList(0L))
+            Set<Number> set = new HashSet<Number>(Arrays.asList(0L))
         '''
 
         assertScript '''
@@ -659,7 +651,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
-    @NotYetImplemented // GROOVY-7419
+    // GROOVY-7419
     void testDiamondInferrenceFromConstructor4() {
         assertScript '''
             Map<Thread.State, Object> map = new EnumMap<>(Thread.State)
@@ -773,7 +765,6 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
-    @NotYetImplemented
     void testDiamondInferrenceFromConstructor9() {
         assertScript '''
             abstract class A<X> { }
@@ -798,12 +789,12 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
 
             A<String> ax = new C<>(new D())
         ''',
-        'Incompatible generic argument types. Cannot assign C<D> to: A<java.lang.String>'
+        '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<java.lang.Number>> to: java.util.Set<java.util.List<java.lang.String>>'
+        'Incompatible generic argument types. Cannot assign java.util.HashSet <java.util.ArrayList> to: java.util.Set <List>'
     }
 
     // GROOVY-9972
@@ -832,7 +823,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
             C<D> cd = b ? new C<>(new D()) : (b ? new C<>((D) null) : new C<>(new D()))
             assert cd.p.f.toLowerCase() == 'd#f'
         '''
-/*
+
         assertScript '''
             @groovy.transform.TupleConstructor(defaults=false)
             class C<T> {
@@ -849,7 +840,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
             }
             assert cd.p.f.toLowerCase() == 'd#f'
         '''
-*/
+
         assertScript '''
             @groovy.transform.TupleConstructor
             class C {
@@ -3182,17 +3173,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 '''