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/28 16:34:46 UTC

[groovy] branch master updated: GROOVY-10813: fix receiver distance, receiver static and extension order

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 657c8e5395 GROOVY-10813: fix receiver distance, receiver static and extension order
657c8e5395 is described below

commit 657c8e5395d1343775669a425167c78dcd9ac220
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Nov 28 10:16:10 2022 -0600

    GROOVY-10813: fix receiver distance, receiver static and extension order
---
 ...StaticTypesMethodReferenceExpressionWriter.java |  90 +++---
 .../transform/stc/MethodReferenceTest.groovy       | 340 ++++++++++++---------
 2 files changed, 229 insertions(+), 201 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesMethodReferenceExpressionWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesMethodReferenceExpressionWriter.java
index c3efd7a793..19b8b030d0 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesMethodReferenceExpressionWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesMethodReferenceExpressionWriter.java
@@ -18,9 +18,6 @@
  */
 package org.codehaus.groovy.classgen.asm.sc;
 
-import groovy.lang.Tuple;
-import groovy.lang.Tuple2;
-import org.codehaus.groovy.ast.ASTNode;
 import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.MethodNode;
@@ -44,8 +41,9 @@ import org.objectweb.asm.Opcodes;
 
 import java.util.Arrays;
 import java.util.List;
-import java.util.stream.Collectors;
 
+import static java.util.Comparator.comparingInt;
+import static java.util.stream.Collectors.joining;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.classX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX;
@@ -143,7 +141,7 @@ public class StaticTypesMethodReferenceExpressionWriter extends MethodReferenceE
 
         if (!isClassExpression) {
             if (isConstructorReference) { // TODO: move this check to the parser
-                addFatalError("Constructor reference must be TypeName::new", methodReferenceExpression);
+                controller.getSourceUnit().addFatalError("Constructor reference must be TypeName::new", methodReferenceExpression);
             } else if (methodRefMethod.isStatic() && !targetIsArgument) {
                 // "string"::valueOf refers to static method, so instance is superfluous
                 typeOrTargetRef = makeClassTarget(typeOrTargetRefType, typeOrTargetRef);
@@ -191,10 +189,10 @@ public class StaticTypesMethodReferenceExpressionWriter extends MethodReferenceE
     private void validate(final MethodReferenceExpression methodReference, final ClassNode targetType, final String methodName, final MethodNode methodNode, final Parameter[] samParameters, final ClassNode samReturnType) {
         if (methodNode == null) {
             String error = String.format("Failed to find the expected method[%s(%s)] in the type[%s]",
-                    methodName, Arrays.stream(samParameters).map(e -> e.getType().getText()).collect(Collectors.joining(",")), targetType.getText());
-            addFatalError(error, methodReference);
+                    methodName, Arrays.stream(samParameters).map(e -> e.getType().getText()).collect(joining(",")), targetType.getText());
+            controller.getSourceUnit().addFatalError(error, methodReference);
         } else if (methodNode.isVoidMethod() && !ClassHelper.isPrimitiveVoid(samReturnType)) {
-            addFatalError("Invalid return type: void is not convertible to " + samReturnType.getText(), methodReference);
+            controller.getSourceUnit().addFatalError("Invalid return type: void is not convertible to " + samReturnType.getText(), methodReference);
         } else if (samParameters.length > 0 && isTypeReferringInstanceMethod(methodReference.getExpression(), methodNode) && !isAssignableTo(samParameters[0].getType(), targetType)) {
             throw new RuntimeParserException("Invalid receiver type: " + samParameters[0].getType().getText() + " is not compatible with " + targetType.getText(), methodReference.getExpression());
         }
@@ -350,7 +348,26 @@ public class StaticTypesMethodReferenceExpressionWriter extends MethodReferenceE
             return true; // no match; remove method
         });
 
