[FIR] Elvis operator: flexible rhs type implies flexible type of whole elvis
It's required for further removing of enhancement of final static fields Also, it's k2-potential feature ^KT-62467 Fixed
This commit is contained in:
committed by
Space Team
parent
648330da50
commit
2d61b9a477
+6
@@ -3351,6 +3351,12 @@ public class DiagnosticCompilerTestFirTestdataTestGenerated extends AbstractDiag
|
|||||||
runTest("compiler/fir/analysis-tests/testData/resolve/inference/extensionCallableReferences.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/inference/extensionCallableReferences.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("flexibleTypeAtRightSideOfElvis.kt")
|
||||||
|
public void testFlexibleTypeAtRightSideOfElvis() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/inference/flexibleTypeAtRightSideOfElvis.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("integerLiteralAsComparable.kt")
|
@TestMetadata("integerLiteralAsComparable.kt")
|
||||||
public void testIntegerLiteralAsComparable() throws Exception {
|
public void testIntegerLiteralAsComparable() throws Exception {
|
||||||
|
|||||||
+6
@@ -3351,6 +3351,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFirTestDataTestGenerated
|
|||||||
runTest("compiler/fir/analysis-tests/testData/resolve/inference/extensionCallableReferences.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/inference/extensionCallableReferences.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("flexibleTypeAtRightSideOfElvis.kt")
|
||||||
|
public void testFlexibleTypeAtRightSideOfElvis() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/inference/flexibleTypeAtRightSideOfElvis.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("integerLiteralAsComparable.kt")
|
@TestMetadata("integerLiteralAsComparable.kt")
|
||||||
public void testIntegerLiteralAsComparable() throws Exception {
|
public void testIntegerLiteralAsComparable() throws Exception {
|
||||||
|
|||||||
Vendored
+28
@@ -0,0 +1,28 @@
|
|||||||
|
FILE: main.kt
|
||||||
|
public final fun testWithStatic1(x1: R|kotlin/String?|): R|kotlin/String| {
|
||||||
|
lval x: R|kotlin/String?|
|
||||||
|
R|<local>/x| = R|<local>/x1| ?: Q|JavaClass|.R|/JavaClass.X*s|
|
||||||
|
^testWithStatic1 R|<local>/x|
|
||||||
|
}
|
||||||
|
public final fun testWithStatic2(x1: R|kotlin/String?|): R|kotlin/String| {
|
||||||
|
lvar x: R|kotlin/String?| = Null(null)
|
||||||
|
R|<local>/x| = R|<local>/x1| ?: Q|JavaClass|.R|/JavaClass.f*s|()
|
||||||
|
^testWithStatic2 R|<local>/x|
|
||||||
|
}
|
||||||
|
public final fun testWithStatic3(x1: R|kotlin/String?|): R|kotlin/String| {
|
||||||
|
lval x: R|kotlin/String?| = R|<local>/x1| ?: Q|JavaClass|.R|/JavaClass.X*s|
|
||||||
|
^testWithStatic3 R|<local>/x|
|
||||||
|
}
|
||||||
|
public final fun testWithStatic4(x1: R|kotlin/String?|, w: R|kotlin/Int|): R|kotlin/String| {
|
||||||
|
lvar x: R|kotlin/String?|
|
||||||
|
R|<local>/x| = R|<local>/x1| ?: when (R|<local>/w|) {
|
||||||
|
==($subj$, Int(42)) -> {
|
||||||
|
Q|JavaClass|.R|/JavaClass.X*s|
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
Q|JavaClass|.R|/JavaClass.f*s|()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
^testWithStatic4 R|<local>/x|
|
||||||
|
}
|
||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
// ISSUE: KT-62467
|
||||||
|
|
||||||
|
// FILE: JavaClass.java
|
||||||
|
|
||||||
|
public class JavaClass {
|
||||||
|
public static String X = null;
|
||||||
|
public static String f() { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: main.kt
|
||||||
|
|
||||||
|
fun testWithStatic1(x1: String?): String {
|
||||||
|
val x: String?
|
||||||
|
x = x1 ?: JavaClass.X
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testWithStatic2(x1: String?): String {
|
||||||
|
var x: String? = null
|
||||||
|
x = x1 ?: JavaClass.f()
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testWithStatic3(x1: String?): String {
|
||||||
|
val x: String? = x1 ?: JavaClass.X
|
||||||
|
return <!RETURN_TYPE_MISMATCH!>x<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testWithStatic4(x1: String?, w: Int): String {
|
||||||
|
var x: String?
|
||||||
|
x = x1 ?: when (w) {
|
||||||
|
42 -> JavaClass.X
|
||||||
|
else -> JavaClass.f()
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
+6
@@ -3351,6 +3351,12 @@ public class FirLightTreeDiagnosticsTestGenerated extends AbstractFirLightTreeDi
|
|||||||
runTest("compiler/fir/analysis-tests/testData/resolve/inference/extensionCallableReferences.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/inference/extensionCallableReferences.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("flexibleTypeAtRightSideOfElvis.kt")
|
||||||
|
public void testFlexibleTypeAtRightSideOfElvis() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/inference/flexibleTypeAtRightSideOfElvis.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("integerLiteralAsComparable.kt")
|
@TestMetadata("integerLiteralAsComparable.kt")
|
||||||
public void testIntegerLiteralAsComparable() throws Exception {
|
public void testIntegerLiteralAsComparable() throws Exception {
|
||||||
|
|||||||
+6
@@ -3351,6 +3351,12 @@ public class FirPsiDiagnosticTestGenerated extends AbstractFirPsiDiagnosticTest
|
|||||||
runTest("compiler/fir/analysis-tests/testData/resolve/inference/extensionCallableReferences.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/inference/extensionCallableReferences.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("flexibleTypeAtRightSideOfElvis.kt")
|
||||||
|
public void testFlexibleTypeAtRightSideOfElvis() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/inference/flexibleTypeAtRightSideOfElvis.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("integerLiteralAsComparable.kt")
|
@TestMetadata("integerLiteralAsComparable.kt")
|
||||||
public void testIntegerLiteralAsComparable() throws Exception {
|
public void testIntegerLiteralAsComparable() throws Exception {
|
||||||
|
|||||||
+34
-6
@@ -271,16 +271,44 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirAbstractBodyRes
|
|||||||
}
|
}
|
||||||
|
|
||||||
session.typeContext.run {
|
session.typeContext.run {
|
||||||
if (result.resolvedType.isNullableType() && !result.rhs.resolvedType.isNullableType()) {
|
if (result.resolvedType.isNullableType()) {
|
||||||
// Sometimes return type for special call for elvis operator might be nullable,
|
val rhsResolvedType = result.rhs.resolvedType
|
||||||
// but result is not nullable if the right type is not nullable
|
// This part of the code is a kind of workaround, and it probably will be resolved by KT-55692
|
||||||
result.replaceConeTypeOrNull(
|
if (!rhsResolvedType.isNullableType()) {
|
||||||
result.resolvedType.makeConeTypeDefinitelyNotNullOrNotNull(session.typeContext)
|
// It's definitely not a flexible with nullable bound
|
||||||
)
|
// Sometimes return type for special call for elvis operator might be nullable,
|
||||||
|
// but result is not nullable if the right type is not nullable
|
||||||
|
result.replaceConeTypeOrNull(result.resolvedType.makeConeTypeDefinitelyNotNullOrNotNull(session.typeContext))
|
||||||
|
} else if (rhsResolvedType is ConeFlexibleType && !rhsResolvedType.lowerBound.isNullableType()) {
|
||||||
|
result.replaceConeTypeOrNull(result.resultType.makeConeFlexibleTypeWithNotNullableLowerBound(session.typeContext))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dataFlowAnalyzer.exitElvis(elvisExpression, isLhsNotNull, data.forceFullCompletion)
|
dataFlowAnalyzer.exitElvis(elvisExpression, isLhsNotNull, data.forceFullCompletion)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun ConeKotlinType.makeConeFlexibleTypeWithNotNullableLowerBound(typeContext: ConeTypeContext): ConeKotlinType {
|
||||||
|
with(typeContext) {
|
||||||
|
return when (this@makeConeFlexibleTypeWithNotNullableLowerBound) {
|
||||||
|
is ConeDefinitelyNotNullType ->
|
||||||
|
error("It can't happen because of the previous `isNullableType` check")
|
||||||
|
is ConeFlexibleType -> {
|
||||||
|
if (!lowerBound.isNullableType()) {
|
||||||
|
this@makeConeFlexibleTypeWithNotNullableLowerBound
|
||||||
|
} else {
|
||||||
|
ConeFlexibleType(lowerBound.makeConeTypeDefinitelyNotNullOrNotNull(typeContext) as ConeSimpleKotlinType, upperBound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is ConeIntersectionType -> ConeIntersectionType(
|
||||||
|
intersectedTypes.map { it.makeConeFlexibleTypeWithNotNullableLowerBound(typeContext) }
|
||||||
|
)
|
||||||
|
is ConeSimpleKotlinType -> ConeFlexibleType(
|
||||||
|
makeConeTypeDefinitelyNotNullOrNotNull(typeContext) as ConeSimpleKotlinType,
|
||||||
|
this@makeConeFlexibleTypeWithNotNullableLowerBound
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user