[NI] Add extra ordering for ready-for-fixation variables

Helps fixing to more specific type in the following situations:
Type1 <: Var1
Var2 <: Var1
Var2 <: Type2

Type1 and Type2 may also be nullable and non-nullable versions of the same type.
Note that no additional constraints can be inferred from such constraints before fixation.
Resulting types for variables will always Type1 and Type2 may also be nullable and non-nullable versions of the same type.
Fixing Var1 first will make Var2's type more specific while fixing Var2 first
will make Var1's type less specific. The first is preferrable in general.
This commit is contained in:
Pavel Kirpichenkov
2020-09-17 14:39:22 +03:00
parent ec8465859c
commit 896fbbd1a3
6 changed files with 43 additions and 2 deletions
@@ -11965,6 +11965,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt41386.kt");
}
@TestMetadata("kt41394.kt")
public void testKt41394() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt41394.kt");
}
@TestMetadata("kt4420.kt")
public void testKt4420() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt4420.kt");
@@ -42,7 +42,8 @@ class VariableFixationFinder(
WITH_TRIVIAL_OR_NON_PROPER_CONSTRAINTS, // proper trivial constraint from arguments, Nothing <: T
RELATED_TO_ANY_OUTPUT_TYPE,
FROM_INCORPORATION_OF_DECLARED_UPPER_BOUND,
READY_FOR_FIXATION,
READY_FOR_FIXATION_UPPER,
READY_FOR_FIXATION_LOWER,
READY_FOR_FIXATION_REIFIED,
}
@@ -59,7 +60,8 @@ class VariableFixationFinder(
variableHasOnlyIncorporatedConstraintsFromDeclaredUpperBound(variable) ->
TypeVariableFixationReadiness.FROM_INCORPORATION_OF_DECLARED_UPPER_BOUND
isReified(variable) -> TypeVariableFixationReadiness.READY_FOR_FIXATION_REIFIED
else -> TypeVariableFixationReadiness.READY_FOR_FIXATION
!variableHasLowerProperConstraint(variable) -> TypeVariableFixationReadiness.READY_FOR_FIXATION_UPPER
else -> TypeVariableFixationReadiness.READY_FOR_FIXATION_LOWER
}
fun isTypeVariableHasProperConstraint(context: Context, typeVariable: TypeConstructorMarker): Boolean {
@@ -135,6 +137,13 @@ class VariableFixationFinder(
private fun Context.isReified(variable: TypeConstructorMarker): Boolean =
notFixedTypeVariables[variable]?.typeVariable?.let { isReified(it) } ?: false
private fun Context.variableHasLowerProperConstraint(variable: TypeConstructorMarker): Boolean =
notFixedTypeVariables[variable]?.constraints?.let { constraints ->
constraints.any {
it.kind.isLower() && isProperArgumentConstraint(it)
}
} ?: false
}
inline fun TypeSystemInferenceExtensionContext.isProperTypeForFixation(
@@ -0,0 +1,12 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_ANONYMOUS_PARAMETER
// !LANGUAGE: +NewInference
fun <T, VR : T> foo(x: T, fn: (VR?/*T?*/, T) -> Unit) {}
fun takeInt(x: Int) {}
fun main(x: Int) {
foo(x) { prev: Int?, new -> takeInt(new) } // `new` is `Int` in OI, `Int?` in NI
// It seems, `VR` has been fixed to `Int?` instead of `Int`
}
@@ -0,0 +1,5 @@
package
public fun </*0*/ T, /*1*/ VR : T> foo(/*0*/ x: T, /*1*/ fn: (VR?, T) -> kotlin.Unit): kotlin.Unit
public fun main(/*0*/ x: kotlin.Int): kotlin.Unit
public fun takeInt(/*0*/ x: kotlin.Int): kotlin.Unit
@@ -11972,6 +11972,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt41386.kt");
}
@TestMetadata("kt41394.kt")
public void testKt41394() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt41394.kt");
}
@TestMetadata("kt4420.kt")
public void testKt4420() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt4420.kt");
@@ -11967,6 +11967,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt41386.kt");
}
@TestMetadata("kt41394.kt")
public void testKt41394() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt41394.kt");
}
@TestMetadata("kt4420.kt")
public void testKt4420() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt4420.kt");