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
|
interface PsiClass
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
val processor = AdapterProcessor<PsiMethod, PsiClass>(
|
val processor = AdapterProcessor<PsiMethod, PsiClass?>(
|
||||||
Function { method: PsiMethod? -> method?.containingClass }
|
Function { method: PsiMethod? -> method?.containingClass }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@ FILE: main.kt
|
|||||||
public abstract interface PsiClass : R|kotlin/Any| {
|
public abstract interface PsiClass : R|kotlin/Any| {
|
||||||
}
|
}
|
||||||
public final fun test(): R|kotlin/Unit| {
|
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|
|
R|<local>/method|?.R|/PsiMethod.containingClass|
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
|
|||||||
+5
@@ -14635,6 +14635,11 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok
|
|||||||
runTest("compiler/testData/diagnostics/tests/nullableTypes/elvisOnUnit.kt");
|
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")
|
@TestMetadata("nullAssertOnTypeWithNullableUpperBound.kt")
|
||||||
public void testNullAssertOnTypeWithNullableUpperBound() throws Exception {
|
public void testNullAssertOnTypeWithNullableUpperBound() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/nullableTypes/nullAssertOnTypeWithNullableUpperBound.kt");
|
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!! .. Foo?) <: T
|
* Foo? <: T! -- Foo? <: T
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* (Foo..Bar) <: T! --
|
* (Foo..Bar) <: T! --
|
||||||
@@ -163,7 +163,11 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
|
|||||||
when (subType) {
|
when (subType) {
|
||||||
is SimpleTypeMarker ->
|
is SimpleTypeMarker ->
|
||||||
// Foo <: T! -- (Foo!! .. Foo) <: T
|
// 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 ->
|
is FlexibleTypeMarker ->
|
||||||
// (Foo..Bar) <: T! -- (Foo!! .. Bar) <: T
|
// (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");
|
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")
|
@TestMetadata("nullAssertOnTypeWithNullableUpperBound.kt")
|
||||||
public void testNullAssertOnTypeWithNullableUpperBound() throws Exception {
|
public void testNullAssertOnTypeWithNullableUpperBound() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/nullableTypes/nullAssertOnTypeWithNullableUpperBound.kt");
|
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");
|
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")
|
@TestMetadata("nullAssertOnTypeWithNullableUpperBound.kt")
|
||||||
public void testNullAssertOnTypeWithNullableUpperBound() throws Exception {
|
public void testNullAssertOnTypeWithNullableUpperBound() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/nullableTypes/nullAssertOnTypeWithNullableUpperBound.kt");
|
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);
|
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")
|
@TestMetadata("unsafeNullCheck.kt")
|
||||||
public void testUnsafeNullCheck() throws Exception {
|
public void testUnsafeNullCheck() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/platformTypes/unsafeNullCheck.kt");
|
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);
|
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")
|
@TestMetadata("unsafeNullCheck.kt")
|
||||||
public void testUnsafeNullCheck() throws Exception {
|
public void testUnsafeNullCheck() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/platformTypes/unsafeNullCheck.kt");
|
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);
|
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")
|
@TestMetadata("unsafeNullCheck.kt")
|
||||||
public void testUnsafeNullCheck() throws Exception {
|
public void testUnsafeNullCheck() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/platformTypes/unsafeNullCheck.kt");
|
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);
|
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")
|
@TestMetadata("unsafeNullCheck.kt")
|
||||||
public void testUnsafeNullCheck() throws Exception {
|
public void testUnsafeNullCheck() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/platformTypes/unsafeNullCheck.kt");
|
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);
|
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")
|
@TestMetadata("compiler/testData/codegen/box/platformTypes/primitives")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@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);
|
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")
|
@TestMetadata("compiler/testData/codegen/box/platformTypes/primitives")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user