From ab7e3ce78c2861ec200776cb626a5fe0ac5a6e90 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Thu, 10 Oct 2013 15:25:10 +0400 Subject: [PATCH] interpret block with function literal as function literal (temporary) --- .../resolve/calls/ArgumentTypeResolver.java | 35 +++++++++++++++++-- .../lang/resolve/calls/CandidateResolver.java | 6 ++-- .../functionLIteralInBlockInIf.kt | 11 ++++++ .../checkers/JetDiagnosticsTestGenerated.java | 5 +++ 4 files changed, 51 insertions(+), 6 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/functionLiterals/functionLIteralInBlockInIf.kt diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ArgumentTypeResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ArgumentTypeResolver.java index 6f13e67e66a..f06d8262e10 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ArgumentTypeResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ArgumentTypeResolver.java @@ -165,6 +165,36 @@ public class ArgumentTypeResolver { } } + public static boolean isFunctionLiteralArgument(@NotNull JetExpression expression) { + return getFunctionLiteralArgumentIfAny(expression) != null; + } + + @NotNull + public static JetFunctionLiteralExpression getFunctionLiteralArgument(@NotNull JetExpression expression) { + assert isFunctionLiteralArgument(expression); + //noinspection ConstantConditions + return getFunctionLiteralArgumentIfAny(expression); + } + + @Nullable + private static JetFunctionLiteralExpression getFunctionLiteralArgumentIfAny(@NotNull JetExpression expression) { + JetExpression deparenthesizedExpression = JetPsiUtil.deparenthesize(expression, false); + if (deparenthesizedExpression instanceof JetBlockExpression) { + // todo + // This case is a temporary hack for 'if' branches. + // The right way to implement this logic is to interpret 'if' branches as function literals with explicitly-typed signatures + // (no arguments and no receiver) and therefore analyze them straight away (not in the 'complete' phase). + JetElement lastStatementInABlock = JetPsiUtil.getLastStatementInABlock((JetBlockExpression) deparenthesizedExpression); + if (lastStatementInABlock instanceof JetExpression) { + deparenthesizedExpression = JetPsiUtil.deparenthesize((JetExpression) lastStatementInABlock, false); + } + } + if (deparenthesizedExpression instanceof JetFunctionLiteralExpression) { + return (JetFunctionLiteralExpression) deparenthesizedExpression; + } + return null; + } + @NotNull public JetTypeInfo getArgumentTypeInfo( @Nullable JetExpression expression, @@ -174,9 +204,8 @@ public class ArgumentTypeResolver { if (expression == null) { return JetTypeInfo.create(null, context.dataFlowInfo); } - JetExpression deparenthesizedExpression = JetPsiUtil.deparenthesize(expression, false); - if (deparenthesizedExpression instanceof JetFunctionLiteralExpression) { - return getFunctionLiteralTypeInfo(expression, (JetFunctionLiteralExpression) deparenthesizedExpression, context, resolveArgumentsMode); + if (isFunctionLiteralArgument(expression)) { + return getFunctionLiteralTypeInfo(expression, getFunctionLiteralArgument(expression), context, resolveArgumentsMode); } JetTypeInfo recordedTypeInfo = getRecordedTypeInfo(expression, context.trace.getBindingContext()); if (recordedTypeInfo != null) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java index 941952349e8..c77636da836 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java @@ -470,9 +470,9 @@ public class CandidateResolver { ) { JetExpression argumentExpression = valueArgument.getArgumentExpression(); if (argumentExpression == null) return; - JetExpression deparenthesizedExpression = JetPsiUtil.deparenthesize(argumentExpression, false); - if (!(deparenthesizedExpression instanceof JetFunctionLiteralExpression)) return; - JetFunctionLiteralExpression functionLiteralExpression = (JetFunctionLiteralExpression) deparenthesizedExpression; + if (!ArgumentTypeResolver.isFunctionLiteralArgument(argumentExpression)) return; + + JetFunctionLiteralExpression functionLiteralExpression = ArgumentTypeResolver.getFunctionLiteralArgument(argumentExpression); JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument); JetType expectedType = constraintSystem.getCurrentSubstitutor().substitute(effectiveExpectedType, Variance.INVARIANT); diff --git a/compiler/testData/diagnostics/tests/functionLiterals/functionLIteralInBlockInIf.kt b/compiler/testData/diagnostics/tests/functionLiterals/functionLIteralInBlockInIf.kt new file mode 100644 index 00000000000..4133a0318bb --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionLiterals/functionLIteralInBlockInIf.kt @@ -0,0 +1,11 @@ +fun test() { + val a = if (true) { + val x = 1 + ({ x }) + } else { + { 2 } + } + TypeOf(a): TypeOf> +} + +class TypeOf(t: T) \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index cf33fd156f7..30ccef1a6d1 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -2710,6 +2710,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/functionLiterals/ExpectedParametersTypesMismatch.kt"); } + @TestMetadata("functionLIteralInBlockInIf.kt") + public void testFunctionLIteralInBlockInIf() throws Exception { + doTest("compiler/testData/diagnostics/tests/functionLiterals/functionLIteralInBlockInIf.kt"); + } + @TestMetadata("kt2906.kt") public void testKt2906() throws Exception { doTest("compiler/testData/diagnostics/tests/functionLiterals/kt2906.kt");