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/11/19 16:11:53 UTC

[groovy] branch GROOVY_2_5_X updated: GROOVY-10847: STC: `T t = new C<>()` where `T` extends a type parameter

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

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


The following commit(s) were added to refs/heads/GROOVY_2_5_X by this push:
     new 81d253f188 GROOVY-10847: STC: `T t = new C<>()` where `T` extends a type parameter
81d253f188 is described below

commit 81d253f1888cfc7e978a6382084df64a696ba591
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Nov 19 08:19:39 2022 -0600

    GROOVY-10847: STC: `T t = new C<>()` where `T` extends a type parameter
---
 .../transform/stc/StaticTypeCheckingVisitor.java   |   5 +-
 .../groovy/transform/stc/GenericsSTCTest.groovy    | 158 +++++++++++++++++++--
 2 files changed, 149 insertions(+), 14 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 86e663d400..dabb39c3a8 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -1130,9 +1130,10 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 }
                 inferredType = type;
             }
-            if (inferredType.isGenericsPlaceHolder()) // GROOVY-10344: "T t = new C<>()"
+            // GROOVY-10344, GROOVY-10847: "T t = new C<>()" where "T" may extend another type parameter
+            while (inferredType.isGenericsPlaceHolder() && asBoolean(inferredType.getGenericsTypes())) {
                 inferredType = getCombinedBoundType(inferredType.getGenericsTypes()[0]);
-
+            }
             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 7b003e8754..6aebed4dda 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -353,7 +353,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         'Cannot assign java.util.Map <String, java.util.Collection> to: java.util.Map <String, Set>'
     }
 
