NI: Prefer nullable lower bound to flexible one when substitution of type variable is performed
^KT-32435 Fixed
This commit is contained in:
committed by
victor.petukhov
parent
78dfcef160
commit
09c2b92b1d
@@ -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|
|
||||
}
|
||||
))
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
+6
-2
@@ -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"
|
||||
}
|
||||
+63
@@ -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");
|
||||
|
||||
Generated
+5
@@ -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");
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
Generated
+5
@@ -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)
|
||||
|
||||
+5
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user