-        return chooseMethodRefMethodCandidate(typeOrTargetRef, methods);
+        return chooseMethodRefMethod(methods, typeOrTargetRef, typeOrTargetRefType);
+    }
+
+    private MethodNode chooseMethodRefMethod(final List<MethodNode> methods, final Expression typeOrTargetRef, final ClassNode typeOrTargetRefType) {
+        if (methods.isEmpty()) return null;
+        if (methods.size() == 1) return methods.get(0);
+        return methods.stream().max(comparingInt((MethodNode mn) -> {
+            int score = 9;
+            for (ClassNode cn = typeOrTargetRefType; cn != null && !cn.equals(mn.getDeclaringClass()); cn = cn.getSuperClass()) {
+                score -= 1;
+            }
+            if (score < 0) {
+                score = 0;
+            }
+            score *= 10;
+            if ((typeOrTargetRef instanceof ClassExpression) == isStaticMethod(mn)) {
+                score += 9;
+            }
+            return score;
+        }).thenComparing(StaticTypesMethodReferenceExpressionWriter::isExtensionMethod)).get();
     }
 
     private List<MethodNode> findVisibleMethods(final String name, final ClassNode type) {
@@ -365,24 +382,23 @@ public class StaticTypesMethodReferenceExpressionWriter extends MethodReferenceE
         return filterMethodsByVisibility(methods, controller.getClassNode());
     }
 
-    private void addFatalError(final String msg, final ASTNode node) {
-        controller.getSourceUnit().addFatalError(msg, node);
-    }
-
     //--------------------------------------------------------------------------
 
