diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt index a90465c8794..03c48a2620a 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt @@ -38,6 +38,8 @@ class ResultTypeResolver( fun findResultType(c: Context, variableWithConstraints: VariableWithConstraints, direction: ResolveDirection): UnwrappedType? { findResultIfThereIsEqualsConstraint(c, variableWithConstraints, allowedFixToNotProperType = false)?.let { return it } + val builtIns = variableWithConstraints.typeVariable.freshTypeConstructor.builtIns + if (direction == ResolveDirection.TO_SUBTYPE || direction == ResolveDirection.UNKNOWN) { val lowerConstraints = variableWithConstraints.constraints.filter { it.kind == ConstraintKind.LOWER && c.isProperType(it.type) } if (lowerConstraints.isNotEmpty()) { @@ -64,6 +66,8 @@ class ResultTypeResolver( } } + if (direction == ResolveDirection.TO_SUBTYPE) return builtIns.nothingType + // direction == TO_SUPER or there is no LOWER bounds val upperConstraints = variableWithConstraints.constraints.filter { it.kind == ConstraintKind.UPPER && c.isProperType(it.type) } if (upperConstraints.isNotEmpty()) { @@ -72,7 +76,7 @@ class ResultTypeResolver( return typeApproximator.approximateToSubType(upperType, TypeApproximatorConfiguration.CapturedTypesApproximation) ?: upperType } - return null + return return builtIns.anyType } fun findResultIfThereIsEqualsConstraint( diff --git a/compiler/testData/diagnostics/tests/inference/fixVariableToNothing.kt b/compiler/testData/diagnostics/tests/inference/fixVariableToNothing.kt new file mode 100644 index 00000000000..4930e689c7e --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/fixVariableToNothing.kt @@ -0,0 +1,15 @@ + +// completion order here: X, Y, WHEN_VARIABLE +fun List.optimizeReadOnlyList() = when (size) { + 0 -> emptyList() // here type variable Y will be fixed to Nothing + 1 -> listOf(this[0]) + else -> this +} +fun listOf(element: X): List = TODO() +fun emptyList(): List = TODO() + + +fun test(l: List): List { + val foo = l.optimizeReadOnlyList() + return foo +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/fixVariableToNothing.txt b/compiler/testData/diagnostics/tests/inference/fixVariableToNothing.txt new file mode 100644 index 00000000000..18f314a76f0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/fixVariableToNothing.txt @@ -0,0 +1,6 @@ +package + +public fun emptyList(): kotlin.collections.List +public fun listOf(/*0*/ element: X): kotlin.collections.List +public fun test(/*0*/ l: kotlin.collections.List): kotlin.collections.List +public fun kotlin.collections.List.optimizeReadOnlyList(): kotlin.collections.List diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 69341ee0e7c..e5e8cbcacbf 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -10048,6 +10048,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("fixVariableToNothing.kt") + public void testFixVariableToNothing() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/fixVariableToNothing.kt"); + doTest(fileName); + } + @TestMetadata("flexibleTypesAsUpperBound.kt") public void testFlexibleTypesAsUpperBound() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/flexibleTypesAsUpperBound.kt");