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/09/14 19:58:15 UTC

[groovy] branch GROOVY_2_5_X updated: GROOVY-10120: STC: synthetic variant (bridge method) lacks generics info

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 a26ab04f9b GROOVY-10120: STC: synthetic variant (bridge method) lacks generics info
a26ab04f9b is described below

commit a26ab04f9b005f0f4a8b6f32ea374cde79feb4d2
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Aug 12 12:27:30 2022 -0500

    GROOVY-10120: STC: synthetic variant (bridge method) lacks generics info
    
    2_5_X backport
---
 .../transform/stc/StaticTypeCheckingSupport.java   | 20 ++++++++++-------
 .../groovy/transform/stc/GenericsSTCTest.groovy    | 25 ++++++++++++++++++++++
 2 files changed, 37 insertions(+), 8 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 0d8ebbdf86..7b9efe147b 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -1248,21 +1248,20 @@ public abstract class StaticTypeCheckingSupport {
                             // equivalent, for example String#compareTo(Object) and
                             // String#compareTo(String) -- in that case, the Object
                             // version is marked as synthetic
-                            if (one.isSynthetic() && !two.isSynthetic()) {
+                            if (isSynthetic(one, two)) {
                                 toBeRemoved.add(one);
-                            } else if (two.isSynthetic() && !one.isSynthetic()) {
+                            } else if (isSynthetic(two, one)) {
                                 toBeRemoved.add(two);
                             }
                         }
                     } else if (!oneDC.equals(twoDC)) {
                         if (ParameterUtils.parametersEqual(one.getParameters(), two.getParameters())) {
                             // GROOVY-6882, GROOVY-6970: drop overridden or interface equivalent method
-                            if (twoDC.isInterface() ? oneDC.implementsInterface(twoDC)
-                                    : oneDC.isDerivedFrom(twoDC)) {
-                                toBeRemoved.add(two);
-                            } else if (oneDC.isInterface() ? twoDC.isInterface()
-                                    : twoDC.isDerivedFrom(oneDC)) {
-                                toBeRemoved.add(one);
+                            // GROOVY-8638, GROOVY-10120: unless bridge method (synthetic variant) overrides
+                            if (twoDC.isInterface() ? oneDC.implementsInterface(twoDC) : oneDC.isDerivedFrom(twoDC)) {
+                                toBeRemoved.add(isSynthetic(one, two) ? one : two);
+                            } else if (oneDC.isInterface() ? twoDC.isInterface() : twoDC.isDerivedFrom(oneDC)) {
+                                toBeRemoved.add(isSynthetic(two, one) ? two : one);
                             }
                         }
                     }
@@ -1283,6 +1282,11 @@ public abstract class StaticTypeCheckingSupport {
         return (one.isDerivedFrom(two) || one.implementsInterface(two));
     }
 
+    private static boolean isSynthetic(final MethodNode one, final MethodNode two) {
+        return ((one.getModifiers() & Opcodes.ACC_SYNTHETIC) != 0)
+            && ((two.getModifiers() & Opcodes.ACC_SYNTHETIC) == 0);
+    }
+
     /**
      * Given a receiver and a method node, parameterize the method arguments using
      * available generic type information.
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index 026c3751e4..1975811401 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -323,6 +323,31 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-8638, GROOVY-10120
+    void testReturnTypeInferenceWithMethodGenerics18() {
+        String guava = '''
+            @Grab('com.google.guava:guava:31.1-jre')
+            import com.google.common.collect.*
+        '''
+
+        assertScript guava + '''
+            ListMultimap<String, Integer> mmap = ArrayListMultimap.create()
+
+            Map<String, Collection<Integer>> map = mmap.asMap()
+            Set<Map.Entry<String, Collection<Integer>>> set = map.entrySet()
+            Iterator<Map.Entry<String, Collection<Integer>>> it = set.iterator()
+            while (it.hasNext()) { Map.Entry<String, Collection<Integer>> entry = it.next()
+                Collection<Integer> values = entry.value
+            }
+        '''
+
+        shouldFailWithMessages guava + '''
+            ListMultimap<String, Integer> mmap = ArrayListMultimap.create()
+            Map<String, Set<Integer>> map = mmap.asMap() // ArrayListMultimap#asMap() is bridge and lacks generics
+        ''',
+        'Cannot assign java.util.Map <String, java.util.Collection> to: java.util.Map <String, Set>'
+    }
+
     @NotYetImplemented // GROOVY-10339
     void testReturnTypeInferenceWithMethodGenerics21() {
         for (type in ['Character', 'Integer']) {