You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2018/02/02 03:07:30 UTC
groovy git commit: Refine the check of functional interface,
which must be an interface
Repository: groovy
Updated Branches:
refs/heads/native-lambda 91448dd1e -> 13eed82a7
Refine the check of functional interface, which must be an interface
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/13eed82a
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/13eed82a
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/13eed82a
Branch: refs/heads/native-lambda
Commit: 13eed82a7873052e763e8ecda33d417441ff2e8d
Parents: 91448dd
Author: sunlan <su...@apache.org>
Authored: Fri Feb 2 11:07:23 2018 +0800
Committer: sunlan <su...@apache.org>
Committed: Fri Feb 2 11:07:23 2018 +0800
----------------------------------------------------------------------
.../org/codehaus/groovy/ast/ClassHelper.java | 6 +++
.../groovy/classgen/asm/InvocationWriter.java | 2 +-
.../asm/sc/StaticTypesLambdaWriter.java | 2 +-
.../stc/StaticTypeCheckingVisitor.java | 2 +-
src/test/groovy/transform/stc/LambdaTest.groovy | 50 ++++++++++++++++++++
5 files changed, 59 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/13eed82a/src/main/java/org/codehaus/groovy/ast/ClassHelper.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/ClassHelper.java b/src/main/java/org/codehaus/groovy/ast/ClassHelper.java
index 93658d7..7ce72a3 100644
--- a/src/main/java/org/codehaus/groovy/ast/ClassHelper.java
+++ b/src/main/java/org/codehaus/groovy/ast/ClassHelper.java
@@ -395,6 +395,12 @@ public class ClassHelper {
return findSAM(type) != null;
}
+ public static boolean isFunctionalInterface(ClassNode type) {
+ // Functional interface must be an interface at first, or the following exception will occur:
+ // java.lang.invoke.LambdaConversionException: Functional interface SamCallable is not an interface
+ return type.isInterface() && isSAMType(type);
+ }
+
/**
* Returns the single abstract method of a class node, if it is a SAM type, or null otherwise.
*
http://git-wip-us.apache.org/repos/asf/groovy/blob/13eed82a/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java
index bc56b5a..6ab3fd9 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java
@@ -494,7 +494,7 @@ public class InvocationWriter {
return false;
}
- if (ClassHelper.isSAMType(objectExpression.getType())) {
+ if (ClassHelper.isFunctionalInterface(objectExpression.getType())) {
return true;
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/13eed82a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesLambdaWriter.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesLambdaWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesLambdaWriter.java
index 60f8f7d..ab9d0f3 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesLambdaWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesLambdaWriter.java
@@ -98,7 +98,7 @@ public class StaticTypesLambdaWriter extends LambdaWriter {
public void writeLambda(LambdaExpression expression) {
ClassNode lambdaType = getLambdaType(expression);
- if (!ClassHelper.isSAMType(lambdaType.redirect())) {
+ if (!ClassHelper.isFunctionalInterface(lambdaType.redirect())) {
// if the parameter type is not real FunctionInterface, generate the default bytecode, which is actually a closure
super.writeLambda(expression);
return;
http://git-wip-us.apache.org/repos/asf/groovy/blob/13eed82a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
----------------------------------------------------------------------
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 e9ccffd..c3f0148 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -4121,7 +4121,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
collectAllInterfaceMethodsByName(receiver, name, methods);
methods.addAll(OBJECT_TYPE.getMethods(name));
- if (CALL.equals(name) && ClassHelper.isSAMType(receiver)) {
+ if (CALL.equals(name) && ClassHelper.isFunctionalInterface(receiver)) {
MethodNode sam = ClassHelper.findSAM(receiver);
MethodNode callMethodNode = new MethodNode(CALL, sam.getModifiers(), sam.getReturnType(), sam.getParameters(), sam.getExceptions(), sam.getCode());
callMethodNode.setDeclaringClass(sam.getDeclaringClass());
http://git-wip-us.apache.org/repos/asf/groovy/blob/13eed82a/src/test/groovy/transform/stc/LambdaTest.groovy
----------------------------------------------------------------------
diff --git a/src/test/groovy/transform/stc/LambdaTest.groovy b/src/test/groovy/transform/stc/LambdaTest.groovy
index 9bf9774..dc47754 100644
--- a/src/test/groovy/transform/stc/LambdaTest.groovy
+++ b/src/test/groovy/transform/stc/LambdaTest.groovy
@@ -534,6 +534,56 @@ TestScript0.groovy: 14: [Static type checking] - Cannot find matching method jav
'''
}
+ void testSamCall() {
+ assertScript '''
+ import groovy.transform.CompileStatic
+ import java.util.stream.Collectors
+ import java.util.stream.Stream
+
+ @CompileStatic
+ public class Test1 {
+ public static void main(String[] args) {
+ p();
+ }
+
+ public static void p() {
+ SamCallable c = (int e) -> e
+ assert 1 == c(1)
+ }
+ }
+
+ @CompileStatic
+ interface SamCallable {
+ int call(int p);
+ }
+ '''
+ }
+
+ void testSamCall2() {
+ assertScript '''
+ import groovy.transform.CompileStatic
+ import java.util.stream.Collectors
+ import java.util.stream.Stream
+
+ @CompileStatic
+ public class Test1 {
+ public static void main(String[] args) {
+ p();
+ }
+
+ public static void p() {
+ SamCallable c = (int e) -> e // This is actually a closure(not a native lambda), because "Functional interface SamCallable is not an interface"
+ assert 1 == c(1)
+ }
+ }
+
+ @CompileStatic
+ abstract class SamCallable {
+ abstract int call(int p);
+ }
+ '''
+ }
+
void testFunctionWithUpdatingLocalVariable() {
assertScript '''
import groovy.transform.CompileStatic