-    private static boolean isConstructorReference(final String methodRefName) {
-        return "new".equals(methodRefName);
+    private static boolean isConstructorReference(final String name) {
+        return "new".equals(name);
+    }
+
+    private static boolean isExtensionMethod(final MethodNode mn) {
+        return (mn instanceof ExtensionMethodNode);
     }
 
-    private static boolean isExtensionMethod(final MethodNode methodRefMethod) {
-        return (methodRefMethod instanceof ExtensionMethodNode);
+    private static boolean isStaticMethod(final MethodNode mn) {
+        return isExtensionMethod(mn) ? ((ExtensionMethodNode) mn).isStaticExtension() : mn.isStatic();
     }
 
     private static boolean isTypeReferringInstanceMethod(final Expression typeOrTargetRef, final MethodNode mn) {
         // class::instanceMethod
-        return (typeOrTargetRef instanceof ClassExpression) && ((mn != null && !mn.isStatic())
-                || (isExtensionMethod(mn) && !((ExtensionMethodNode) mn).isStaticExtension()));
+        return (typeOrTargetRef instanceof ClassExpression) && (mn != null && !isStaticMethod(mn));
     }
 
     private static Expression makeClassTarget(final ClassNode target, final Expression source) {
@@ -394,40 +410,4 @@ public class StaticTypesMethodReferenceExpressionWriter extends MethodReferenceE
     private static Parameter[] removeFirstParameter(final Parameter[] parameters) {
         return Arrays.copyOfRange(parameters, 1, parameters.length);
     }
-
-    /**
-     * Chooses the best method node for method reference.
-     */
-    private static MethodNode chooseMethodRefMethodCandidate(final Expression methodRef, final List<MethodNode> candidates) {
-        if (candidates.size() == 1) return candidates.get(0);
-
-        return candidates.stream()
-                .map(e -> Tuple.tuple(e, matchingScore(e, methodRef)))
-                .min((t1, t2) -> Integer.compare(t2.getV2(), t1.getV2()))
-                .map(Tuple2::getV1)
-                .orElse(null);
-    }
-
-    private static Integer matchingScore(final MethodNode mn, final Expression typeOrTargetRef) {
-        ClassNode typeOrTargetRefType = typeOrTargetRef.getType(); // TODO: pass this type in
-
-        int score = 9;
-        for (ClassNode cn = mn.getDeclaringClass(); null != cn && !cn.equals(typeOrTargetRefType); cn = cn.getSuperClass()) {
-            score -= 1;
-        }
-        if (score < 0) {
-            score = 0;
-        }
-        score *= 10;
-
-        if ((typeOrTargetRef instanceof ClassExpression) == mn.isStatic()) {
-            score += 9;
-        }
-
-        if (isExtensionMethod(mn)) {
-            score += 100;
-        }
-
-        return score;
-    }
 }
diff --git a/src/test/groovy/transform/stc/MethodReferenceTest.groovy b/src/test/groovy/transform/stc/MethodReferenceTest.groovy
index 3ddd3c3892..6070c93777 100644
--- a/src/test/groovy/transform/stc/MethodReferenceTest.groovy
+++ b/src/test/groovy/transform/stc/MethodReferenceTest.groovy
@@ -21,7 +21,6 @@ package groovy.transform.stc
 import org.junit.Test
 
 import static groovy.test.GroovyAssert.assertScript
-import static groovy.test.GroovyAssert.isAtLeastJdk
 import static groovy.test.GroovyAssert.shouldFail
 
 final class MethodReferenceTest {
@@ -38,12 +37,12 @@ final class MethodReferenceTest {
     void testFunctionCI() {
         assertScript shell, '''
             @CompileStatic
-            void p() {
+            void test() {
                 def result = [1, 2, 3].stream().map(Object::toString).collect(Collectors.toList())
                 assert result == ['1', '2', '3']
             }
 
-            p()
+            test()
         '''
     }
 
@@ -51,12 +50,12 @@ final class MethodReferenceTest {
     void testFunctionCI2() {
         assertScript shell, '''
             @CompileStatic
-            void p() {
+            void test() {
                 def result = [1, 2, 3].stream().map(Integer::toString).collect(Collectors.toList())
                 assert result == ['1', '2', '3']
             }
 
-            p()
+            test()
         '''
     }
 
@@ -64,26 +63,26 @@ final class MethodReferenceTest {
     void testFunctionCI3() {
         assertScript shell, '''
             @CompileStatic
-            void p() {
+            void test() {
                 List<String> list = ['a','bc','def']
                 Function<String,String> self = str -> str // help for toMap
                 def map = list.stream().collect(Collectors.toMap(self, String::length))
                 assert map == [a: 1, bc: 2, 'def': 3]
             }
 
-            p()
+            test()
         '''
 
         assertScript shell, '''
             @CompileStatic
-            void p() {
+            void test() {
                 List<String> list = ['a','bc','def']
                 // TODO: inference for T in toMap(Function<? super T,...>, Function<? super T,...>)
-                def map = list.stream().collect(Collectors.toMap(Function.<String>identity(), String::length))
-                assert map == [a: 1, bc: 2, 'def': 3]
+                def result = list.stream().collect(Collectors.toMap(Function.<String>identity(), String::length))
+                assert result == [a: 1, bc: 2, 'def': 3]
             }
 
-            p()
+            test()
         '''
     }
 
@@ -91,11 +90,11 @@ final class MethodReferenceTest {
     void testFunctionCI4() {
         def err = shouldFail shell, '''
             @CompileStatic
-            void p() {
-                def result = [1, 2, 3].stream().map(String::toString).collect(Collectors.toList())
+            void test() {
+                [1, 2, 3].stream().map(String::toString).collect(Collectors.toList())
             }
 
-            p()
+            test()
         '''
         assert err =~ /Invalid receiver type: java.lang.Integer is not compatible with java.lang.String/
     }
@@ -168,6 +167,7 @@ final class MethodReferenceTest {
                 int size = f.applyAsInt("")
                 assert size == 0
             }
+
             test()
         '''
 
@@ -178,6 +178,7 @@ final class MethodReferenceTest {
                 int length = f.applyAsInt("")
                 assert length == 0
             }
+
             test()
         '''
 
@@ -188,6 +189,7 @@ final class MethodReferenceTest {
                 Integer length = f.apply("")
                 assert length == 0
             }
+
             test()
         '''
 
@@ -200,11 +202,10 @@ final class MethodReferenceTest {
                 IntStream chars = f.apply("")
                 assert chars.count() == 0
             }
+
             test()
         '''
 
-        if (!isAtLeastJdk('11.0')) return
-
         assertScript shell, '''
             @CompileStatic
             void test() {
@@ -212,6 +213,7 @@ final class MethodReferenceTest {
                 int result = f.applyAsInt("","")
                 assert result == 0
             }
+
             test()
         '''
     }
@@ -222,12 +224,14 @@ final class MethodReferenceTest {
             class C {
                 String p
             }
+
             @CompileStatic
             Map test(Collection<C> items) {
                 items.stream().collect(
                     Collectors.groupingBy(C::getP) // Failed to find the expected method[getP(Object)] in the type[C]
                 )
             }
+
             def map = test([new C(p:'foo'), new C(p:'bar'), new C(p:'foo')])
             assert map.foo.size() == 2
             assert map.bar.size() == 1
@@ -242,6 +246,7 @@ final class MethodReferenceTest {
                 strings.removeIf(String::isEmpty)
                 assert strings.isEmpty()
             }
+
             test()
         '''
     }
@@ -254,6 +259,7 @@ final class MethodReferenceTest {
                 BiConsumer<List<T>, Consumer<? super T>> binder = List::forEach // default method of Iterator
                 binder.accept(list, todo)
             }
+
             test(['works']) { assert it == 'works' }
         '''
     }
@@ -264,8 +270,9 @@ final class MethodReferenceTest {
             @CompileStatic
             void test() {
                 def result = [1.0G, 2.0G, 3.0G].stream().reduce(0.0G, BigDecimal::add)
-                assert 6.0G == result
+                assert result == 6.0G
             }
+
             test()
         '''
     }
@@ -285,6 +292,7 @@ final class MethodReferenceTest {
                 def list = zero.get()
                 assert list.isEmpty()
             }
+
             test()
         '''
 
@@ -296,6 +304,7 @@ final class MethodReferenceTest {
                 assert list.size() == 1
                 assert list[0] == 1
             }
+
             test()
         '''
 
@@ -308,6 +317,7 @@ final class MethodReferenceTest {
                 assert list[0] == 2
                 assert list[1] == 3
             }
+
             test()
         '''
 
@@ -320,6 +330,7 @@ final class MethodReferenceTest {
                 assert list[0] == 2
                 assert list[1] == 3
             }
+
             test()
         '''
     }
@@ -332,6 +343,7 @@ final class MethodReferenceTest {
                     [this,*args]
                 }
             }
+
             @CompileStatic
             void test(C c) {
                 BiFunction<Integer, Integer, List> two = c::m
@@ -341,11 +353,12 @@ final class MethodReferenceTest {
                 assert list[1] == 1
                 assert list[2] == 2
             }
+
             test(new C())
         '''
     }
 
-    @Test // instance::instanceMethod (DGM) -- GROOVY-10653
+    @Test // instance::instanceGroovyMethod -- GROOVY-10653
     void testFunctionII3() {
         assertScript shell, '''
             @CompileStatic
@@ -353,6 +366,7 @@ final class MethodReferenceTest {
                 IntSupplier sizing = chars::size // from StringGroovyMethods
                 return sizing.getAsInt()
             }
+
             int size = test("foo")
             assert size == 3
         '''
@@ -389,73 +403,65 @@ final class MethodReferenceTest {
     @Test // instance::instanceMethod
     void testBinaryOperatorII() {
         assertScript shell, '''
-            @CompileStatic
-            void p() {
-                Adder adder = new Adder()
-                def result = [1.0G, 2.0G, 3.0G].stream().reduce(0.0G, adder::add)
-                assert 6.0G == result
-            }
-
-            p()
-
             class Adder {
                 BigDecimal add(BigDecimal a, BigDecimal b) {
                     a.add(b)
                 }
             }
-        '''
-    }
 
-    @Test // instance::instanceMethod
-    void testBinaryOperatorII_COMPATIBLE() {
-        assertScript shell, '''
             @CompileStatic
-            void p() {
+            void test() {
                 Adder adder = new Adder()
                 def result = [1.0G, 2.0G, 3.0G].stream().reduce(0.0G, adder::add)
-                assert 6.0G == result
+                assert result == 6.0G
             }
 
-            p()
+            test()
+        '''
+    }
 
+    @Test // instance::instanceMethod
+    void testBinaryOperatorII_COMPATIBLE() {
+        assertScript shell, '''
             class Adder {
                 BigDecimal add(Number a, Number b) {
                     ((BigDecimal) a).add((BigDecimal) b)
                 }
             }
+
+            @CompileStatic
+            void test() {
+                Adder adder = new Adder()
+                def result = [1.0G, 2.0G, 3.0G].stream().reduce(0.0G, adder::add)
+                assert result == 6.0G
+            }
+
+            test()
         '''
     }
 
     @Test // expression::instanceMethod
     void testBinaryOperatorII_EXPRESSION() {
         assertScript shell, '''
-            @CompileStatic
-            void p() {
-                def result = [1.0G, 2.0G, 3.0G].stream().reduce(0.0G, new Adder()::add)
-                assert 6.0G == result
-            }
-
-            p()
-
             class Adder {
                 public BigDecimal add(BigDecimal a, BigDecimal b) {
                     a.add(b)
                 }
             }
+
+            @CompileStatic
+            void test() {
+                def result = [1.0G, 2.0G, 3.0G].stream().reduce(0.0G, new Adder()::add)
+                assert result == 6.0G
+            }
+
+            test()
         '''
     }
 
     @Test // expression::instanceMethod
     void testBinaryOperatorII_EXPRESSION2() {
         assertScript shell, '''
-            @CompileStatic
-            void p() {
-                def result = [1.0G, 2.0G, 3.0G].stream().reduce(0.0G, new Adder().getThis()::add)
-                assert new BigDecimal(6) == result
-            }
-
-            p()
-
             class Adder {
                 BigDecimal add(BigDecimal a, BigDecimal b) {
                     a.add(b)
@@ -465,100 +471,100 @@ final class MethodReferenceTest {
                     return this
                 }
             }
+
+            @CompileStatic
+            void test() {
+                def result = [1.0G, 2.0G, 3.0G].stream().reduce(0.0G, new Adder().getThis()::add)
+                assert result == new BigDecimal(6)
+            }
+
+            test()
         '''
     }
 
     @Test // instance::instanceMethod
     void testBinaryOperatorII_RHS() {
         assertScript shell, '''
+            class Adder {
+                BigDecimal add(BigDecimal a, BigDecimal b) {
+                    a.add(b)
+                }
+            }
+
             @CompileStatic
-            void p() {
+            void test() {
                 Adder adder = new Adder()
                 BinaryOperator<BigDecimal> b = adder::add
                 def result = [1.0G, 2.0G, 3.0G].stream().reduce(0.0G, b)
-                assert 6.0G == result
+                assert result == 6.0G
             }
 
-            p()
+            test()
+        '''
+    }
 
+    @Test // expression::instanceMethod
+    void testBinaryOperatorII_RHS2() {
+        assertScript shell, '''
             class Adder {
                 BigDecimal add(BigDecimal a, BigDecimal b) {
                     a.add(b)
                 }
             }
-        '''
-    }
 
-    @Test // expression::instanceMethod
-    void testBinaryOperatorII_RHS2() {
-        assertScript shell, '''
             @CompileStatic
-            void p() {
+            void test() {
                 BinaryOperator<BigDecimal> b = new Adder()::add
                 def result = [1.0G, 2.0G, 3.0G].stream().reduce(0.0G, b)
-                assert 6.0G == result
+                assert result == 6.0G
             }
 
-            p()
-
-            class Adder {
-                BigDecimal add(BigDecimal a, BigDecimal b) {
-                    a.add(b)
-                }
-            }
+            test()
         '''
     }
 
     @Test // instance::staticMethod
     void testBinaryOperatorIS() {
         assertScript shell, '''
-            @CompileStatic
-            void p() {
-                Adder adder = new Adder()
-                def result = [1.0G, 2.0G, 3.0G].stream().reduce(0.0G, adder::add)
-                assert 6.0G == result
-            }
-
-            p()
-
             class Adder {
                 static BigDecimal add(BigDecimal a, BigDecimal b) {
                     a.add(b)
                 }
             }
+
+            @CompileStatic
+            void test() {
+                Adder adder = new Adder()
+                def result = [1.0G, 2.0G, 3.0G].stream().reduce(0.0G, adder::add)
+                assert result == 6.0G
+            }
+
+            test()
         '''
     }
 
     @Test // expression::staticMethod
     void testBinaryOperatorIS_EXPRESSION() {
         assertScript shell, '''
-            @CompileStatic
-            void p() {
-                def result = [1.0G, 2.0G, 3.0G].stream().reduce(0.0G, new Adder()::add)
-                assert 6.0G == result
-            }
-
-            p()
-
             class Adder {
                 static BigDecimal add(BigDecimal a, BigDecimal b) {
                     a.add(b)
                 }
             }
+
+            @CompileStatic
+            void test() {
+                def result = [1.0G, 2.0G, 3.0G].stream().reduce(0.0G, new Adder()::add)
+                assert result == 6.0G
+            }
+
+            test()
         '''
     }
 
     @Test // expression::staticMethod
     void testBinaryOperatorIS_EXPRESSION2() {
         assertScript shell, '''
-            @CompileStatic
-            void p() {
-                def result = [1.0G, 2.0G, 3.0G].stream().reduce(0.0G, Adder.newInstance()::add)
-                assert 6.0G == result
-            }
-
-            p()
-
             class Adder {
                 static BigDecimal add(BigDecimal a, BigDecimal b) {
                     a.add(b)
@@ -568,19 +574,27 @@ final class MethodReferenceTest {
                     new Adder()
                 }
             }
+
+            @CompileStatic
+            void test() {
+                def result = [1.0G, 2.0G, 3.0G].stream().reduce(0.0G, Adder.newInstance()::add)
+                assert result == 6.0G
+            }
+
+            test()
         '''
     }
 
-    @Test // arrayClass::new
+    @Test // class::new
     void testFunctionCN() {
         assertScript shell, '''
             @CompileStatic
-            void p() {
-                def result = [1, 2, 3].stream().toArray(Integer[]::new)
-                assert result == new Integer[] { 1, 2, 3 }
+            void test() {
+                def result = ["1", "2", "3"].stream().map(Integer::new).collect(Collectors.toList())
+                assert result == [1, 2, 3]
             }
 
-            p()
+            test()
         '''
     }
 
@@ -588,12 +602,13 @@ final class MethodReferenceTest {
     void testFunctionCN2() {
         assertScript shell, '''
             @CompileStatic
-            void p() {
-                def result = ["1", "2", "3"].stream().map(Integer::new).collect(Collectors.toList())
+            void test() {
+                Function<String, Integer> f = Integer::new
+                def result = ["1", "2", "3"].stream().map(f).collect(Collectors.toList())
                 assert result == [1, 2, 3]
             }
 
-            p()
+            test()
         '''
     }
 
@@ -610,6 +625,7 @@ final class MethodReferenceTest {
                     new C(Integer::new)
                 }
             }
+
             C.test()
         '''
     }
@@ -644,29 +660,17 @@ final class MethodReferenceTest {
         '''
     }
 
-    @Test // class::new
-    void testFunctionCN5() {
-        assertScript shell, '''
-            @CompileStatic
-            void p() {
-                Function<String, Integer> f = Integer::new
-                assert [1, 2, 3] == ["1", "2", "3"].stream().map(f).collect(Collectors.toList())
-            }
-
-            p()
-        '''
-    }
-
     @Test // arrayClass::new
-    void testIntFunctionCN6() {
+    void testIntFunctionCN() {
         assertScript shell, '''
             @CompileStatic
-            void p() {
-                IntFunction<Integer[]> f = Integer[]::new
-                assert new Integer[] { 1, 2, 3 } == [1, 2, 3].stream().toArray(f)
+            void test() {
+                IntFunction<Integer[]> f = Integer[]::new;
+                def result = [1, 2, 3].stream().toArray(f)
+                result == new Integer[] {1, 2, 3}
             }
 
-            p()
+            test()
         '''
     }
 
@@ -674,12 +678,12 @@ final class MethodReferenceTest {
     void testFunctionCS() {
         assertScript shell, '''
             @CompileStatic
-            void p() {
+            void test() {
                 def result = [1, -2, 3].stream().map(Math::abs).collect(Collectors.toList())
                 assert [1, 2, 3] == result
             }
 
-            p()
+            test()
         '''
     }
 
@@ -687,13 +691,13 @@ final class MethodReferenceTest {
     void testFunctionCS2() {
         assertScript shell, '''
             @CompileStatic
-            void p() {
+            void test() {
                 List<String> list = ['x','y','z']
                 def map = list.stream().collect(Collectors.toMap(Function.identity(), Collections::singletonList))
                 assert map == [x: ['x'], y: ['y'], z: ['z']]
             }
 
-            p()
+            test()
         '''
     }
 
@@ -725,12 +729,13 @@ final class MethodReferenceTest {
     void testFunctionCS4() {
         assertScript shell, '''
             @CompileStatic
-            void p() {
+            void test() {
                 Function<Integer, Integer> f = Math::abs
                 def result = [1, -2, 3].stream().map(f).collect(Collectors.toList())
                 assert [1, 2, 3] == result
             }
-            p()
+
+            test()
         '''
     }
 
@@ -738,12 +743,13 @@ final class MethodReferenceTest {
     void testFunctionCS5() {
         assertScript shell, '''
             @CompileStatic
-            void p() {
+            void test() {
                 def f = Math::abs // No explicit type defined, so it is actually a method closure. We can make it smarter in a later version.
                 def result = [1, -2, 3].stream().map(f).collect(Collectors.toList())
                 assert [1, 2, 3] == result
             }
-            p()
+
+            test()
         '''
     }
 
@@ -751,35 +757,38 @@ final class MethodReferenceTest {
     void testFunctionCS6() {
         assertScript shell, '''
             @CompileStatic
-            void p() {
+            void test() {
                 Supplier<List> zero = Arrays::asList
                 def list = zero.get()
                 assert list.isEmpty()
             }
-            p()
+
+            test()
         '''
 
         assertScript shell, '''
             @CompileStatic
-            void p() {
+            void test() {
                 Function<Integer, List> one = Arrays::asList
                 def list = one.apply(1)
                 assert list.size() == 1
                 assert list[0] == 1
             }
-            p()
+
+            test()
         '''
 
         assertScript shell, '''
             @CompileStatic
-            void p() {
+            void test() {
                 BiFunction<Integer, Integer, List> two = Arrays::asList
                 def list = two.apply(2,3)
                 assert list.size() == 2
                 assert list[0] == 2
                 assert list[1] == 3
             }
-            p()
+
+            test()
         '''
     }
 
@@ -824,11 +833,12 @@ final class MethodReferenceTest {
     void testFunctionCI_DGM() {
         assertScript shell, '''
             @CompileStatic
-            void p() {
+            void test() {
                 def result = ['a', 'ab', 'abc'].stream().map(String::size).collect(Collectors.toList())
                 assert [1, 2, 3] == result
             }
-            p()
+
+            test()
         '''
     }
 
@@ -836,11 +846,12 @@ final class MethodReferenceTest {
     void testFunctionCS_DGSM() {
         assertScript shell, '''
             @CompileStatic
-            void p() {
+            void test() {
                 def result = [{}, {}, {}].stream().map(Thread::startDaemon).collect(Collectors.toList())
                 assert result.every(e -> e instanceof Thread)
             }
-            p()
+
+            test()
         '''
     }
 
@@ -848,12 +859,13 @@ final class MethodReferenceTest {
     void testFunctionCI_SHADOW_DGM() {
         assertScript shell, '''
             @CompileStatic
-            void p() {
+            void test() {
                 def result = [[a:1], [b:2], [c:3]].stream().map(Object::toString).collect(Collectors.toList())
-                assert 3 == result.size()
-                assert ['[a:1]', '[b:2]', '[c:3]'] == result
+                assert result.size() == 3
+                assert result == ['[a:1]', '[b:2]', '[c:3]']
             }
-            p()
+
+            test()
         '''
     }
 
@@ -861,14 +873,15 @@ final class MethodReferenceTest {
     void testFunctionCS_MULTI_DGSM() {
         assertScript shell, '''
             @CompileStatic
-            void p() {
+            void test() {
                 def result = [{}, {}, {}].stream().map(Thread::startDaemon).collect(Collectors.toList())
                 assert result.every(e -> e instanceof Thread)
 
                 result = [{}, {}, {}].stream().map(Thread::startDaemon).collect(Collectors.toList())
                 assert result.every(e -> e instanceof Thread)
             }
-            p()
+
+            test()
         '''
     }
 
@@ -876,7 +889,7 @@ final class MethodReferenceTest {
     void testMethodNotFound1() {
         def err = shouldFail shell, '''
             @CompileStatic
-            void p() {
+            void test() {
                 [1.0G, 2.0G, 3.0G].stream().reduce(0.0G, BigDecimal::addx)
             }
         '''
@@ -887,7 +900,7 @@ final class MethodReferenceTest {
     void testMethodNotFound2() {
         def err = shouldFail shell, '''
             @CompileStatic
-            void p() {
+            void test() {
                 Function<String,String> reference = String::toLowerCaseX
             }
         '''
@@ -926,8 +939,43 @@ final class MethodReferenceTest {
         '''
     }
 
+    @Test // GROOVY-10813
+    void testMethodSelection2() {
+        for (spec in ['', '<?>', '<Object>', '<? extends Object>', '<? super String>']) {
+            assertScript shell, """
+                @CompileStatic
+                void test() {
+                    Consumer$spec c = this::print // overloads in Script and DefaultGroovyMethods
+                    c.accept('hello world!')
+                }
+
+                test()
+            """
+        }
+        for (spec in ['', '<?,?>', '<?,Object>', '<?,? extends Object>', '<?,? super String>']) {
+            assertScript shell, """
+                @CompileStatic
+                void test() {
+                    BiConsumer$spec c = Object::print
+                    c.accept(this, 'hello world!')
+                }
+
+                test()
+            """
+        }
+        assertScript shell, '''
+            @CompileStatic
+            void test() {
+                BiConsumer<Script,?> c = Script::print
+                c.accept(this, 'hello world!')
+            }
+
+            test()
+        '''
+    }
+
     @Test // GROOVY-10742
-    void testVoidMethodSelection() {
+    void testIncompatibleReturnType() {
         def err = shouldFail shell, '''
             void foo(bar) {
             }