From 7b0f6018dcbbf750cc04cd6bc053079cf20e0621 Mon Sep 17 00:00:00 2001 From: Michael Bogdanov Date: Fri, 10 Apr 2015 18:52:46 +0300 Subject: [PATCH] Fix nameless function inlining --- .../kotlin/codegen/inline/InlineCodegen.java | 14 ++++--- .../kotlin/codegen/inline/LambdaInfo.java | 2 +- .../codegen/boxInline/nameless/extension.1.kt | 37 +++++++++++++++++++ .../codegen/boxInline/nameless/extension.2.kt | 29 +++++++++++++++ .../BlackBoxInlineCodegenTestGenerated.java | 15 ++++++++ ...otlinAgainstInlineKotlinTestGenerated.java | 15 ++++++++ 6 files changed, 106 insertions(+), 6 deletions(-) create mode 100644 compiler/testData/codegen/boxInline/nameless/extension.1.kt create mode 100644 compiler/testData/codegen/boxInline/nameless/extension.2.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java index 5459014ac22..01f32cfa384 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java @@ -299,7 +299,7 @@ public class InlineCodegen extends CallGenerator { } private SMAPAndMethodNode generateLambdaBody(LambdaInfo info) { - JetExpression declaration = info.getFunctionLiteralOrCallableReference(); + JetExpression declaration = info.getFunctionWithBodyOrCallableReference(); FunctionDescriptor descriptor = info.getFunctionDescriptor(); MethodContext parentContext = codegen.getContext(); @@ -524,14 +524,18 @@ public class InlineCodegen extends CallGenerator { //TODO deparenthisise typed JetExpression deparenthesized = JetPsiUtil.deparenthesize(expression); return InlineUtil.isInlineLambdaParameter(valueParameterDescriptor) && - (deparenthesized instanceof JetFunctionLiteralExpression || - deparenthesized instanceof JetCallableReferenceExpression); + isInlinableParameterExpression(deparenthesized); + } + + protected static boolean isInlinableParameterExpression(JetExpression deparenthesized) { + return deparenthesized instanceof JetFunctionLiteralExpression || + deparenthesized instanceof JetNamedFunction || + deparenthesized instanceof JetCallableReferenceExpression; } public void rememberClosure(JetExpression expression, Type type) { JetExpression lambda = JetPsiUtil.deparenthesize(expression); - assert lambda instanceof JetCallableReferenceExpression || lambda instanceof JetFunctionLiteralExpression : - "Couldn't find inline expression in " + expression.getText(); + assert isInlinableParameterExpression(lambda) :"Couldn't find inline expression in " + expression.getText(); String labelNameIfPresent = null; PsiElement parent = lambda.getParent(); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.java index 8e18ba9928c..825bd79f3eb 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.java @@ -86,7 +86,7 @@ public class LambdaInfo implements CapturedParamOwner, LabelOwner { return functionDescriptor; } - public JetExpression getFunctionLiteralOrCallableReference() { + public JetExpression getFunctionWithBodyOrCallableReference() { return expression; } diff --git a/compiler/testData/codegen/boxInline/nameless/extension.1.kt b/compiler/testData/codegen/boxInline/nameless/extension.1.kt new file mode 100644 index 00000000000..e9961cb67e7 --- /dev/null +++ b/compiler/testData/codegen/boxInline/nameless/extension.1.kt @@ -0,0 +1,37 @@ +fun test1(): Int { + val inlineX = Inline(9) + return inlineX.calcExt(fun smth(z: Int) = z, 25) +} + +fun test2(): Int { + val inlineX = Inline(9) + return inlineX.calcExt2(fun Int.(): Int = this, 25) +} + +fun test3(): Int { + val inlineX = Inline(9) + return inlineX.doWork(InlineX(11)) +} + +fun test4(): Double { + val inlineX = Inline(9) + return inlineX.doWorkWithDouble(11.0) +} + +fun test5(): Double { + val inlineX = Inline(9) + with(inlineX) { + 11.0.calcDouble(fun (a: Int, b: Double) = a + b) + } + return inlineX.doWorkWithDouble(11.0) +} + +fun box(): String { + if (test1() != 25) return "test1: ${test1()}" + if (test2() != 25) return "test2: ${test2()}" + if (test3() != 20) return "test3: ${test3()}" + if (test4() != 20.0) return "test4: ${test4()}" + if (test5() != 20.0) return "test5: ${test5()}" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/nameless/extension.2.kt b/compiler/testData/codegen/boxInline/nameless/extension.2.kt new file mode 100644 index 00000000000..55e2c13f94a --- /dev/null +++ b/compiler/testData/codegen/boxInline/nameless/extension.2.kt @@ -0,0 +1,29 @@ +inline fun Inline.calcExt(s: (Int) -> Int, p: Int) : Int { + return s(p) +} + +inline fun Inline.calcExt2(s: Int.() -> Int, p: Int) : Int { + return p.s() +} + +class InlineX(val value : Int) {} + +class Inline(val res: Int) { + + inline fun InlineX.calcInt(s: (Int, Int) -> Int) : Int { + return s(res, this.value) + } + + inline fun Double.calcDouble(s: (Int, Double) -> Double) : Double { + return s(res, this) + } + + fun doWork(l : InlineX) : Int { + return l.calcInt(fun (a: Int, b: Int) = a + b) + } + + fun doWorkWithDouble(s : Double) : Double { + return s.calcDouble(fun (a: Int, b: Double) = a + b) + } + +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxInlineCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxInlineCodegenTestGenerated.java index 09802dade73..d8ca343e801 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxInlineCodegenTestGenerated.java @@ -338,6 +338,21 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo } } + @TestMetadata("compiler/testData/codegen/boxInline/nameless") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Nameless extends AbstractBlackBoxInlineCodegenTest { + public void testAllFilesPresentInNameless() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/nameless"), Pattern.compile("^(.+)\\.1.kt$"), true); + } + + @TestMetadata("extension.1.kt") + public void testExtension() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nameless/extension.1.kt"); + doTestMultiFileWithInlineCheck(fileName); + } + } + @TestMetadata("compiler/testData/codegen/boxInline/noInline") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java index 27eac3d9103..3ece3492ba1 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java @@ -338,6 +338,21 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi } } + @TestMetadata("compiler/testData/codegen/boxInline/nameless") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Nameless extends AbstractCompileKotlinAgainstInlineKotlinTest { + public void testAllFilesPresentInNameless() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/nameless"), Pattern.compile("^(.+)\\.1.kt$"), true); + } + + @TestMetadata("extension.1.kt") + public void testExtension() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/nameless/extension.1.kt"); + doBoxTestWithInlineCheck(fileName); + } + } + @TestMetadata("compiler/testData/codegen/boxInline/noInline") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)