This is an automated email from the ASF dual-hosted git repository.
sunlan 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 9a8a33bd81 GROOVY-11685: STC: `null` or `void` return within closure
expression (#2243)
9a8a33bd81 is described below
commit 9a8a33bd81f270d76a26f2f9fd13a8d6ec284a26
Author: Eric Milles <[email protected]>
AuthorDate: Sat May 31 21:09:07 2025 -0500
GROOVY-11685: STC: `null` or `void` return within closure expression (#2243)
---
.../groovy/transform/stc/StaticTypeCheckingVisitor.java | 5 +++--
.../groovy/groovy/transform/stc/ClosuresSTCTest.groovy | 17 +++++++++++++++++
2 files changed, 20 insertions(+), 2 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 fa7df3da1e..2605a17e2e 100644
---
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -2397,7 +2397,7 @@ out: if ((samParameterTypes.length == 1 &&
isOrImplements(samParameterTypes[0
protected ClassNode checkReturnType(final ReturnStatement statement) {
Expression expression = statement.getExpression();
- ClassNode type = getType(expression);
+ var type = statement.isReturningNullOrVoid() ? VOID_TYPE :
getType(expression); // GROOVY-11685
TypeCheckingContext.EnclosingClosure enclosingClosure =
typeCheckingContext.getEnclosingClosure();
if (enclosingClosure != null) {
@@ -2419,7 +2419,8 @@ out: if ((samParameterTypes.length == 1 &&
isOrImplements(samParameterTypes[0
} else if (statement.isReturningNullOrVoid() ?
!isPrimitiveType(inferredReturnType) // GROOVY-7713, GROOVY-8202
:
GenericsUtils.buildWildcardType(wrapTypeIfNecessary(inferredReturnType)).isCompatibleWith(wrapTypeIfNecessary(type)))
{
type = inferredReturnType; // GROOVY-8310, GROOVY-10082,
GROOVY-10091, GROOVY-10128, GROOVY-10306: allow simple covariance
- } else if (!isPrimitiveVoid(type) &&
!extension.handleIncompatibleReturnType(statement, type)) { // GROOVY-10277:
incompatible
+ } else if ((statement.isReturningNullOrVoid() ||
!isPrimitiveVoid(type)) && !extension.handleIncompatibleReturnType(statement,
type)) {
+ // GROOVY-10277, GROOVY-11490: incompatible return
statement (null for primitive or inconvertible type)
String value = (statement.isReturningNullOrVoid() ? "null"
: "value of type " + prettyPrintType(type));
String which = (enclosingClosure.getClosureExpression()
instanceof LambdaExpression ? "lambda" : "closure");
addStaticTypeError("Cannot return " + value + " for " +
which + " expecting " + prettyPrintType(inferredReturnType), expression);
diff --git a/src/test/groovy/groovy/transform/stc/ClosuresSTCTest.groovy
b/src/test/groovy/groovy/transform/stc/ClosuresSTCTest.groovy
index 3bec5b2998..856cc3c4bd 100644
--- a/src/test/groovy/groovy/transform/stc/ClosuresSTCTest.groovy
+++ b/src/test/groovy/groovy/transform/stc/ClosuresSTCTest.groovy
@@ -429,6 +429,23 @@ class ClosuresSTCTest extends StaticTypeCheckingTestCase {
'''
}
+ // GROOVY-11685
+ void testCollect3() {
+ assertScript '''
+ List<Number> test(List<String> strings) {
+ List<Number> numbers = []
+ if (true) {
+ numbers = strings.collect { string ->
+ if (!string.isNumber()) return
+ (Number) Integer.parseInt(string)
+ }
+ }
+ numbers
+ }
+ assert test(['1','2','3','x']) == [1,2,3,null]
+ '''
+ }
+
void testWithIntReturnType() {
assertScript '''
class Test {