-    @NotYetImplemented // GROOVY-10120
+    // GROOVY-10120
+    @NotYetImplemented
     void testReturnTypeInferenceWithMethodGenerics18b() {
         if (!GroovyAssert.isAtLeastJdk('1.8')) return
         shouldFailWithMessages '''
@@ -366,7 +367,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         'Cannot assign java.util.Map <String, java.util.Collection> to: java.util.Map <String, Set>'
     }
 
-    @NotYetImplemented // GROOVY-10339
+    // GROOVY-10339
+    @NotYetImplemented
     void testReturnTypeInferenceWithMethodGenerics21() {
         for (type in ['Character', 'Integer']) {
             shouldFailWithMessages """
@@ -513,7 +515,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
-    @NotYetImplemented // GROOVY-9984
+    // GROOVY-9984
+    @NotYetImplemented
     void testDiamondInferrenceFromConstructor7a() {
         assertScript '''
             @groovy.transform.TupleConstructor(defaults=false)
@@ -714,7 +717,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
-    @NotYetImplemented // GROOVY-10080
+    // GROOVY-10080
+    @NotYetImplemented
     void testDiamondInferrenceFromConstructor11() {
         assertScript '''
             @groovy.transform.TupleConstructor(defaults=false)
@@ -898,7 +902,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
-    @NotYetImplemented // GROOVY-10228
+    // GROOVY-10228
+    @NotYetImplemented
     void testDiamondInferrenceFromConstructor18() {
         assertScript '''
             @groovy.transform.TupleConstructor(defaults=false)
@@ -1030,7 +1035,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
-    @NotYetImplemented // GROOVY-10343
+    // GROOVY-10343
+    @NotYetImplemented
     void testDiamondInferrenceFromConstructor27() {
         assertScript '''
             class C<T1, T2 extends T1> {
@@ -1114,7 +1120,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
-    @NotYetImplemented // GROOVY-10633
+    // GROOVY-10633
+    @NotYetImplemented
     void testDiamondInferrenceFromConstructor32() {
         assertScript '''
             class A<T, Y> {
@@ -1135,6 +1142,128 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-10699
+    @NotYetImplemented
+    void testDiamondInferrenceFromConstructor33() {
+        assertScript '''
+            class A<T> {
+                A(B<T> b_of_t) {
+                }
+            }
+            class B<T> {
+                B(T t) {
+                }
+            }
+
+            @ASTTest(phase=INSTRUCTION_SELECTION, value={
+                def type = node.getNodeMetaData(INFERRED_TYPE)
+                assert type.toString(false) == 'A<java.lang.String>'
+            })
+            def x = new A<>(new B<>('str'))
+        '''
+
+        assertScript '''import java.util.function.Consumer
+            class C<T> {
+                C(Consumer<T> consumer_of_t) {
+                    consumer_of_t.accept(null)
+                }
+            }
+
+            @ASTTest(phase=INSTRUCTION_SELECTION, value={
+                def type = node.getNodeMetaData(INFERRED_TYPE)
+                assert type.toString(false) == 'C<java.lang.String>'
+            })
+            def y = new C<>((String s) -> { print(s); }) // error: Expected type Object for lambda parameter: s
+        '''
+
+        assertScript '''import java.util.function.Supplier
+            class D<T> {
+                D(Supplier<T> supplier_of_t) {
+                    T t = supplier_of_t.get()
+                }
+            }
+
+            @ASTTest(phase=INSTRUCTION_SELECTION, value={
+                def type = node.getNodeMetaData(INFERRED_TYPE)
+                assert type.toString(false) == 'D<java.lang.String>'
+            })
+            def z = new D<>(() -> 'str')
+        '''
+    }
+
+    // GROOVY-10698
+    @NotYetImplemented
+    void testDiamondInferrenceFromConstructor34() {
+        assertScript '''
+            class A<T> {
+                A(T t, B<T> b_of_t) {
+                }
+            }
+            class B<U> {
+            }
+
+            @ASTTest(phase=INSTRUCTION_SELECTION, value={
+                def type = node.getNodeMetaData(INFERRED_TYPE)
+                assert type.toString(false) == 'A<java.lang.String>'
+            })
+            def x = new A<>('witness', new B<>()) // Cannot call A#<init>(Object,B<Object>) with arguments [String, B<T>]
+        '''
+    }
+
+    // GROOVY-10847
+    void testDiamondInferrenceFromConstructor35() {
+        assertScript '''
+            class A<T, U> {
+            }
+            class B {
+              def <X extends A<Character, Boolean>, Y extends X> Object m(X x, Y y) {
+              }
+            }
+
+            @ASTTest(phase=INSTRUCTION_SELECTION, value={
+                def type = node.rightExpression.arguments[1].getNodeMetaData(INFERRED_TYPE)
+                assert type.toString(false) == 'A <java.lang.Character, java.lang.Boolean>'
+            })
+            def c = new B().m(null, new A<>())
+        '''
+    }
+
+    // GROOVY-10674
+    @NotYetImplemented
+    void testDiamondInferrenceFromConstructor36() {
+        assertScript '''
+            class Foo<BB extends Bar<Byte>, X extends BB> {
+                X x
+                Foo(X x) {
+                    this.x = x
+                }
+            }
+            class Bar<T extends Number> {
+            }
+
+            class Baz {
+                static Foo<Bar<Byte>, ? super Bar<Byte>> foo = new Foo<>(new Bar<>())
+            }
+            new Baz()
+        '''
+
+        assertScript '''
+            class Foo<BBQ extends Bar<Byte, ? extends Byte>, X extends BBQ> {
+                X x
+                Foo(X x) {
+                    this.x = x
+                }
+            }
+            class Bar<T extends Number, S extends T> {
+            }
+
+            class Baz {
+                Foo<Bar<Byte,Byte>, ? super Bar<Byte,Byte>> foo = new Foo<>(new Bar<>())
+            }
+            new Baz()
+        '''
+    }
+
     // GROOVY-10280
     void testTypeArgumentPropagation() {
         assertScript '''
@@ -1979,7 +2108,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
-    @NotYetImplemented // GROOVY-10648
+    // GROOVY-10648
+    @NotYetImplemented
     void testShouldUseMethodGenericType16() {
         assertScript '''
             def <T extends Number> Set<T> test(Iterable<T> iterable) {
@@ -2594,7 +2724,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
-    @NotYetImplemented // GROOVY-10153
+    // GROOVY-10153
+    @NotYetImplemented
     void testCompatibleArgumentsForPlaceholders11() {
         ['A', 'B', 'C'].each { T ->
             assertScript """
@@ -3063,7 +3194,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
-    @NotYetImplemented // GROOVY-10322
+    // GROOVY-10322
+    @NotYetImplemented
     void testShouldFindMethodEvenWithRepeatNames4() {
         assertScript '''
             class C<T> {
@@ -3107,7 +3239,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
-    @NotYetImplemented // GROOVY-5893
+    // GROOVY-5893
+    @NotYetImplemented
     void testPlusInClosure() {
         assertScript '''
         def list = [1, 2, 3]
@@ -4201,7 +4334,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
-    @NotYetImplemented // GROOVY-10556
+    // GROOVY-10556
+    @NotYetImplemented
     void testSelfReferentialTypeParameter3() {
         ['(B) this', 'this as B'].each { self ->
             assertScript """