From fe34d1673eb76b36033279b8d5be6d997cf317b2 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Fri, 4 Sep 2015 16:23:00 +0300 Subject: [PATCH] Exception 'Base expression was not processed: function literal' fixed --- .../org/jetbrains/kotlin/diagnostics/Errors.java | 2 ++ .../rendering/DefaultErrorMessages.java | 2 ++ .../expressions/BasicExpressionTypingVisitor.java | 14 ++++++++++++++ .../expressions/ControlStructureTypingUtils.java | 3 ++- .../lambdasInExclExclAndElvis.kt | 15 +++++++++++++++ .../lambdasInExclExclAndElvis.txt | 4 ++++ .../checkers/JetDiagnosticsTestGenerated.java | 6 ++++++ 7 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/diagnostics/tests/controlStructures/lambdasInExclExclAndElvis.kt create mode 100644 compiler/testData/diagnostics/tests/controlStructures/lambdasInExclExclAndElvis.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 3b3af024656..d568c668809 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -551,8 +551,10 @@ public interface Errors { DiagnosticFactory3 UNSAFE_INFIX_CALL = DiagnosticFactory3.create(ERROR); DiagnosticFactory1 UNNECESSARY_SAFE_CALL = DiagnosticFactory1.create(WARNING); DiagnosticFactory1 UNNECESSARY_NOT_NULL_ASSERTION = DiagnosticFactory1.create(WARNING); + DiagnosticFactory0 NOT_NULL_ASSERTION_ON_FUNCTION_LITERAL = DiagnosticFactory0.create(WARNING); DiagnosticFactory1 USELESS_ELVIS = DiagnosticFactory1.create(WARNING, PositioningStrategies.USELESS_ELVIS); + DiagnosticFactory0 USELESS_ELVIS_ON_FUNCTION_LITERAL = DiagnosticFactory0.create(WARNING); // Compile-time values diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 3bb9a1acb82..d93c69fc59b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -376,6 +376,7 @@ public class DefaultErrorMessages { MAP.put(FINAL_UPPER_BOUND, "''{0}'' is a final type, and thus a value of the type parameter is predetermined", RENDER_TYPE); MAP.put(DYNAMIC_UPPER_BOUND, "Dynamic type can not be used as an upper bound"); MAP.put(USELESS_ELVIS, "Elvis operator (?:) always returns the left operand of non-nullable type {0}", RENDER_TYPE); + MAP.put(USELESS_ELVIS_ON_FUNCTION_LITERAL, "Left operand of elvis operator (?:) is function literal"); MAP.put(CONFLICTING_UPPER_BOUNDS, "Upper bounds of {0} have empty intersection", NAME); MAP.put(TOO_MANY_ARGUMENTS, "Too many arguments for {0}", FQ_NAMES_IN_TYPES); @@ -447,6 +448,7 @@ public class DefaultErrorMessages { MAP.put(EXCEPTION_FROM_ANALYZER, "Internal Error occurred while analyzing this expression:\n{0}", THROWABLE); MAP.put(UNNECESSARY_SAFE_CALL, "Unnecessary safe call on a non-null receiver of type {0}", RENDER_TYPE); MAP.put(UNNECESSARY_NOT_NULL_ASSERTION, "Unnecessary non-null assertion (!!) on a non-null receiver of type {0}", RENDER_TYPE); + MAP.put(NOT_NULL_ASSERTION_ON_FUNCTION_LITERAL, "Non-null assertion (!!) is called on function literal"); MAP.put(NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER, "{0} does not refer to a type parameter of {1}", new Renderer() { @NotNull @Override diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java index 057354d9e6c..3dc5b5e7596 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java @@ -36,6 +36,7 @@ import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.*; import org.jetbrains.kotlin.resolve.callableReferences.CallableReferencesPackage; +import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver; import org.jetbrains.kotlin.resolve.calls.CallExpressionResolver; import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker; import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext; @@ -826,6 +827,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { components.controlStructureTypingUtils.resolveSpecialConstructionAsCall( call, "ExclExcl", Collections.singletonList("baseExpr"), Collections.singletonList(true), context, null); JetTypeInfo baseTypeInfo = BindingContextUtils.getRecordedTypeInfo(baseExpression, context.trace.getBindingContext()); + + if (ArgumentTypeResolver.isFunctionLiteralArgument(baseExpression, context)) { + context.trace.report(NOT_NULL_ASSERTION_ON_FUNCTION_LITERAL.on(operationSign)); + return baseTypeInfo; + } assert baseTypeInfo != null : "Base expression was not processed: " + expression; JetType baseType = baseTypeInfo.getType(); if (baseType == null) { @@ -1149,12 +1155,20 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { ResolvedCall resolvedCall = components.controlStructureTypingUtils.resolveSpecialConstructionAsCall( call, "Elvis", Lists.newArrayList("left", "right"), Lists.newArrayList(true, false), contextWithExpectedType, null); JetTypeInfo leftTypeInfo = BindingContextUtils.getRecordedTypeInfo(left, context.trace.getBindingContext()); + if (ArgumentTypeResolver.isFunctionLiteralArgument(left, context)) { + context.trace.report(USELESS_ELVIS_ON_FUNCTION_LITERAL.on(expression.getOperationReference())); + if (leftTypeInfo == null) return TypeInfoFactoryPackage.noTypeInfo(context); + } assert leftTypeInfo != null : "Left expression was not processed: " + expression; JetType leftType = leftTypeInfo.getType(); if (leftType != null && isKnownToBeNotNull(left, leftType, context)) { context.trace.report(USELESS_ELVIS.on(expression, leftType)); } JetTypeInfo rightTypeInfo = BindingContextUtils.getRecordedTypeInfo(right, context.trace.getBindingContext()); + if (rightTypeInfo == null && ArgumentTypeResolver.isFunctionLiteralArgument(right, context)) { + // the type is computed later in call completer according to the '?:' semantics as a function + return TypeInfoFactoryPackage.noTypeInfo(context); + } assert rightTypeInfo != null : "Right expression was not processed: " + expression; boolean loopBreakContinuePossible = leftTypeInfo.getJumpOutPossible() || rightTypeInfo.getJumpOutPossible(); JetType rightType = rightTypeInfo.getType(); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingUtils.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingUtils.java index 143a6954f02..d83d0af1ef2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingUtils.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingUtils.java @@ -380,7 +380,8 @@ public class ControlStructureTypingUtils { return; } JetExpression expression = (JetExpression) call.getCallElement(); - if (status.hasOnlyErrorsDerivedFrom(EXPECTED_TYPE_POSITION) || status.hasConflictingConstraints()) { + if (status.hasOnlyErrorsDerivedFrom(EXPECTED_TYPE_POSITION) || status.hasConflictingConstraints() + || status.hasTypeInferenceIncorporationError()) { // todo after KT-... remove this line expression.accept(checkTypeVisitor, new CheckTypeContext(trace, data.expectedType)); return; } diff --git a/compiler/testData/diagnostics/tests/controlStructures/lambdasInExclExclAndElvis.kt b/compiler/testData/diagnostics/tests/controlStructures/lambdasInExclExclAndElvis.kt new file mode 100644 index 00000000000..d33b0cecc2b --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlStructures/lambdasInExclExclAndElvis.kt @@ -0,0 +1,15 @@ +// !DIAGNOSTICS: -UNUSED_EXPRESSION + +fun use(a: Any?) = a + +fun test() { + { }!! + use({ }!!); + + // KT-KT-9070 + { } ?: 1 + use({ 2 } ?: 1); + + 1 ?: { } + use(1 ?: { }) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlStructures/lambdasInExclExclAndElvis.txt b/compiler/testData/diagnostics/tests/controlStructures/lambdasInExclExclAndElvis.txt new file mode 100644 index 00000000000..c0a06c8aed1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlStructures/lambdasInExclExclAndElvis.txt @@ -0,0 +1,4 @@ +package + +internal fun test(): kotlin.Unit +internal fun use(/*0*/ a: kotlin.Any?): kotlin.Any? diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 0f407175ef2..8d40193c90f 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -3114,6 +3114,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("lambdasInExclExclAndElvis.kt") + public void testLambdasInExclExclAndElvis() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlStructures/lambdasInExclExclAndElvis.kt"); + doTest(fileName); + } + @TestMetadata("tryReturnType.kt") public void testTryReturnType() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlStructures/tryReturnType.kt");