[FIR] Fix raw type nullability computation

Consider the nullability of the type arguments, not of the type.
This fixes a false positive ARGUMENT_TYPE_MISMATCH.

#KT-66294 Fixed
This commit is contained in:
Kirill Rakhman
2024-03-04 11:11:40 +01:00
committed by Space Team
parent df878918ee
commit 172df04c9b
9 changed files with 88 additions and 7 deletions
@@ -22432,6 +22432,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
runTest("compiler/testData/diagnostics/tests/j+k/nullForOptionalOrElse.kt");
}
@Test
@TestMetadata("nullableRawTypeWithFlexibleArguments.kt")
public void testNullableRawTypeWithFlexibleArguments() {
runTest("compiler/testData/diagnostics/tests/j+k/nullableRawTypeWithFlexibleArguments.kt");
}
@Test
@TestMetadata("orderOfSupertypesAndFakeOverrides_1.kt")
public void testOrderOfSupertypesAndFakeOverrides_1() {
@@ -22432,6 +22432,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
runTest("compiler/testData/diagnostics/tests/j+k/nullForOptionalOrElse.kt");
}
@Test
@TestMetadata("nullableRawTypeWithFlexibleArguments.kt")
public void testNullableRawTypeWithFlexibleArguments() {
runTest("compiler/testData/diagnostics/tests/j+k/nullableRawTypeWithFlexibleArguments.kt");
}
@Test
@TestMetadata("orderOfSupertypesAndFakeOverrides_1.kt")
public void testOrderOfSupertypesAndFakeOverrides_1() {
@@ -22426,6 +22426,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
runTest("compiler/testData/diagnostics/tests/j+k/nullForOptionalOrElse.kt");
}
@Test
@TestMetadata("nullableRawTypeWithFlexibleArguments.kt")
public void testNullableRawTypeWithFlexibleArguments() {
runTest("compiler/testData/diagnostics/tests/j+k/nullableRawTypeWithFlexibleArguments.kt");
}
@Test
@TestMetadata("orderOfSupertypesAndFakeOverrides_1.kt")
public void testOrderOfSupertypesAndFakeOverrides_1() {
@@ -22432,6 +22432,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
runTest("compiler/testData/diagnostics/tests/j+k/nullForOptionalOrElse.kt");
}
@Test
@TestMetadata("nullableRawTypeWithFlexibleArguments.kt")
public void testNullableRawTypeWithFlexibleArguments() {
runTest("compiler/testData/diagnostics/tests/j+k/nullableRawTypeWithFlexibleArguments.kt");
}
@Test
@TestMetadata("orderOfSupertypesAndFakeOverrides_1.kt")
public void testOrderOfSupertypesAndFakeOverrides_1() {
@@ -200,7 +200,7 @@ private fun JavaClassifierType.toConeKotlinTypeForFlexibleBound(
// Given `C<T : X>`, `C` -> `C<X>..C<*>?`.
when {
mode.insideAnnotation -> Array(classifier.allTypeParametersNumber()) { ConeStarProjection }
else -> typeParameterSymbols?.getProjectionsForRawType(session, makeNullable = false)
else -> typeParameterSymbols?.getProjectionsForRawType(session, nullabilities = null)
?: Array(classifier.allTypeParametersNumber()) { ConeStarProjection }
}
}
@@ -281,7 +281,7 @@ class ConeRawScopeSubstitutor(
return when {
type is ConeTypeParameterType -> {
substituteOrSelf(
listOf(type.lookupTag.symbol).getProjectionsForRawType(useSiteSession, makeNullable = type.isNullable)[0]
type.lookupTag.symbol.getProjectionForRawType(useSiteSession, makeNullable = type.isMarkedNullable)
)
}
type is ConeClassLikeType && type.typeArguments.isNotEmpty() -> {
@@ -295,8 +295,11 @@ class ConeRawScopeSubstitutor(
}
val firClass = type.fullyExpandedType(useSiteSession).lookupTag.toFirRegularClassSymbol(useSiteSession) ?: return null
val nullabilities = BooleanArray(type.typeArguments.size) { type.typeArguments[it].type?.isMarkedNullable == true }
ConeRawType.create(
type.withArguments(firClass.typeParameterSymbols.getProjectionsForRawType(useSiteSession, makeNullable = type.isNullable)),
type.withArguments(
firClass.typeParameterSymbols.getProjectionsForRawType(useSiteSession, nullabilities = nullabilities)
),
type.replaceArgumentsWithStarProjections()
)
}
@@ -689,15 +689,32 @@ fun List<FirTypeParameterSymbol>.eraseToUpperBoundsAssociated(
}
}
fun List<FirTypeParameterSymbol>.getProjectionsForRawType(session: FirSession, makeNullable: Boolean): Array<ConeKotlinType> {
fun List<FirTypeParameterSymbol>.getProjectionsForRawType(session: FirSession, nullabilities: BooleanArray?): Array<ConeKotlinType> {
val cache = mutableMapOf<FirTypeParameter, ConeKotlinType>()
return Array(size) { index ->
this[index].fir.eraseToUpperBound(
session, cache, mode = EraseUpperBoundMode.FOR_RAW_TYPE_ERASURE
).applyIf(makeNullable) { withNullability(ConeNullability.NULLABLE, session.typeContext) }
this[index].getProjectionForRawType(session, cache, nullabilities?.get(index) == true)
}
}
fun FirTypeParameterSymbol.getProjectionForRawType(
session: FirSession,
makeNullable: Boolean,
): ConeKotlinType {
return getProjectionForRawType(session, mutableMapOf(), makeNullable)
}
private fun FirTypeParameterSymbol.getProjectionForRawType(
session: FirSession,
cache: MutableMap<FirTypeParameter, ConeKotlinType>,
makeNullable: Boolean,
): ConeKotlinType {
return fir.eraseToUpperBound(session, cache, mode = EraseUpperBoundMode.FOR_RAW_TYPE_ERASURE)
.applyIf(makeNullable) {
withNullability(ConeNullability.NULLABLE, session.typeContext)
}
}
private enum class EraseUpperBoundMode {
FOR_RAW_TYPE_ERASURE,
FOR_EMPTY_INTERSECTION_CHECK
@@ -0,0 +1,31 @@
// FIR_IDENTICAL
// FILE: J.java
package test;
import org.jetbrains.annotations.Nullable;
class Editor<BC extends BuildConfiguration, TARGET extends BuildTarget<BC>> {
public void onTargetSelected(@Nullable TARGET target) {}
}
interface BuildConfiguration {}
interface BuildTarget<BC extends BuildConfiguration> {}
class Helper extends AbstractHelper {}
abstract class AbstractHelper<BC extends BuildConfiguration, TARGET extends BuildTarget<BC>> {
@Nullable
public TARGET findRunTarget() {
return null;
}
}
// FILE: test.kt
package test
private fun test(
editor: Editor<BuildConfiguration, BuildTarget<BuildConfiguration>>,
helper: Helper,
) {
editor.onTargetSelected(helper.findRunTarget())
}
@@ -22432,6 +22432,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/j+k/nullForOptionalOrElse.kt");
}
@Test
@TestMetadata("nullableRawTypeWithFlexibleArguments.kt")
public void testNullableRawTypeWithFlexibleArguments() {
runTest("compiler/testData/diagnostics/tests/j+k/nullableRawTypeWithFlexibleArguments.kt");
}
@Test
@TestMetadata("orderOfSupertypesAndFakeOverrides_1.kt")
public void testOrderOfSupertypesAndFakeOverrides_1() {