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/06/17 14:11:23 UTC
[groovy] branch GROOVY_4_0_X updated: GROOVY-10436: STC: closure parameter as type witness for SAM-type target
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY_4_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/GROOVY_4_0_X by this push:
new 8635ff87ea GROOVY-10436: STC: closure parameter as type witness for SAM-type target
8635ff87ea is described below
commit 8635ff87ea52ebe5fe962fa64faaa33e86a5a66f
Author: Eric Milles <er...@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 ++-
.../groovy/transform/stc/GenericsSTCTest.groovy | 72 +++++++++++++---------
2 files changed, 52 insertions(+), 30 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 b4a14fc16f..bebfef2e1c 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -2965,11 +2965,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 47f9297329..7776a15992 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -2498,7 +2498,6 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
r.bindings2['a'] = 'A'
r.bindings2.put('b', 'B')
-
'''
}
void testInferDiamondForAssignment() {
@@ -3604,30 +3603,30 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
void testReturnTypeInferenceWithClosure() {
assertScript '''import org.codehaus.groovy.ast.expr.ClosureExpression
class CTypeTest {
- public static void test1(String[] args) {
- // Cannot assign value of type java.lang.Object to variable of type CTypeTest
- @ASTTest(phase=INSTRUCTION_SELECTION,value={
- def cl = node.rightExpression.arguments[0]
- assert cl instanceof ClosureExpression
- def type = cl.getNodeMetaData(INFERRED_TYPE)
- assert type == make(Closure)
- assert type.isUsingGenerics()
- assert type.genericsTypes
- assert type.genericsTypes[0].type.name == 'CTypeTest'
-
- type = node.getNodeMetaData(INFERRED_TYPE)
- assert type.name == 'CTypeTest'
- })
- def s1 = cache {
- return new CTypeTest();
+ static test(String[] args) {
+ // Cannot assign value of type Object to variable of type CTypeTest
+ @ASTTest(phase=INSTRUCTION_SELECTION,value={
+ def cl = node.rightExpression.arguments[0]
+ assert cl instanceof ClosureExpression
+ def type = cl.getNodeMetaData(INFERRED_TYPE)
+ assert type == make(Closure)
+ assert type.isUsingGenerics()
+ assert type.genericsTypes
+ assert type.genericsTypes[0].type.name == 'CTypeTest'
+
+ type = node.getNodeMetaData(INFERRED_TYPE)
+ assert type.name == 'CTypeTest'
+ })
+ def s1 = cache {
+ new CTypeTest()
+ }
+ CTypeTest s2 = cache {
+ new CTypeTest()
+ }
}
- CTypeTest s2 = cache {
- new CTypeTest()
+ static <T> T cache(Closure<T> closure) {
+ return closure.call();
}
- }
- static <T> T cache(Closure<T> closure) {
- return closure.call();
- }
}
1
'''
@@ -3638,7 +3637,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
assertScript '''
import java.util.function.Function
class C {
- final <T> T m(Function<Reader,T> function) {
+ def <T> T m(Function<Reader,T> function) {
new StringReader("").withCloseable { reader ->
function.apply(reader)
}
@@ -3650,6 +3649,25 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
'''
}
+ // GROOVY-10436
+ void testReturnTypeInferenceWithClosure3() {
+ String method = '''import java.util.function.BiConsumer
+
+ def <T> BiConsumer<String, List<T>> m(BiConsumer<String, ? super T> consumer) {
+ return (String text, List<T> list) -> {
+ for (T item : list) consumer.accept(text, item)
+ }
+ }
+ '''
+ 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 '''
@@ -4019,7 +4037,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
'''
}
- //GROOVY-6723, GROOVY-6415
+ // GROOVY-6723, GROOVY-6415
void testIndirectMethodLevelGenerics() {
assertScript '''
class C1<A> {
@@ -4087,10 +4105,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)
}