[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
This commit is contained in:
+7
-4
@@ -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.NewConstraintSystem
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter
|
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.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.ConstraintStorage.Empty.hasContradiction
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ExpectedTypeConstraintPosition
|
import org.jetbrains.kotlin.resolve.calls.inference.model.ExpectedTypeConstraintPosition
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||||
@@ -21,7 +22,8 @@ import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType
|
|||||||
|
|
||||||
class KotlinCallCompleter(
|
class KotlinCallCompleter(
|
||||||
private val postponedArgumentsAnalyzer: PostponedArgumentsAnalyzer,
|
private val postponedArgumentsAnalyzer: PostponedArgumentsAnalyzer,
|
||||||
private val kotlinConstraintSystemCompleter: KotlinConstraintSystemCompleter
|
private val kotlinConstraintSystemCompleter: KotlinConstraintSystemCompleter,
|
||||||
|
private val trivialConstraintTypeInferenceOracle: TrivialConstraintTypeInferenceOracle
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun runCompletion(
|
fun runCompletion(
|
||||||
@@ -172,7 +174,7 @@ class KotlinCallCompleter(
|
|||||||
// This means that there will be no new LOWER constraints =>
|
// This means that there will be no new LOWER constraints =>
|
||||||
// it's possible to complete call now if there are proper LOWER constraints
|
// it's possible to complete call now if there are proper LOWER constraints
|
||||||
csBuilder.isTypeVariable(currentReturnType) ->
|
csBuilder.isTypeVariable(currentReturnType) ->
|
||||||
if (hasProperLowerConstraints(currentReturnType))
|
if (hasProperNonTrivialLowerConstraints(currentReturnType))
|
||||||
ConstraintSystemCompletionMode.FULL
|
ConstraintSystemCompletionMode.FULL
|
||||||
else
|
else
|
||||||
ConstraintSystemCompletionMode.PARTIAL
|
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" }
|
assert(csBuilder.isTypeVariable(typeVariable)) { "$typeVariable is not a type variable" }
|
||||||
|
|
||||||
val constructor = typeVariable.constructor
|
val constructor = typeVariable.constructor
|
||||||
val variableWithConstraints = csBuilder.currentStorage().notFixedTypeVariables[constructor] ?: return false
|
val variableWithConstraints = csBuilder.currentStorage().notFixedTypeVariables[constructor] ?: return false
|
||||||
return variableWithConstraints.constraints.any {
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
// !LANGUAGE: +NewInference
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
inline fun <T> foo(f: () -> T): String {
|
||||||
|
return (f() as? Inv<T>)?.result() ?: "Bad"
|
||||||
|
}
|
||||||
|
|
||||||
|
class Inv<T> {
|
||||||
|
fun result(): String = "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <K> create(): Inv<K> = Inv()
|
||||||
|
|
||||||
|
fun test(b: Boolean): String {
|
||||||
|
return foo {
|
||||||
|
if (!b) {
|
||||||
|
return@foo create<String>()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b) {
|
||||||
|
create()
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return test(true)
|
||||||
|
}
|
||||||
+5
@@ -11834,6 +11834,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
public void testKt10822() throws Exception {
|
public void testKt10822() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inference/kt10822.kt");
|
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")
|
@TestMetadata("compiler/testData/codegen/box/inlineClasses")
|
||||||
|
|||||||
+5
@@ -11834,6 +11834,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
public void testKt10822() throws Exception {
|
public void testKt10822() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inference/kt10822.kt");
|
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")
|
@TestMetadata("compiler/testData/codegen/box/inlineClasses")
|
||||||
|
|||||||
+5
@@ -11839,6 +11839,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
public void testKt10822() throws Exception {
|
public void testKt10822() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inference/kt10822.kt");
|
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")
|
@TestMetadata("compiler/testData/codegen/box/inlineClasses")
|
||||||
|
|||||||
+5
@@ -9419,6 +9419,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
public void testKt10822() throws Exception {
|
public void testKt10822() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inference/kt10822.kt");
|
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")
|
@TestMetadata("compiler/testData/codegen/box/inlineClasses")
|
||||||
|
|||||||
+5
@@ -10514,6 +10514,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
public void testKt10822() throws Exception {
|
public void testKt10822() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inference/kt10822.kt");
|
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")
|
@TestMetadata("compiler/testData/codegen/box/inlineClasses")
|
||||||
|
|||||||
Reference in New Issue
Block a user