[NI] Narrow nullability constraint check in incorporator
This commit is a hotfix rather then proper solution.
The source of the issue is that currently type variable fixation result
may change due to fixation order alteration for variables with the same priority.
For instance, having variables V1, V2, and proper types Type1, Type2, such that:
V1 <: Type1
V1 <: V2
Type2 <: V2
both variables will be fixed either to Type1, if V1 will be fixed first,
or to Type2 otherwise.
Since this limitation cannot be easily overcome, the taken approach is to remove
incedental constraint added after 2d5a0546 by restricting nullability constraint check
to `Nothing?` constraints only, thus postponing problematic variable fixation.
To clearify, additional constraint is correct and should cause no harm (in ideal world),
but currently its presence changes fixation order.
So without the restriction the previously used constraint from fixed outer variable
is no longer available by the time problematic variable type is being selected.
^KT-37043 Fixed
This commit is contained in:
Generated
+10
@@ -11345,6 +11345,16 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
|
||||
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt36342_2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt37043.kt")
|
||||
public void testKt37043() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt37043.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt37043_2.kt")
|
||||
public void testKt37043_2() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt37043_2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt4420.kt")
|
||||
public void testKt4420() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt4420.kt");
|
||||
|
||||
+2
@@ -203,6 +203,8 @@ class ConstraintIncorporator(
|
||||
otherConstraint: KotlinTypeMarker,
|
||||
kind: ConstraintKind
|
||||
): Boolean {
|
||||
if (trivialConstraintTypeInferenceOracle.isSuitableResultedType(newConstraint)) return false
|
||||
|
||||
val otherConstraintCanAddNullabilityToNewOne =
|
||||
!newConstraint.isNullableType() && otherConstraint.isNullableType() && kind == ConstraintKind.LOWER
|
||||
val newConstraintCanAddNullabilityToOtherOne =
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -CAST_NEVER_SUCCEEDS -UNUSED_VARIABLE
|
||||
// FILE: Test.java
|
||||
|
||||
class Test {
|
||||
static Number[] flexibleNumbers() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
fun <T> foo(x: Array<out T>): T = x[0]
|
||||
|
||||
inline fun <reified T> materializeArray(): Array<T> = null as Array<T>
|
||||
|
||||
fun main() {
|
||||
val y = foo(Test.flexibleNumbers() ?: materializeArray()) // Any? in NI, Number! in OI (T of `materializeArray` is inferred to Any?)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -CAST_NEVER_SUCCEEDS -UNUSED_VARIABLE
|
||||
// FILE: Test.java
|
||||
|
||||
class Test {
|
||||
static Number[] flexibleNumbers() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
fun <T> foo(x: Array<out T>): T = x[0]
|
||||
|
||||
inline fun <reified T> materializeArray(): Array<T> = null as Array<T>
|
||||
|
||||
fun main() {
|
||||
val y = foo(Test.flexibleNumbers() ?: materializeArray()) // Any? in NI, Number! in OI (T of `materializeArray` is inferred to Any?)
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package
|
||||
|
||||
public fun </*0*/ T> foo(/*0*/ x: kotlin.Array<out T>): T
|
||||
public fun main(): kotlin.Unit
|
||||
public inline fun </*0*/ reified T> materializeArray(): kotlin.Array<T>
|
||||
|
||||
public/*package*/ open class Test {
|
||||
public/*package*/ constructor Test()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
// Static members
|
||||
public/*package*/ open fun flexibleNumbers(): kotlin.Array<(out) kotlin.Number!>!
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -USELESS_ELVIS
|
||||
|
||||
fun <T> first(x: Array<out T>): T = TODO()
|
||||
fun <E> elvis(first: E?, second: E): E = TODO()
|
||||
|
||||
inline fun <reified M> materializeArray(): Array<M> = TODO()
|
||||
|
||||
fun nullableNumbers(): Array<Number?> = TODO()
|
||||
fun notNullableNumbers(): Array<Number> = TODO()
|
||||
fun nullableNumbersNullableArray(): Array<Number?>? = TODO()
|
||||
fun notNullableNumbersNullableArray(): Array<Number>? = TODO()
|
||||
|
||||
fun main() {
|
||||
val number1 = first(elvis(notNullableNumbers(), materializeArray()))
|
||||
val number2 = first(elvis(notNullableNumbersNullableArray(), materializeArray()))
|
||||
val number3 = first(notNullableNumbers() ?: materializeArray())
|
||||
val number4 = first(notNullableNumbersNullableArray() ?: materializeArray())
|
||||
val nullableNumber1 = first(elvis(nullableNumbers(), materializeArray()))
|
||||
val nullableNumber2 = first(elvis(nullableNumbersNullableArray(), materializeArray()))
|
||||
val nullableNumber3 = first(nullableNumbers() ?: materializeArray())
|
||||
val nullableNumber4 = first(nullableNumbersNullableArray() ?: materializeArray())
|
||||
|
||||
number1
|
||||
number2
|
||||
number3
|
||||
number4
|
||||
nullableNumber1
|
||||
nullableNumber2
|
||||
nullableNumber3
|
||||
nullableNumber4
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -USELESS_ELVIS
|
||||
|
||||
fun <T> first(x: Array<out T>): T = TODO()
|
||||
fun <E> elvis(first: E?, second: E): E = TODO()
|
||||
|
||||
inline fun <reified M> materializeArray(): Array<M> = TODO()
|
||||
|
||||
fun nullableNumbers(): Array<Number?> = TODO()
|
||||
fun notNullableNumbers(): Array<Number> = TODO()
|
||||
fun nullableNumbersNullableArray(): Array<Number?>? = TODO()
|
||||
fun notNullableNumbersNullableArray(): Array<Number>? = TODO()
|
||||
|
||||
fun main() {
|
||||
val number1 = first(elvis(notNullableNumbers(), materializeArray()))
|
||||
val number2 = first(elvis(notNullableNumbersNullableArray(), materializeArray()))
|
||||
val number3 = first(notNullableNumbers() ?: materializeArray())
|
||||
val number4 = first(notNullableNumbersNullableArray() ?: materializeArray())
|
||||
val nullableNumber1 = first(elvis(nullableNumbers(), materializeArray()))
|
||||
val nullableNumber2 = first(elvis(nullableNumbersNullableArray(), materializeArray()))
|
||||
val nullableNumber3 = first(nullableNumbers() ?: materializeArray())
|
||||
val nullableNumber4 = first(nullableNumbersNullableArray() ?: materializeArray())
|
||||
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>number1<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>number2<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>number3<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>number4<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number?")!>nullableNumber1<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number?")!>nullableNumber2<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number?")!>nullableNumber3<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number?")!>nullableNumber4<!>
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package
|
||||
|
||||
public fun </*0*/ E> elvis(/*0*/ first: E?, /*1*/ second: E): E
|
||||
public fun </*0*/ T> first(/*0*/ x: kotlin.Array<out T>): T
|
||||
public fun main(): kotlin.Unit
|
||||
public inline fun </*0*/ reified M> materializeArray(): kotlin.Array<M>
|
||||
public fun notNullableNumbers(): kotlin.Array<kotlin.Number>
|
||||
public fun notNullableNumbersNullableArray(): kotlin.Array<kotlin.Number>?
|
||||
public fun nullableNumbers(): kotlin.Array<kotlin.Number?>
|
||||
public fun nullableNumbersNullableArray(): kotlin.Array<kotlin.Number?>?
|
||||
+1
-1
@@ -14,5 +14,5 @@ public class Matcher<T> {
|
||||
|
||||
// FILE: main.kt
|
||||
fun test(x: List<String>) {
|
||||
Assert.<!INAPPLICABLE_CANDIDATE!>assertThat<!>(x, Matcher.hasItem("abc"))
|
||||
Assert.assertThat(x, Matcher.hasItem("abc"))
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
// NI_EXPECTED_FILE
|
||||
|
||||
fun foo(first: Array<Any?>, second: Array<Any?>) = Pair(first.toCollection(<!NO_VALUE_FOR_PARAMETER!>)<!>, second.toCollection(<!NO_VALUE_FOR_PARAMETER!>)<!>)
|
||||
fun foo(first: Array<Any?>, second: Array<Any?>) = <!NI;NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Pair<!>(first.<!NI;NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>toCollection<!>(<!NO_VALUE_FOR_PARAMETER!>)<!>, second.<!NI;NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>toCollection<!>(<!NO_VALUE_FOR_PARAMETER!>)<!>)
|
||||
@@ -1,3 +1,3 @@
|
||||
package
|
||||
|
||||
public fun foo(/*0*/ first: kotlin.Array<kotlin.Any?>, /*1*/ second: kotlin.Array<kotlin.Any?>): kotlin.Pair<kotlin.collections.MutableCollection<in kotlin.Any?>, kotlin.collections.MutableCollection<in kotlin.Any?>>
|
||||
public fun foo(/*0*/ first: kotlin.Array<kotlin.Any?>, /*1*/ second: kotlin.Array<kotlin.Any?>): [ERROR : Error function type]
|
||||
|
||||
@@ -11352,6 +11352,16 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali
|
||||
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt36342_2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt37043.kt")
|
||||
public void testKt37043() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt37043.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt37043_2.kt")
|
||||
public void testKt37043_2() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt37043_2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt4420.kt")
|
||||
public void testKt4420() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt4420.kt");
|
||||
|
||||
Generated
+10
@@ -11347,6 +11347,16 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt36342_2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt37043.kt")
|
||||
public void testKt37043() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt37043.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt37043_2.kt")
|
||||
public void testKt37043_2() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt37043_2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt4420.kt")
|
||||
public void testKt4420() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt4420.kt");
|
||||
|
||||
Reference in New Issue
Block a user