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 2023/06/06 20:47:31 UTC
[groovy] branch master updated: GROOVY-11083: STC: propagate inferred closure param type
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 1e0e8b98bd GROOVY-11083: STC: propagate inferred closure param type
1e0e8b98bd is described below
commit 1e0e8b98bd7418e7ba7d455394d9fd9f3a4a849a
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue Jun 6 15:16:02 2023 -0500
GROOVY-11083: STC: propagate inferred closure param type
---
.../transform/stc/StaticTypeCheckingVisitor.java | 5 +-
.../groovy/transform/stc/ClosuresSTCTest.groovy | 129 +++++++++++++--------
.../groovy/transform/stc/CoercionSTCTest.groovy | 11 ++
3 files changed, 93 insertions(+), 52 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 e5792f0fae..5c134ebcd2 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -3136,14 +3136,15 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
paramTypes = samParamTypes;
} else { // TODO: error for length mismatch
paramTypes = Arrays.copyOf(samParamTypes, n);
- for (int i = 0; i < Math.min(n, samParamTypes.length); i += 1) {
+ for (int i = 0, j = Math.min(n, samParamTypes.length); i < j; i += 1) {
+ if (p[i].isDynamicTyped()) { p[i].setType(samParamTypes[i]); } else // GROOVY-11083
checkParamType(p[i], paramTypes[i], i == n-1, expression instanceof LambdaExpression);
}
}
- expression.putNodeMetaData(CLOSURE_ARGUMENTS, paramTypes);
if (paramTypes.length != samParamTypes.length) { // GROOVY-8499
addError("Incorrect number of parameters. Expected " + samParamTypes.length + " but found " + paramTypes.length, expression);
}
+ expression.putNodeMetaData(CLOSURE_ARGUMENTS, paramTypes);
}
}
}
diff --git a/src/test/groovy/transform/stc/ClosuresSTCTest.groovy b/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
index 490f2338d0..0225bf0de1 100644
--- a/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
@@ -18,27 +18,75 @@
*/
package groovy.transform.stc
+import groovy.test.NotYetImplemented
+
/**
* Unit tests for static type checking : closures.
*/
class ClosuresSTCTest extends StaticTypeCheckingTestCase {
- void testClosureWithoutArguments1() {
+ void testCallClosure1() {
assertScript '''
def c = { return 'foo' }
assert c() == 'foo'
'''
}
- void testClosureWithoutArguments2() {
+ void testCallClosure2() {
assertScript '''
def c = { -> return 'foo' }
assert c() == 'foo'
'''
}
+ @NotYetImplemented
+ void testCallClosure3() {
+ shouldFailWithMessages '''
+ def c = { -> }
+ c('')
+ ''',
+ 'Cannot call closure that accepts [] with [java.lang.String]'
+ }
+
+ void testCallClosure4() {
+ assertScript '''
+ def c = { int a, int b -> a + b }
+ assert c(5, 7) == 12
+ '''
+ }
+
+ void testCallClosure5() {
+ shouldFailWithMessages '''
+ def c = { int a, int b -> a + b }
+ c('5', '7')
+ ''',
+ 'Cannot call closure that accepts [int, int] with [java.lang.String, java.lang.String]'
+ }
+
+ void testCallClosure6() {
+ assertScript '''
+ def result = { int a, int b -> a + b }(5, 7)
+ assert result == 12
+ '''
+ }
+
+ void testCallClosure7() {
+ shouldFailWithMessages '''
+ { int a, int b -> a + b }('5', 7)
+ ''',
+ 'Cannot call closure that accepts [int, int] with [java.lang.String, int]'
+ }
+
+ // GROOVY-6365
+ void testCallClosure8() {
+ assertScript '''
+ def c = { Object[] args -> args.length }
+ assert c('one', 'two') == 2
+ '''
+ }
+
// GROOVY-10071
- void testClosureWithoutArguments3() {
+ void testCallClosure9() {
assertScript '''
def c = { ... zeroOrMore -> return 'foo' + zeroOrMore }
assert c('bar', 'baz') == 'foo[bar, baz]'
@@ -47,22 +95,33 @@ class ClosuresSTCTest extends StaticTypeCheckingTestCase {
'''
}
- // GROOVY-10072, GROOVY-11023
- void testClosureWithoutArguments4() {
+ // GROOVY-10072
+ void testCallClosure10() {
assertScript '''
def c = { p = 'foo' -> return p }
assert c('bar') == 'bar'
assert c() == 'foo'
'''
+ }
+
+ // GROOVY-10072
+ void testCallClosure11() {
assertScript '''
- def c = { p, q = p.toString() -> '' + p + q }
- assert c('foo', 'bar') == 'foobar'
- assert c('foo') == 'foofoo'
+ def c = { Number n, Number total = 41 -> total += n }
+ assert c(1) == 42
'''
}
+ // GROOVY-10072
+ void testCallClosure12() {
+ shouldFailWithMessages '''
+ def c = { Number n, Number total = new Date() -> total += n }
+ ''',
+ 'Cannot assign value of type java.util.Date to variable of type java.lang.Number'
+ }
+
// GROOVY-10636
- void testClosureWithoutArguments5() {
+ void testCallClosure13() {
assertScript '''
def f(Closure<Number>... closures) {
closures*.call().sum()
@@ -70,6 +129,10 @@ class ClosuresSTCTest extends StaticTypeCheckingTestCase {
Object result = f({->1},{->2})
assert result == 3
'''
+ }
+
+ // GROOVY-10636
+ void testCallClosure14() {
shouldFailWithMessages '''
def f(Closure<Number>... closures) {
}
@@ -78,36 +141,16 @@ class ClosuresSTCTest extends StaticTypeCheckingTestCase {
'Cannot return value of type java.lang.String for closure expecting java.lang.Number'
}
- void testClosureWithArguments1() {
+ // GROOVY-11023
+ void testCallClosure15() {
assertScript '''
- def c = { int a, int b -> a + b }
- assert c(5, 7) == 12
- '''
- shouldFailWithMessages '''
- def c = { int a, int b -> a + b }
- c('5', '7')
- ''',
- 'Cannot call closure that accepts [int, int] with [java.lang.String, java.lang.String]'
- }
-
- void testClosureWithArguments2() {
- assertScript '''
- def result = { int a, int b -> a + b }(5, 7)
- assert result == 12
+ def c = { p, q = p.toString() -> '' + p + q }
+ assert c('foo', 'bar') == 'foobar'
+ assert c('foo') == 'foofoo'
'''
- shouldFailWithMessages '''
- { int a, int b -> a + b }('5', 7)
- ''',
- 'Cannot call closure that accepts [int, int] with [java.lang.String, int]'
}
- // GROOVY-6365
- void testClosureWithArguments3() {
- assertScript '''
- def c = { Object[] args -> args.length }
- assert c('one', 'two') == 2
- '''
- }
+ //
void testClosureReturnTypeInference1() {
assertScript '''
@@ -400,24 +443,10 @@ class ClosuresSTCTest extends StaticTypeCheckingTestCase {
'''
}
- void testClosureCallAsAMethod() {
- assertScript '''
- Closure cl = { 'foo' }
- assert cl() == 'foo'
- '''
- }
-
- void testClosureCallWithOneArgAsAMethod() {
- assertScript '''
- Closure cl = { int x -> "foo$x" }
- assert cl(1) == 'foo1'
- '''
- }
-
void testRecurseClosureCallAsAMethod() {
assertScript '''
Closure<Integer> cl
- cl = { int x-> x==0?x:1+cl(x-1) }
+ cl = { int x -> x == 0 ? x : 1+cl(x-1) }
'''
}
diff --git a/src/test/groovy/transform/stc/CoercionSTCTest.groovy b/src/test/groovy/transform/stc/CoercionSTCTest.groovy
index e3a28b5138..063a489719 100644
--- a/src/test/groovy/transform/stc/CoercionSTCTest.groovy
+++ b/src/test/groovy/transform/stc/CoercionSTCTest.groovy
@@ -493,4 +493,15 @@ class CoercionSTCTest extends StaticTypeCheckingTestCase {
test( [null] )
'''
}
+
+ // GROOVY-11083
+ void testCoerceToFunctionalInterface18() {
+ shouldFailWithMessages '''
+ void setFoo(Consumer<Number> c) {}
+ void test(Date d) {
+ foo = { n = d -> }
+ }
+ ''',
+ 'Cannot assign value of type java.util.Date to variable of type java.lang.Number'
+ }
}