diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index 537a8e6b6cf..23c14d60622 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -132,6 +132,10 @@ public class ClosureCodegen extends GenerationStateAware { genClosureFields(closure, cv, typeMapper); + FunctionCodegen.generateDefaultIfNeeded(context.intoFunction(funDescriptor), state, cv, + typeMapper.mapSignature(Name.identifier("invoke"), funDescriptor), funDescriptor, + context.getContextKind(), DefaultParameterValueLoader.DEFAULT); + cv.done(); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index acdc117bc0c..1d53e60e373 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -51,6 +51,7 @@ import java.util.*; import static org.jetbrains.asm4.Opcodes.*; import static org.jetbrains.jet.codegen.AsmUtil.*; import static org.jetbrains.jet.codegen.CodegenUtil.*; +import static org.jetbrains.jet.codegen.binding.CodegenBinding.classNameForAnonymousClass; import static org.jetbrains.jet.codegen.binding.CodegenBinding.isLocalNamedFun; import static org.jetbrains.jet.lang.resolve.BindingContextUtils.callableDescriptorToDeclaration; import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration; @@ -533,11 +534,17 @@ public class FunctionCodegen extends GenerationStateAware { if (contextClass instanceof NamespaceDescriptor) { ownerInternalName = state.getTypeMapper().getOwner(functionDescriptor, kind, true); } - else { + else if (contextClass instanceof ClassDescriptor) { ownerInternalName = JvmClassName.byType(state.getTypeMapper() .mapType(((ClassDescriptor) contextClass).getDefaultType(), JetTypeMapperMode.IMPL)); } + else if (isLocalNamedFun(functionDescriptor)) { + ownerInternalName = classNameForAnonymousClass(state.getBindingContext(), functionDescriptor); + } + else { + throw new IllegalStateException("Couldn't obtain owner name for " + functionDescriptor); + } String descriptor = jvmSignature.getDescriptor().replace(")", "I)"); boolean isConstructor = "".equals(jvmSignature.getName()); @@ -552,7 +559,7 @@ public class FunctionCodegen extends GenerationStateAware { genStubCode(mv); } else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { - generateDefaultImpl(owner, state, signature, functionDescriptor, kind, isStatic, mv, loadStrategy); + generateDefaultImpl(owner, state, signature, functionDescriptor, isStatic, mv, loadStrategy); } } @@ -561,7 +568,6 @@ public class FunctionCodegen extends GenerationStateAware { @NotNull GenerationState state, @NotNull JvmMethodSignature signature, @NotNull FunctionDescriptor functionDescriptor, - @NotNull OwnerKind kind, boolean aStatic, @NotNull MethodVisitor mv, @NotNull DefaultParameterValueLoader loadStrategy @@ -637,7 +643,6 @@ public class FunctionCodegen extends GenerationStateAware { iv.areturn(jvmSignature.getReturnType()); endVisit(mv, "default method", callableDescriptorToDeclaration(state.getBindingContext(), functionDescriptor)); - mv.visitEnd(); } diff --git a/compiler/testData/codegen/box/functions/localFunctions/kt3978.kt b/compiler/testData/codegen/box/functions/localFunctions/kt3978.kt new file mode 100644 index 00000000000..03ba97cd9b7 --- /dev/null +++ b/compiler/testData/codegen/box/functions/localFunctions/kt3978.kt @@ -0,0 +1,10 @@ +fun box() : String { + + + fun local(i: Int = 1) : Int { + return i + } + + return if (local() != 1) "fail" else "OK" +} + diff --git a/compiler/testData/codegen/box/functions/localFunctions/localWithDefault.kt b/compiler/testData/codegen/box/functions/localFunctions/localWithDefault.kt new file mode 100644 index 00000000000..4792a9ce2b9 --- /dev/null +++ b/compiler/testData/codegen/box/functions/localFunctions/localWithDefault.kt @@ -0,0 +1,8 @@ +class Z {} + +fun box(): String { + fun Z.plus(s : String, d : String = "K") : String { + return s + d + } + return Z() + "O" +} diff --git a/compiler/testData/codegen/bytecodeText/directInvoke/callableReference.kt b/compiler/testData/codegen/bytecodeText/directInvoke/callableReference.kt new file mode 100644 index 00000000000..749b223141e --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/directInvoke/callableReference.kt @@ -0,0 +1,10 @@ +class Z{ + + fun a(s: Int) {} + + fun b() { + Z().(Z::a)(1) + } +} + +// 2 invoke \(LZ;I\)V \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/directInvoke/inplaceClosure.kt b/compiler/testData/codegen/bytecodeText/directInvoke/inplaceClosure.kt new file mode 100644 index 00000000000..d7833e060aa --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/directInvoke/inplaceClosure.kt @@ -0,0 +1,5 @@ +fun box() { + 1.{Int.() -> 2}() +} + +// 2 invoke \(I\)I \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/directInvoke/localFun.kt b/compiler/testData/codegen/bytecodeText/directInvoke/localFun.kt new file mode 100644 index 00000000000..de43ea3c151 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/directInvoke/localFun.kt @@ -0,0 +1,8 @@ +fun box() { + fun local(s: Int) { + } + + local(1) +} + +// 2 invoke \(I\)V \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/BytecodeTextTestGenerated.java index 8c177828cc9..320b03b1ca6 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/BytecodeTextTestGenerated.java @@ -31,7 +31,7 @@ import org.jetbrains.jet.codegen.AbstractBytecodeTextTest; /** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") @TestMetadata("compiler/testData/codegen/bytecodeText") -@InnerTestClasses({BytecodeTextTestGenerated.Statements.class}) +@InnerTestClasses({BytecodeTextTestGenerated.DirectInvoke.class, BytecodeTextTestGenerated.Statements.class}) public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { public void testAllFilesPresentInBytecodeText() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/bytecodeText"), Pattern.compile("^(.+)\\.kt$"), true); @@ -97,6 +97,29 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { doTest("compiler/testData/codegen/bytecodeText/topLevelFunWithDefaultArgs.kt"); } + @TestMetadata("compiler/testData/codegen/bytecodeText/directInvoke") + public static class DirectInvoke extends AbstractBytecodeTextTest { + public void testAllFilesPresentInDirectInvoke() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/bytecodeText/directInvoke"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("callableReference.kt") + public void testCallableReference() throws Exception { + doTest("compiler/testData/codegen/bytecodeText/directInvoke/callableReference.kt"); + } + + @TestMetadata("inplaceClosure.kt") + public void testInplaceClosure() throws Exception { + doTest("compiler/testData/codegen/bytecodeText/directInvoke/inplaceClosure.kt"); + } + + @TestMetadata("localFun.kt") + public void testLocalFun() throws Exception { + doTest("compiler/testData/codegen/bytecodeText/directInvoke/localFun.kt"); + } + + } + @TestMetadata("compiler/testData/codegen/bytecodeText/statements") public static class Statements extends AbstractBytecodeTextTest { public void testAllFilesPresentInStatements() throws Exception { @@ -138,6 +161,7 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { public static Test suite() { TestSuite suite = new TestSuite("BytecodeTextTestGenerated"); suite.addTestSuite(BytecodeTextTestGenerated.class); + suite.addTestSuite(DirectInvoke.class); suite.addTestSuite(Statements.class); return suite; } diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java index 0208214c8a3..ac6070d63af 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -2418,11 +2418,21 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/box/functions/localFunctions"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("kt3978.kt") + public void testKt3978() throws Exception { + doTest("compiler/testData/codegen/box/functions/localFunctions/kt3978.kt"); + } + @TestMetadata("localFunctionInConstructor.kt") public void testLocalFunctionInConstructor() throws Exception { doTest("compiler/testData/codegen/box/functions/localFunctions/localFunctionInConstructor.kt"); } + @TestMetadata("localWithDefault.kt") + public void testLocalWithDefault() throws Exception { + doTest("compiler/testData/codegen/box/functions/localFunctions/localWithDefault.kt"); + } + } public static Test innerSuite() {