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 16f6be8639 GROOVY-10271, GROOVY-10272: STC: process closure in ternary
expression
16f6be8639 is described below
commit 16f6be8639c15e227efc0154604b6bd8f8ffe1ae
Author: Eric Milles <[email protected]>
AuthorDate: Thu May 19 12:28:46 2022 -0500
GROOVY-10271, GROOVY-10272: STC: process closure in ternary expression
---
.../transform/stc/StaticTypeCheckingVisitor.java | 28 ++++++++++++++----
.../transform/stc/TernaryOperatorSTCTest.groovy | 33 +++++++++++++++++++++-
2 files changed, 54 insertions(+), 7 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 88df814abb..91834456a7 100644
---
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -4176,12 +4176,10 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
}
Expression trueExpression = expression.getTrueExpression();
ClassNode typeOfTrue = findCurrentInstanceOfClass(trueExpression,
null);
- trueExpression.visit(this);
- if (typeOfTrue == null) typeOfTrue = getType(trueExpression);
+ typeOfTrue =
Optional.ofNullable(typeOfTrue).orElse(visitValueExpression(trueExpression));
typeCheckingContext.popTemporaryTypeInfo(); // instanceof doesn't
apply to false branch
Expression falseExpression = expression.getFalseExpression();
- falseExpression.visit(this);
- ClassNode typeOfFalse = getType(falseExpression);
+ ClassNode typeOfFalse = visitValueExpression(falseExpression);
ClassNode resultType;
if (isNullConstant(trueExpression) && isNullConstant(falseExpression))
{ // GROOVY-5523
@@ -4201,13 +4199,25 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
popAssignmentTracking(oldTracker);
}
+ /**
+ * @param expr true or false branch of ternary expression
+ * @return the inferred type of {@code expr}
+ */
+ private ClassNode visitValueExpression(final Expression expr) {
+ if (expr instanceof ClosureExpression) {
+ ClassNode targetType = checkForTargetType(expr, null);
+ if (isFunctionalInterface(targetType))
+ processFunctionalInterfaceAssignment(targetType, expr);
+ }
+ expr.visit(this);
+ return getType(expr);
+ }
+
/**
* @param expr true or false branch of ternary expression
* @param type the inferred type of {@code expr}
*/
private ClassNode checkForTargetType(final Expression expr, final
ClassNode type) {
- ClassNode sourceType =
Optional.ofNullable(getInferredReturnType(expr)).orElse(type);
-
ClassNode targetType = null;
MethodNode enclosingMethod = typeCheckingContext.getEnclosingMethod();
BinaryExpression enclosingExpression =
typeCheckingContext.getEnclosingBinaryExpression();
@@ -4222,6 +4232,12 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
targetType = enclosingMethod.getReturnType();
}
+ if (expr instanceof ClosureExpression) { // GROOVY-10271, GROOVY-10272
+ return isSAMType(targetType) ? targetType : type;
+ }
+
+ ClassNode sourceType =
Optional.ofNullable(getInferredReturnType(expr)).orElse(type);
+
if (expr instanceof ConstructorCallExpression) { // GROOVY-9972,
GROOVY-9983
// GROOVY-10114: type parameter(s) could be inferred from call
arguments
if (targetType == null) targetType =
sourceType.getPlainNodeReference();
diff --git a/src/test/groovy/transform/stc/TernaryOperatorSTCTest.groovy
b/src/test/groovy/transform/stc/TernaryOperatorSTCTest.groovy
index c8708bccea..1c5a7da7b7 100644
--- a/src/test/groovy/transform/stc/TernaryOperatorSTCTest.groovy
+++ b/src/test/groovy/transform/stc/TernaryOperatorSTCTest.groovy
@@ -166,6 +166,37 @@ class TernaryOperatorSTCTest extends
StaticTypeCheckingTestCase {
'''
}
+ // GROOVY-10271
+ void testFunctionalInterfaceTarget1() {
+ ['true', 'false'].each { flag ->
+ assertScript """import java.util.function.Supplier
+
+ Supplier<Integer> x = { -> 1 }
+ Supplier<Integer> y = $flag ? x : { -> 2 }
+
+ assert y.get() == ($flag ? 1 : 2)
+ """
+ }
+ }
+
+ // GROOVY-10272
+ void testFunctionalInterfaceTarget2() {
+ assertScript '''
+ import java.util.function.Function
+
+ Function<Integer, Long> x
+ if (true) {
+ x = { a -> a.longValue() }
+ } else {
+ x = { Integer b -> (Long)b }
+ }
+ assert x.apply(42) == 42L
+
+ Function<Integer, Long> y = (true ? { a -> a.longValue() } : {
Integer b -> (Long)b })
+ assert y.apply(42) == 42L
+ '''
+ }
+
// GROOVY-10357
void testAbstractMethodDefault() {
assertScript '''
@@ -186,7 +217,7 @@ class TernaryOperatorSTCTest extends
StaticTypeCheckingTestCase {
}
// GROOVY-10358
- void testCommonInterface() {
+ void testCommonInterface1() {
assertScript '''
interface I {
int m(int i)