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

emilles 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 deeb858cc8 GROOVY-10633, GROOVY-10662: STC: do not mix generics 
contexts
deeb858cc8 is described below

commit deeb858cc89fe8fee68bff00ef12eeb152720360
Author: Eric Milles <eric.mil...@thomsonreuters.com>
AuthorDate: Tue Jun 21 09:39:09 2022 -0500

    GROOVY-10633, GROOVY-10662: STC: do not mix generics contexts
---
 .../transform/stc/StaticTypeCheckingSupport.java   | 70 +++++++++-------------
 .../groovy/transform/stc/GenericsSTCTest.groovy    | 40 +++++++++++++
 2 files changed, 68 insertions(+), 42 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 dd687fa3a3..f68572e192 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -1603,53 +1603,39 @@ public abstract class StaticTypeCheckingSupport {
 
     static void applyGenericsConnections(final Map<GenericsTypeName, 
GenericsType> connections, final Map<GenericsTypeName, GenericsType> 
resolvedPlaceholders) {
         if (connections == null || connections.isEmpty()) return;
-        int count = 0;
-        while (count++ < 10000) {
-            boolean checkForMorePlaceholders = false;
-            for (Map.Entry<GenericsTypeName, GenericsType> entry : 
resolvedPlaceholders.entrySet()) {
-                // entry could be T=T, T=T extends U, T=V, T=String, T=? 
extends String, etc.
-                GenericsType oldValue = entry.getValue();
-                if (oldValue.isPlaceholder()) { // T=T or V, not T=String or ? 
...
-                    GenericsTypeName name = new 
GenericsTypeName(oldValue.getName());
-                    GenericsType newValue = connections.get(name); // find "V" 
in T=V
-                    if (newValue == oldValue) continue;
-                    if (newValue == null) {
-                        newValue = connections.get(entry.getKey());
-                        if (newValue != null) { // GROOVY-10315, GROOVY-10317
-                            newValue = getCombinedGenericsType(oldValue, 
newValue);
-                        }
+        for (Map.Entry<GenericsTypeName, GenericsType> entry : 
resolvedPlaceholders.entrySet()) {
+            // entry could be T=T, T=T extends U, T=V, T=String, T=? extends 
String, etc.
+            GenericsType oldValue = entry.getValue();
+            if (oldValue.isPlaceholder()) { // T=T or V, not T=String or ? ...
+                GenericsTypeName name = new 
GenericsTypeName(oldValue.getName());
+                GenericsType newValue = connections.get(name); // find "V" in 
T=V
+                if (newValue == oldValue) continue;
+                if (newValue == null) {
+                    newValue = connections.get(entry.getKey());
+                    if (newValue != null) { // GROOVY-10315, GROOVY-10317
+                        newValue = getCombinedGenericsType(oldValue, newValue);
                     }
-                    if (newValue == null) {
-                        entry.setValue(newValue = 
applyGenericsContext(connections, oldValue));
-                        if (!checkForMorePlaceholders) {
-                            checkForMorePlaceholders = 
!equalIncludingGenerics(oldValue, newValue);
-                        }
-                    } else if (!newValue.isPlaceholder() || newValue != 
resolvedPlaceholders.get(name)) {
-                        // GROOVY-6787: Don't override the original if the 
replacement doesn't respect the bounds otherwise
-                        // the original bounds are lost, which can result in 
accepting an incompatible type as an argument!
-                        ClassNode replacementType = extractType(newValue);
-                        ClassNode suitabilityType = 
!replacementType.isGenericsPlaceHolder()
-                                ? replacementType : 
Optional.ofNullable(replacementType.getGenericsTypes())
-                                        .map(gts -> 
extractType(gts[0])).orElse(replacementType.redirect());
-
-                        if (oldValue.isCompatibleWith(suitabilityType)) {
-                            if (newValue.isWildcard() && 
newValue.getLowerBound() == null && newValue.getUpperBounds() == null) {
-                                // GROOVY-9998: apply upper/lower bound for 
unknown
-                                
entry.setValue(replacementType.asGenericsType());
-                            } else {
-                                entry.setValue(newValue);
-                            }
-                            if (!checkForMorePlaceholders && 
newValue.isPlaceholder()) {
-                                checkForMorePlaceholders = 
!equalIncludingGenerics(oldValue, newValue);
-                            }
+                }
+                if (newValue == null) {
+                    entry.setValue(newValue = 
applyGenericsContext(connections, oldValue));
+                } else if (!newValue.isPlaceholder() || newValue != 
resolvedPlaceholders.get(name)) {
+                    // GROOVY-6787: Don't override the original if the 
replacement doesn't respect the bounds otherwise
+                    // the original bounds are lost, which can result in 
accepting an incompatible type as an argument!
+                    ClassNode replacementType = extractType(newValue);
+                    ClassNode suitabilityType = 
!replacementType.isGenericsPlaceHolder()
+                            ? replacementType : 
Optional.ofNullable(replacementType.getGenericsTypes())
+                                    .map(gts -> 
extractType(gts[0])).orElse(replacementType.redirect());
+
+                    if (oldValue.isCompatibleWith(suitabilityType)) {
+                        if (newValue.isWildcard() && newValue.getLowerBound() 
== null && newValue.getUpperBounds() == null) {
+                            // GROOVY-9998: apply upper/lower bound for unknown
+                            entry.setValue(replacementType.asGenericsType());
+                        } else {
+                            entry.setValue(newValue);
                         }
                     }
                 }
             }
-            if (!checkForMorePlaceholders) break;
-        }
-        if (count >= 10000) {
-            throw new GroovyBugError("unable to handle generics in " + 
resolvedPlaceholders + " with connections " + connections);
         }
     }
 
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy 
b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index eeda172da0..e61f98320e 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -1382,6 +1382,46 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase 
{
         '''
     }
 
+    // GROOVY-10662
+    void testDiamondInferrenceFromConstructor31() {
+        assertScript '''
+            class A<X, T> {
+                A(T t, X x) {}
+                void m(X x) {}
+            }
+            class B<T extends Number> {
+                void test() {
+                    T t = (T) null
+                    Character c = 'c'
+                    def a = new A<>(c, t)
+                    a.m((T) null) // Cannot find matching method A#m(T)
+                }
+            }
+            new B<Integer>().test()
+        '''
+    }
+
+    // GROOVY-10633
+    void testDiamondInferrenceFromConstructor32() {
+        assertScript '''
+            class A<T, Y> {
+                public B<Y> f
+                A(B<Y> b_of_y, T t) {
+                    this.f = b_of_y
+                }
+            }
+            class B<T> {
+                void m(T t) {
+                }
+            }
+            <T extends Number> void test() {
+                def x = new B<T>()
+                new A<>(x, '').f.m((T) null)
+            }
+            test()
+        '''
+    }
+
     // GROOVY-10280
     void testTypeArgumentPropagation() {
         assertScript '''

Reply via email to