NI: Prefer nullable lower bound to flexible one when substitution of type variable is performed

^KT-32435 Fixed
This commit is contained in:
Victor Petukhov
2019-12-07 20:24:53 +03:00
committed by victor.petukhov
parent 78dfcef160
commit 09c2b92b1d
14 changed files with 187 additions and 4 deletions
@@ -20,7 +20,7 @@ interface PsiMethod {
interface PsiClass
fun test() {
val processor = AdapterProcessor<PsiMethod, PsiClass>(
val processor = AdapterProcessor<PsiMethod, PsiClass?>(
Function { method: PsiMethod? -> method?.containingClass }
)
}
@@ -7,7 +7,7 @@ FILE: main.kt
public abstract interface PsiClass : R|kotlin/Any| {
}
public final fun test(): R|kotlin/Unit| {
lval processor: R|AdapterProcessor<PsiMethod, PsiClass>| = R|/AdapterProcessor.AdapterProcessor|<R|PsiMethod|, R|PsiClass|>(R|/Function|<R|PsiMethod|, R|ft<PsiClass, PsiClass?>!|>(<L> = Function@fun <anonymous>(method: R|PsiMethod?|): R|PsiClass?| {
lval processor: R|AdapterProcessor<PsiMethod, PsiClass?>| = R|/AdapterProcessor.AdapterProcessor|<R|PsiMethod|, R|PsiClass?|>(R|/Function|<R|PsiMethod|, R|PsiClass?|>(<L> = Function@fun <anonymous>(method: R|PsiMethod?|): R|PsiClass?| {
R|<local>/method|?.R|/PsiMethod.containingClass|
}
))
@@ -14635,6 +14635,11 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok
runTest("compiler/testData/diagnostics/tests/nullableTypes/elvisOnUnit.kt");
}
@TestMetadata("inferenceFlexibleTToNullable.kt")
public void testInferenceFlexibleTToNullable() throws Exception {
runTest("compiler/testData/diagnostics/tests/nullableTypes/inferenceFlexibleTToNullable.kt");
}
@TestMetadata("nullAssertOnTypeWithNullableUpperBound.kt")
public void testNullAssertOnTypeWithNullableUpperBound() throws Exception {
runTest("compiler/testData/diagnostics/tests/nullableTypes/nullAssertOnTypeWithNullableUpperBound.kt");
@@ -136,7 +136,7 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
*
* => Foo <: T! -- (Foo!! .. Foo) <: T
*
* Foo? <: T! -- (Foo!! .. Foo?) <: T
* Foo? <: T! -- Foo? <: T
*
*
* (Foo..Bar) <: T! --
@@ -163,7 +163,11 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
when (subType) {
is SimpleTypeMarker ->
// Foo <: T! -- (Foo!! .. Foo) <: T
createFlexibleType(subType.makeSimpleTypeDefinitelyNotNullOrNotNull(), subType)
if (subType.isNullableType()) {
subType // prefer nullable type to flexible one: `Foo? <: (T..T?)` => lowerConstraint = `Foo?`
} else {
createFlexibleType(subType.makeSimpleTypeDefinitelyNotNullOrNotNull(), subType)
}
is FlexibleTypeMarker ->
// (Foo..Bar) <: T! -- (Foo!! .. Bar) <: T
@@ -0,0 +1,71 @@
// !LANGUAGE: +NewInference
// FILE: Foo.java
import org.jetbrains.annotations.NotNull;
public class Foo<T> {
T x;
public Foo(T x) {
this.x = x;
}
public static Number bar() { return null; }
public static <K> K simpleId(K k) {
return k;
}
public T produceT() {
return x;
}
@NotNull
public T produceNotNullT() {
return x;
}
public void consumeT(T x) {}
}
// FILE: main.kt
fun <T> bar(n: Number?, d: T, e: T) {
val b: Number? = Foo.simpleId(n)
b?.toInt()
val c = Foo.simpleId(n)
c?.toInt()
val x4 = Foo(if (true) 10 else null)
val x6: Number? = x4.produceT()
x6?.toInt()
val x7 = x4.produceT()
x7?.toInt()
val x8 = x4.produceNotNullT()
x8.toInt()
x4.consumeT(x7)
val x9: T = Foo.simpleId(d)
val x10: T? = Foo.simpleId(d)
if (e != null) {
var x11 = e
x11 = Foo.simpleId(d) // assign to definitely not-null T, the lack an error is consistent with old inference
}
var x11 = Foo<T>(e).x
x11 = Foo.simpleId(d) // assign to flexible T
var x12 = Foo.bar()
x12 = Foo.simpleId(n) // assign to flexible Number
x12.toInt()
var x13 = e
x13 = Foo.simpleId(d)
}
fun box(): String {
bar(10, "", "")
return "OK"
}
@@ -0,0 +1,63 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNCHECKED_CAST -UNUSED_VALUE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE
// !LANGUAGE: +NewInference
// SKIP_TXT
// FILE: Foo.java
import org.jetbrains.annotations.NotNull;
public class Foo<T> {
T x;
public Foo(T x) {
this.x = x;
}
public static Number bar() { return null; }
public static <K> K simpleId(K k) {
return k;
}
public T produceT() {
return x;
}
@NotNull
public T produceNotNullT() {
return x;
}
public void consumeT(T x) {}
}
// FILE: main.kt
fun <T> bar(n: Number?, d: T, e: T) {
val a: Number = <!TYPE_MISMATCH!>Foo.<!TYPE_MISMATCH!>simpleId(n)<!><!>
val b: Number? = Foo.simpleId(n)
val c = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number?")!>Foo.simpleId(n)<!>
val x4 = Foo(if (true) 10 else null)
val x5: Number = <!TYPE_MISMATCH!>x4.produceT()<!>
val x6: Number? = x4.produceT()
val x7 = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?")!>x4.produceT()<!>
val x8 = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>x4.produceNotNullT()<!>
x4.consumeT(x7)
val x9: T = Foo.simpleId(d)
val x10: T? = Foo.simpleId(d)
if (e != null) {
var x11 = e
x11 = Foo.simpleId(d) // assign to definitely not-null T, the lack an error is consistent with old inference
}
var x11 = Foo<T>(null as T).x
x11 = Foo.simpleId(d) // assign to flexible T
var x12 = Foo.bar()
x12 = Foo.simpleId(n) // assign to flexible Number
var x13 = e
x13 = Foo.simpleId(d)
}
@@ -14642,6 +14642,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
runTest("compiler/testData/diagnostics/tests/nullableTypes/elvisOnUnit.kt");
}
@TestMetadata("inferenceFlexibleTToNullable.kt")
public void testInferenceFlexibleTToNullable() throws Exception {
runTest("compiler/testData/diagnostics/tests/nullableTypes/inferenceFlexibleTToNullable.kt");
}
@TestMetadata("nullAssertOnTypeWithNullableUpperBound.kt")
public void testNullAssertOnTypeWithNullableUpperBound() throws Exception {
runTest("compiler/testData/diagnostics/tests/nullableTypes/nullAssertOnTypeWithNullableUpperBound.kt");
@@ -14637,6 +14637,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
runTest("compiler/testData/diagnostics/tests/nullableTypes/elvisOnUnit.kt");
}
@TestMetadata("inferenceFlexibleTToNullable.kt")
public void testInferenceFlexibleTToNullable() throws Exception {
runTest("compiler/testData/diagnostics/tests/nullableTypes/inferenceFlexibleTToNullable.kt");
}
@TestMetadata("nullAssertOnTypeWithNullableUpperBound.kt")
public void testNullAssertOnTypeWithNullableUpperBound() throws Exception {
runTest("compiler/testData/diagnostics/tests/nullableTypes/nullAssertOnTypeWithNullableUpperBound.kt");
@@ -18111,6 +18111,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/platformTypes"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("inferenceFlexibleTToNullable.kt")
public void testInferenceFlexibleTToNullable() throws Exception {
runTest("compiler/testData/codegen/box/platformTypes/inferenceFlexibleTToNullable.kt");
}
@TestMetadata("unsafeNullCheck.kt")
public void testUnsafeNullCheck() throws Exception {
runTest("compiler/testData/codegen/box/platformTypes/unsafeNullCheck.kt");
@@ -18111,6 +18111,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/platformTypes"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("inferenceFlexibleTToNullable.kt")
public void testInferenceFlexibleTToNullable() throws Exception {
runTest("compiler/testData/codegen/box/platformTypes/inferenceFlexibleTToNullable.kt");
}
@TestMetadata("unsafeNullCheck.kt")
public void testUnsafeNullCheck() throws Exception {
runTest("compiler/testData/codegen/box/platformTypes/unsafeNullCheck.kt");
@@ -16595,6 +16595,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/platformTypes"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
}
@TestMetadata("inferenceFlexibleTToNullable.kt")
public void testInferenceFlexibleTToNullable() throws Exception {
runTest("compiler/testData/codegen/box/platformTypes/inferenceFlexibleTToNullable.kt");
}
@TestMetadata("unsafeNullCheck.kt")
public void testUnsafeNullCheck() throws Exception {
runTest("compiler/testData/codegen/box/platformTypes/unsafeNullCheck.kt");
@@ -16595,6 +16595,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/platformTypes"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
}
@TestMetadata("inferenceFlexibleTToNullable.kt")
public void testInferenceFlexibleTToNullable() throws Exception {
runTest("compiler/testData/codegen/box/platformTypes/inferenceFlexibleTToNullable.kt");
}
@TestMetadata("unsafeNullCheck.kt")
public void testUnsafeNullCheck() throws Exception {
runTest("compiler/testData/codegen/box/platformTypes/unsafeNullCheck.kt");
@@ -13946,6 +13946,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/platformTypes"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true);
}
@TestMetadata("inferenceFlexibleTToNullable.kt")
public void testInferenceFlexibleTToNullable() throws Exception {
runTest("compiler/testData/codegen/box/platformTypes/inferenceFlexibleTToNullable.kt");
}
@TestMetadata("compiler/testData/codegen/box/platformTypes/primitives")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -15126,6 +15126,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/platformTypes"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
}
@TestMetadata("inferenceFlexibleTToNullable.kt")
public void testInferenceFlexibleTToNullable() throws Exception {
runTest("compiler/testData/codegen/box/platformTypes/inferenceFlexibleTToNullable.kt");
}
@TestMetadata("compiler/testData/codegen/box/platformTypes/primitives")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)