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
The following commit(s) were added to refs/heads/GROOVY_3_0_X by this push: new ef324616e2 GROOVY-10436: STC: closure parameter as type witness for SAM-type target ef324616e2 is described below commit ef324616e2da53cea36762425b5c9743ed086344 Author: Eric Milles <eric.mil...@thomsonreuters.com> AuthorDate: Thu Jun 16 15:32:35 2022 -0500 GROOVY-10436: STC: closure parameter as type witness for SAM-type target --- .../transform/stc/StaticTypeCheckingVisitor.java | 10 +++++++++- src/test/groovy/transform/stc/GenericsSTCTest.groovy | 19 +++++++++++++++---- 2 files changed, 24 insertions(+), 5 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 23f95c673c..f421fabc0e 100644 --- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java +++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java @@ -2933,11 +2933,19 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { // check for implicit type arguments int i = -1; Parameter[] p = method.getParameters(); for (Expression argument : (ArgumentListExpression) arguments) { i += 1; - if (argument instanceof ClosureExpression || isNullConstant(argument)) continue; + if (isNullConstant(argument)) continue; ClassNode pType = p[Math.min(i, p.length - 1)].getType(); Map<GenericsTypeName, GenericsType> gc = new HashMap<>(); extractGenericsConnections(gc, wrapTypeIfNecessary(getType(argument)), pType); + // GROOVY-10436: extract generics connections from closure parameter declaration(s) + if (argument == expression || (argument instanceof ClosureExpression && isSAMType(pType))) { + Parameter[] q = getParametersSafe((ClosureExpression) argument); + ClassNode[] r = extractTypesFromParameters(q); // maybe typed + ClassNode[] s = GenericsUtils.parameterizeSAM(pType).getV1(); + for (int j = 0; j < r.length && j < s.length; j += 1) + if (!q[j].isDynamicTyped()) extractGenericsConnections(gc, r[j], s[j]); + } gc.forEach((key, gt) -> { for (GenericsType tp : typeParameters) { diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy index f021659414..06a5b3ab39 100644 --- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy +++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy @@ -3269,6 +3269,21 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase { ''' } + // GROOVY-10436 + void testReturnTypeInferenceWithClosure3() { + String method = '''import java.util.function.BiConsumer + + def <T> void m(BiConsumer<String, ? super T> consumer) { } + ''' + assertScript method + ''' + this.<Number>m { string, number -> number.toBigDecimal() } + ''' + assertScript method + ''' + // the only type witness for T is the closure parameter + m { string, Number number -> number.toBigDecimal() } + ''' + } + // GROOVY-6129 void testShouldNotThrowNPE() { assertScript ''' @@ -3706,10 +3721,6 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase { void testConcreteTypeInsteadOfGenerifiedInterface() { assertScript ''' - import groovy.transform.ASTTest - import static org.codehaus.groovy.transform.stc.StaticTypesMarker.* - import static org.codehaus.groovy.ast.ClassHelper.* - interface Converter<F, T> { T convertC(F from) }