From 67c2f7105bfe015c6ce483884ba927a43b7ab552 Mon Sep 17 00:00:00 2001 From: Michael Bogdanov Date: Thu, 9 Apr 2015 14:21:55 +0300 Subject: [PATCH] Fix for KT-6863: Internal compiler error folding functions #KT-6863 Fixed --- .../kotlin/codegen/inline/InlineCodegen.java | 9 +++++---- .../kotlin/resolve/InlineDescriptorUtils.java | 2 +- .../resolve/calls/checkers/InlineChecker.java | 14 ++------------ .../extension/InlineAnalyzerExtension.java | 16 +++++++--------- .../boxInline/noInline/lambdaAsGeneric.1.kt | 5 +++++ .../boxInline/noInline/lambdaAsGeneric.2.kt | 3 +++ .../boxInline/noInline/lambdaAsNonFunction.1.kt | 5 +++++ .../boxInline/noInline/lambdaAsNonFunction.2.kt | 3 +++ .../inline/nonLocalReturns/lambdaAsGeneric.kt | 11 +++++++++++ .../inline/nonLocalReturns/lambdaAsGeneric.txt | 4 ++++ .../nonLocalReturns/lambdaAsNonFunction.kt | 11 +++++++++++ .../nonLocalReturns/lambdaAsNonFunction.txt | 4 ++++ .../checkers/JetDiagnosticsTestGenerated.java | 12 ++++++++++++ .../BlackBoxInlineCodegenTestGenerated.java | 12 ++++++++++++ ...leKotlinAgainstInlineKotlinTestGenerated.java | 12 ++++++++++++ .../jetbrains/kotlin/builtins/InlineUtil.java | 12 ++++++++++-- .../reference/CallExpressionTranslator.java | 2 +- 17 files changed, 108 insertions(+), 29 deletions(-) create mode 100644 compiler/testData/codegen/boxInline/noInline/lambdaAsGeneric.1.kt create mode 100644 compiler/testData/codegen/boxInline/noInline/lambdaAsGeneric.2.kt create mode 100644 compiler/testData/codegen/boxInline/noInline/lambdaAsNonFunction.1.kt create mode 100644 compiler/testData/codegen/boxInline/noInline/lambdaAsNonFunction.2.kt create mode 100644 compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaAsGeneric.kt create mode 100644 compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaAsGeneric.txt create mode 100644 compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaAsNonFunction.kt create mode 100644 compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaAsNonFunction.txt 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 ccde808d88c..c0a5d02b5a4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java @@ -24,6 +24,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.backend.common.CodegenUtil; import org.jetbrains.kotlin.builtins.InlineStrategy; import org.jetbrains.kotlin.builtins.InlineUtil; +import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.codegen.*; import org.jetbrains.kotlin.codegen.context.CodegenContext; import org.jetbrains.kotlin.codegen.context.FieldOwnerContext; @@ -508,11 +509,11 @@ public class InlineCodegen extends CallGenerator { } } - public static boolean isInliningClosure(JetExpression expression, ValueParameterDescriptor valueParameterDescriptora) { + public static boolean isInliningClosure(JetExpression expression, ValueParameterDescriptor valueParameterDescriptor) { //TODO deparenthisise typed - JetExpression deparenthesize = JetPsiUtil.deparenthesize(expression); - return deparenthesize instanceof JetFunctionLiteralExpression && - !InlineUtil.hasNoinlineAnnotation(valueParameterDescriptora); + JetExpression deparenthesized = JetPsiUtil.deparenthesize(expression); + return deparenthesized instanceof JetFunctionLiteralExpression && + InlineUtil.isInlineLambdaParameter(valueParameterDescriptor); } public void rememberClosure(JetExpression expression, Type type) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/InlineDescriptorUtils.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/InlineDescriptorUtils.java index 2537fb412a2..459dcbeb629 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/InlineDescriptorUtils.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/InlineDescriptorUtils.java @@ -76,7 +76,7 @@ public class InlineDescriptorUtils { ArgumentMapping mapping = resolvedCall.getArgumentMapping(argument); if (mapping instanceof ArgumentMatch) { ValueParameterDescriptor parameter = ((ArgumentMatch) mapping).getValueParameter(); - if (!InlineUtil.hasNoinlineAnnotation(parameter)) { + if (InlineUtil.isInlineLambdaParameter(parameter)) { return !checkNonLocalReturn || allowsNonLocalReturns(parameter); } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineChecker.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineChecker.java index d6e1e4a2d68..2c30aaf0a76 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineChecker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/InlineChecker.java @@ -222,9 +222,8 @@ class InlineChecker implements CallChecker { private static boolean isInlinableParameter(@NotNull CallableDescriptor descriptor) { JetType type = descriptor.getReturnType(); return type != null && - KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(type) && - !type.isMarkedNullable() && - !InlineUtil.hasNoinlineAnnotation(descriptor); + InlineUtil.isInlineLambdaParameter(descriptor) && + !type.isMarkedNullable(); } private static boolean isInvokeOrInlineExtension(@NotNull CallableDescriptor descriptor) { @@ -272,13 +271,4 @@ class InlineChecker implements CallChecker { context.trace.report(Errors.NON_LOCAL_RETURN_NOT_ALLOWED.on(parameterUsage, parameterUsage, inlinableParameterDescriptor, descriptor)); } } - - @Nullable - public static PsiElement getDeclaration(JetExpression expression) { - do { - expression = PsiTreeUtil.getParentOfType(expression, JetDeclaration.class); - } while (expression instanceof JetMultiDeclaration || expression instanceof JetProperty); - return expression; - } - } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/extension/InlineAnalyzerExtension.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/extension/InlineAnalyzerExtension.java index a874082a8f9..77e4c3e3bba 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/extension/InlineAnalyzerExtension.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/extension/InlineAnalyzerExtension.java @@ -143,17 +143,15 @@ public class InlineAnalyzerExtension implements FunctionAnalyzerExtension.Analyz @Nullable BindingTrace trace ) { JetType type = parameter.getReturnType(); - if (type != null && KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(type)) { - if (!InlineUtil.hasNoinlineAnnotation(parameter)) { - if (type.isMarkedNullable()) { - if (trace != null) { - trace.report(Errors.NULLABLE_INLINE_PARAMETER.on(expression, expression, functionDescriptor)); - } - } - else { - return true; + if (type != null && InlineUtil.isInlineLambdaParameter(parameter)) { + if (type.isMarkedNullable()) { + if (trace != null) { + trace.report(Errors.NULLABLE_INLINE_PARAMETER.on(expression, expression, functionDescriptor)); } } + else { + return true; + } } return false; } diff --git a/compiler/testData/codegen/boxInline/noInline/lambdaAsGeneric.1.kt b/compiler/testData/codegen/boxInline/noInline/lambdaAsGeneric.1.kt new file mode 100644 index 00000000000..9d86f6ba42d --- /dev/null +++ b/compiler/testData/codegen/boxInline/noInline/lambdaAsGeneric.1.kt @@ -0,0 +1,5 @@ +fun box() : String { + test {"123"} + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/noInline/lambdaAsGeneric.2.kt b/compiler/testData/codegen/boxInline/noInline/lambdaAsGeneric.2.kt new file mode 100644 index 00000000000..fa1a43fefce --- /dev/null +++ b/compiler/testData/codegen/boxInline/noInline/lambdaAsGeneric.2.kt @@ -0,0 +1,3 @@ +inline fun test(p: T) { + p.toString() +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/noInline/lambdaAsNonFunction.1.kt b/compiler/testData/codegen/boxInline/noInline/lambdaAsNonFunction.1.kt new file mode 100644 index 00000000000..9d86f6ba42d --- /dev/null +++ b/compiler/testData/codegen/boxInline/noInline/lambdaAsNonFunction.1.kt @@ -0,0 +1,5 @@ +fun box() : String { + test {"123"} + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/noInline/lambdaAsNonFunction.2.kt b/compiler/testData/codegen/boxInline/noInline/lambdaAsNonFunction.2.kt new file mode 100644 index 00000000000..eaa2e257641 --- /dev/null +++ b/compiler/testData/codegen/boxInline/noInline/lambdaAsNonFunction.2.kt @@ -0,0 +1,3 @@ +inline fun test(p: Any) { + p.toString() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaAsGeneric.kt b/compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaAsGeneric.kt new file mode 100644 index 00000000000..75114b6c56c --- /dev/null +++ b/compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaAsGeneric.kt @@ -0,0 +1,11 @@ +fun box() : String { + test { + return@box "123" + } + + return "OK" +} + +inline fun test(p: T) { + p.toString() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaAsGeneric.txt b/compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaAsGeneric.txt new file mode 100644 index 00000000000..c7e7f1ca5fd --- /dev/null +++ b/compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaAsGeneric.txt @@ -0,0 +1,4 @@ +package + +internal fun box(): kotlin.String +kotlin.inline() internal fun test(/*0*/ p: T): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaAsNonFunction.kt b/compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaAsNonFunction.kt new file mode 100644 index 00000000000..9d27da6a17e --- /dev/null +++ b/compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaAsNonFunction.kt @@ -0,0 +1,11 @@ +fun box() : String { + test { + return@box "123" + } + + return "OK" +} + +inline fun test(p: Any) { + p.toString() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaAsNonFunction.txt b/compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaAsNonFunction.txt new file mode 100644 index 00000000000..b182828b120 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaAsNonFunction.txt @@ -0,0 +1,4 @@ +package + +internal fun box(): kotlin.String +kotlin.inline() internal fun test(/*0*/ p: kotlin.Any): kotlin.Unit diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index d72e5568fb0..c6d624af324 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -6739,6 +6739,18 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("lambdaAsGeneric.kt") + public void testLambdaAsGeneric() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaAsGeneric.kt"); + doTest(fileName); + } + + @TestMetadata("lambdaAsNonFunction.kt") + public void testLambdaAsNonFunction() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaAsNonFunction.kt"); + doTest(fileName); + } + @TestMetadata("lambdaWithGlobalReturnsInsideOnlyLocalOne.kt") public void testLambdaWithGlobalReturnsInsideOnlyLocalOne() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inline/nonLocalReturns/lambdaWithGlobalReturnsInsideOnlyLocalOne.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxInlineCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxInlineCodegenTestGenerated.java index 0af954db084..c5e10406805 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxInlineCodegenTestGenerated.java @@ -320,6 +320,18 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/noInline"), Pattern.compile("^(.+)\\.1.kt$"), true); } + @TestMetadata("lambdaAsGeneric.1.kt") + public void testLambdaAsGeneric() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/noInline/lambdaAsGeneric.1.kt"); + doTestMultiFileWithInlineCheck(fileName); + } + + @TestMetadata("lambdaAsNonFunction.1.kt") + public void testLambdaAsNonFunction() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/noInline/lambdaAsNonFunction.1.kt"); + doTestMultiFileWithInlineCheck(fileName); + } + @TestMetadata("noInline.1.kt") public void testNoInline() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/noInline/noInline.1.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java index 5ad4f285b79..79b42e1d57a 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java @@ -320,6 +320,18 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/noInline"), Pattern.compile("^(.+)\\.1.kt$"), true); } + @TestMetadata("lambdaAsGeneric.1.kt") + public void testLambdaAsGeneric() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/noInline/lambdaAsGeneric.1.kt"); + doBoxTestWithInlineCheck(fileName); + } + + @TestMetadata("lambdaAsNonFunction.1.kt") + public void testLambdaAsNonFunction() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/noInline/lambdaAsNonFunction.1.kt"); + doBoxTestWithInlineCheck(fileName); + } + @TestMetadata("noInline.1.kt") public void testNoInline() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/noInline/noInline.1.kt"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/InlineUtil.java b/core/descriptors/src/org/jetbrains/kotlin/builtins/InlineUtil.java index 2786c88d2fe..a4e20be15c8 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/InlineUtil.java +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/InlineUtil.java @@ -29,13 +29,21 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.resolve.constants.ArrayValue; import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant; import org.jetbrains.kotlin.resolve.constants.EnumValue; +import org.jetbrains.kotlin.types.JetType; import java.util.List; public class InlineUtil { - public static boolean hasNoinlineAnnotation(@NotNull CallableDescriptor valueParameterDescriptor) { - return KotlinBuiltIns.containsAnnotation(valueParameterDescriptor, KotlinBuiltIns.getNoinlineClassAnnotationFqName()); + public static boolean hasNoinlineAnnotation(@NotNull CallableDescriptor valueParameterOrReceiver) { + return KotlinBuiltIns.containsAnnotation(valueParameterOrReceiver, KotlinBuiltIns.getNoinlineClassAnnotationFqName()); + } + + public static boolean isInlineLambdaParameter(@NotNull CallableDescriptor valueParameterOrReceiver) { + JetType type = valueParameterOrReceiver.getOriginal().getReturnType(); + return !hasNoinlineAnnotation(valueParameterOrReceiver) && + type != null && + KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(type); } @NotNull diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallExpressionTranslator.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallExpressionTranslator.java index 3d7fea7172d..46538fcb112 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallExpressionTranslator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallExpressionTranslator.java @@ -84,7 +84,7 @@ public final class CallExpressionTranslator extends AbstractCallExpressionTransl if (descriptor instanceof ValueParameterDescriptor) { DeclarationDescriptor containingDescriptor = descriptor.getContainingDeclaration(); return InlineUtil.getInlineType(containingDescriptor).isInline() - && !InlineUtil.hasNoinlineAnnotation(descriptor); + && InlineUtil.isInlineLambdaParameter(descriptor); } return false;