Repository: groovy Updated Branches: refs/heads/native-lambda f02cf2123 -> 0b8beb93c
Fix types in the operand stack Project: http://git-wip-us.apache.org/repos/asf/groovy/repo Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/0b8beb93 Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/0b8beb93 Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/0b8beb93 Branch: refs/heads/native-lambda Commit: 0b8beb93c60c2ea05bf6b1b4490cebffd2056e1a Parents: f02cf21 Author: sunlan <[email protected]> Authored: Mon Jan 29 12:51:21 2018 +0800 Committer: sunlan <[email protected]> Committed: Mon Jan 29 12:51:21 2018 +0800 ---------------------------------------------------------------------- .../asm/sc/StaticTypesLambdaWriter.java | 35 +++++++++----------- .../stc/StaticTypeCheckingVisitor.java | 5 +++ src/test/groovy/transform/stc/LambdaTest.groovy | 10 ++---- 3 files changed, 24 insertions(+), 26 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/groovy/blob/0b8beb93/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 008d798..7f44c90 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 @@ -113,10 +113,10 @@ public class StaticTypesLambdaWriter extends LambdaWriter { ClassNode classNode = controller.getClassNode(); boolean isInterface = classNode.isInterface(); - ClassNode lambdaClassNode = getOrAddLambdaClass(expression, ACC_PUBLIC | (isInterface ? ACC_STATIC : 0) | ACC_SYNTHETIC, abstractMethodNode); - MethodNode syntheticLambdaMethodNode = lambdaClassNode.getMethods(DO_CALL).get(0); + ClassNode lambdaWrapperClassNode = getOrAddLambdaClass(expression, ACC_PUBLIC | (isInterface ? ACC_STATIC : 0) | ACC_SYNTHETIC, abstractMethodNode); + MethodNode syntheticLambdaMethodNode = lambdaWrapperClassNode.getMethods(DO_CALL).get(0); - BytecodeVariable lambdaWrapperVariable = newGroovyLambdaWrapperAndLoad(lambdaClassNode, syntheticLambdaMethodNode); + BytecodeVariable lambdaWrapperVariable = newGroovyLambdaWrapperAndLoad(lambdaWrapperClassNode, syntheticLambdaMethodNode); loadEnclosingClassInstance(); @@ -126,11 +126,11 @@ public class StaticTypesLambdaWriter extends LambdaWriter { mv.visitInvokeDynamicInsn( abstractMethodNode.getName(), - createAbstractMethodDesc(lambdaType, lambdaClassNode), + createAbstractMethodDesc(lambdaType, lambdaWrapperClassNode), createBootstrapMethod(isInterface), - createBootstrapMethodArguments(abstractMethodDesc, lambdaClassNode, syntheticLambdaMethodNode) + createBootstrapMethodArguments(abstractMethodDesc, lambdaWrapperClassNode, syntheticLambdaMethodNode) ); - operandStack.replace(lambdaType.redirect(), 1); + operandStack.replace(lambdaType.redirect(), 2); if (null != expression.getNodeMetaData(INFERRED_LAMBDA_TYPE)) { // FIXME declaring variable whose initial value is a lambda, e.g. `Function<Integer, String> f = (Integer e) -> 'a' + e` @@ -175,23 +175,20 @@ public class StaticTypesLambdaWriter extends LambdaWriter { } - saveLambdaObjectInWrapper(lambdaType, lambdaWrapperVariable); + saveLambdaObjectInWrapper(lambdaWrapperVariable); + operandStack.replace(lambdaType.redirect(), 2); } - private void saveLambdaObjectInWrapper(ClassNode lambdaType, BytecodeVariable lambdaWrapperVariable) { + private void saveLambdaObjectInWrapper(BytecodeVariable lambdaWrapperVariable) { MethodVisitor mv = controller.getMethodVisitor(); OperandStack operandStack = controller.getOperandStack(); mv.visitInsn(DUP); - operandStack.push(lambdaType.redirect()); operandStack.loadOrStoreVariable(lambdaWrapperVariable, false); - operandStack.push(ClassHelper.LAMBDA_TYPE); operandStack.swap(); mv.visitMethodInsn( INVOKEVIRTUAL, "groovy/lang/Lambda", "setLambdaObject", "(Ljava/lang/Object;)V", false); - - operandStack.remove(1); } private ClassNode getLambdaType(LambdaExpression expression) { @@ -216,10 +213,10 @@ public class StaticTypesLambdaWriter extends LambdaWriter { } } - private BytecodeVariable newGroovyLambdaWrapperAndLoad(ClassNode lambdaClassNode, MethodNode syntheticLambdaMethodNode) { + private BytecodeVariable newGroovyLambdaWrapperAndLoad(ClassNode lambdaWrapperClassNode, MethodNode syntheticLambdaMethodNode) { MethodVisitor mv = controller.getMethodVisitor(); - String lambdaClassInternalName = BytecodeHelper.getClassInternalName(lambdaClassNode); - mv.visitTypeInsn(NEW, lambdaClassInternalName); + String lambdaWrapperClassInternalName = BytecodeHelper.getClassInternalName(lambdaWrapperClassNode); + mv.visitTypeInsn(NEW, lambdaWrapperClassInternalName); mv.visitInsn(DUP); loadEnclosingClassInstance(); @@ -228,7 +225,7 @@ public class StaticTypesLambdaWriter extends LambdaWriter { loadSharedVariables(syntheticLambdaMethodNode); List<ConstructorNode> constructorNodeList = - lambdaClassNode.getDeclaredConstructors().stream() + lambdaWrapperClassNode.getDeclaredConstructors().stream() .filter(e -> Boolean.TRUE.equals(e.getNodeMetaData(IS_GENERATED_CONSTRUCTOR))) .collect(Collectors.toList()); @@ -237,10 +234,10 @@ public class StaticTypesLambdaWriter extends LambdaWriter { } ConstructorNode constructorNode = constructorNodeList.get(0); - Parameter[] lambdaClassConstructorParameters = constructorNode.getParameters(); - mv.visitMethodInsn(INVOKESPECIAL, lambdaClassInternalName, INIT, BytecodeHelper.getMethodDescriptor(ClassHelper.VOID_TYPE, lambdaClassConstructorParameters), lambdaClassNode.isInterface()); + Parameter[] lambdaWrapperClassConstructorParameters = constructorNode.getParameters(); + mv.visitMethodInsn(INVOKESPECIAL, lambdaWrapperClassInternalName, INIT, BytecodeHelper.getMethodDescriptor(ClassHelper.VOID_TYPE, lambdaWrapperClassConstructorParameters), lambdaWrapperClassNode.isInterface()); OperandStack operandStack = controller.getOperandStack(); - operandStack.replace(ClassHelper.LAMBDA_TYPE, lambdaClassConstructorParameters.length); + operandStack.replace(ClassHelper.LAMBDA_TYPE, lambdaWrapperClassConstructorParameters.length); BytecodeVariable variable = controller.getCompileStack().defineVariable(new VariableExpression(LAMBDA_WRAPPER, ClassHelper.LAMBDA_TYPE), false); operandStack.storeVar(variable); http://git-wip-us.apache.org/repos/asf/groovy/blob/0b8beb93/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 a372284..4688e3b 100644 --- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java +++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java @@ -133,6 +133,7 @@ import static org.codehaus.groovy.ast.ClassHelper.GROOVY_OBJECT_TYPE; import static org.codehaus.groovy.ast.ClassHelper.GSTRING_TYPE; import static org.codehaus.groovy.ast.ClassHelper.Integer_TYPE; import static org.codehaus.groovy.ast.ClassHelper.Iterator_TYPE; +import static org.codehaus.groovy.ast.ClassHelper.LAMBDA_TYPE; import static org.codehaus.groovy.ast.ClassHelper.LIST_TYPE; import static org.codehaus.groovy.ast.ClassHelper.Long_TYPE; import static org.codehaus.groovy.ast.ClassHelper.MAP_TYPE; @@ -4098,6 +4099,10 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { if (receiver.isInterface()) { collectAllInterfaceMethodsByName(receiver, name, methods); methods.addAll(OBJECT_TYPE.getMethods(name)); + + if (!receiver.getAnnotations(ClassHelper.FunctionalInterface_Type).isEmpty()) { + methods.addAll(LAMBDA_TYPE.getDeclaredMethods("call")); + } } // TODO: investigate the trait exclusion a bit further, needed otherwise // CallMethodOfTraitInsideClosureAndClosureParamTypeInference fails saying http://git-wip-us.apache.org/repos/asf/groovy/blob/0b8beb93/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 212ec11..1a0b1ab 100644 --- a/src/test/groovy/transform/stc/LambdaTest.groovy +++ b/src/test/groovy/transform/stc/LambdaTest.groovy @@ -405,16 +405,11 @@ TestScript0.groovy: 14: [Static type checking] - Cannot find matching method jav void testFunctionCall() { if (SKIP_ERRORS) return - /* FIXME - [Static type checking] - Cannot find matching method java.lang.Object#plus(int). Please check if the declared type is correct and if the method exists. - @ line 13, column 35. - assert 2 == (e -> e + 1)(1) - */ - assertScript ''' import groovy.transform.CompileStatic import java.util.stream.Collectors import java.util.stream.Stream + import java.util.function.Function @CompileStatic public class Test1 { @@ -423,7 +418,8 @@ TestScript0.groovy: 14: [Static type checking] - Cannot find matching method jav } public static void p() { - assert 2 == (e -> e + 1)(1) + Function<Integer, Integer> f = (Integer e) -> (Integer) (e + 1) // Casting is required... [Static type checking] - Incompatible generic argument types. Cannot assign java.util.function.Function <java.lang.Integer, int> to: java.util.function.Function <Integer, Integer> + assert 2 == f(1) } } '''
