From 1594c1fc6b8543c83bd5db986c4a44614377caa2 Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Mon, 11 Mar 2019 13:55:07 +0300 Subject: [PATCH] [NI] Don't consider `Nothing`-constraint as proper to complete call Follow-up of 9b3e17f0. There we decided to complete call if a type variable from a return type has proper lower constraints, now we refine this rule wrt `Nothing`-like constraints to avoid inferring type variables to Nothing, which is quite useless #KT-30370 Fixed --- .../calls/components/KotlinCallCompleter.kt | 11 ++++--- ...ExpressionOfLambdaWithNothingConstraint.kt | 30 +++++++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 5 ++++ .../LightAnalysisModeTestGenerated.java | 5 ++++ .../ir/IrBlackBoxCodegenTestGenerated.java | 5 ++++ .../IrJsCodegenBoxTestGenerated.java | 5 ++++ .../semantics/JsCodegenBoxTestGenerated.java | 5 ++++ 7 files changed, 62 insertions(+), 4 deletions(-) create mode 100644 compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt index f31e7a8f18b..fba2d8bfa20 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.resolve.calls.components import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode +import org.jetbrains.kotlin.resolve.calls.inference.components.TrivialConstraintTypeInferenceOracle import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage.Empty.hasContradiction import org.jetbrains.kotlin.resolve.calls.inference.model.ExpectedTypeConstraintPosition import org.jetbrains.kotlin.resolve.calls.model.* @@ -21,7 +22,8 @@ import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType class KotlinCallCompleter( private val postponedArgumentsAnalyzer: PostponedArgumentsAnalyzer, - private val kotlinConstraintSystemCompleter: KotlinConstraintSystemCompleter + private val kotlinConstraintSystemCompleter: KotlinConstraintSystemCompleter, + private val trivialConstraintTypeInferenceOracle: TrivialConstraintTypeInferenceOracle ) { fun runCompletion( @@ -172,7 +174,7 @@ class KotlinCallCompleter( // This means that there will be no new LOWER constraints => // it's possible to complete call now if there are proper LOWER constraints csBuilder.isTypeVariable(currentReturnType) -> - if (hasProperLowerConstraints(currentReturnType)) + if (hasProperNonTrivialLowerConstraints(currentReturnType)) ConstraintSystemCompletionMode.FULL else ConstraintSystemCompletionMode.PARTIAL @@ -181,13 +183,14 @@ class KotlinCallCompleter( } } - private fun KotlinResolutionCandidate.hasProperLowerConstraints(typeVariable: UnwrappedType): Boolean { + private fun KotlinResolutionCandidate.hasProperNonTrivialLowerConstraints(typeVariable: UnwrappedType): Boolean { assert(csBuilder.isTypeVariable(typeVariable)) { "$typeVariable is not a type variable" } val constructor = typeVariable.constructor val variableWithConstraints = csBuilder.currentStorage().notFixedTypeVariables[constructor] ?: return false return variableWithConstraints.constraints.any { - it.kind.isLower() && csBuilder.isProperType(it.type) && !it.type.isIntegerValueType() + !trivialConstraintTypeInferenceOracle.isTrivialConstraint(it) && !it.type.isIntegerValueType() && + it.kind.isLower() && csBuilder.isProperType(it.type) } } diff --git a/compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt b/compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt new file mode 100644 index 00000000000..dba54837117 --- /dev/null +++ b/compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt @@ -0,0 +1,30 @@ +// !LANGUAGE: +NewInference +// WITH_RUNTIME + +inline fun foo(f: () -> T): String { + return (f() as? Inv)?.result() ?: "Bad" +} + +class Inv { + fun result(): String = "OK" +} + +fun create(): Inv = Inv() + +fun test(b: Boolean): String { + return foo { + if (!b) { + return@foo create() + } + + if (b) { + create() + } else { + null + } + } +} + +fun box(): String { + return test(true) +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index cce3b97c3c3..37d6cfa6452 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -11834,6 +11834,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { public void testKt10822() throws Exception { runTest("compiler/testData/codegen/box/inference/kt10822.kt"); } + + @TestMetadata("lastExpressionOfLambdaWithNothingConstraint.kt") + public void testLastExpressionOfLambdaWithNothingConstraint() throws Exception { + runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt"); + } } @TestMetadata("compiler/testData/codegen/box/inlineClasses") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 73ee5b60117..a9e0ccf4e71 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -11834,6 +11834,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes public void testKt10822() throws Exception { runTest("compiler/testData/codegen/box/inference/kt10822.kt"); } + + @TestMetadata("lastExpressionOfLambdaWithNothingConstraint.kt") + public void testLastExpressionOfLambdaWithNothingConstraint() throws Exception { + runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt"); + } } @TestMetadata("compiler/testData/codegen/box/inlineClasses") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index b0235dbdf88..6a1f8139a2f 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -11839,6 +11839,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes public void testKt10822() throws Exception { runTest("compiler/testData/codegen/box/inference/kt10822.kt"); } + + @TestMetadata("lastExpressionOfLambdaWithNothingConstraint.kt") + public void testLastExpressionOfLambdaWithNothingConstraint() throws Exception { + runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt"); + } } @TestMetadata("compiler/testData/codegen/box/inlineClasses") diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java index a9e291e83ca..1ee49f4f6be 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java @@ -9419,6 +9419,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { public void testKt10822() throws Exception { runTest("compiler/testData/codegen/box/inference/kt10822.kt"); } + + @TestMetadata("lastExpressionOfLambdaWithNothingConstraint.kt") + public void testLastExpressionOfLambdaWithNothingConstraint() throws Exception { + runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt"); + } } @TestMetadata("compiler/testData/codegen/box/inlineClasses") diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 0ae6d333b4a..b0039ccada7 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -10514,6 +10514,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { public void testKt10822() throws Exception { runTest("compiler/testData/codegen/box/inference/kt10822.kt"); } + + @TestMetadata("lastExpressionOfLambdaWithNothingConstraint.kt") + public void testLastExpressionOfLambdaWithNothingConstraint() throws Exception { + runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt"); + } } @TestMetadata("compiler/testData/codegen/box/inlineClasses")