FIR: Fix loading read-only collection Java types with incorrect variance

This commit is contained in:
Denis.Zharkov
2021-05-28 13:18:01 +03:00
committed by TeamCityServer
parent 5ade831665
commit 18e93b50d9
12 changed files with 66 additions and 10 deletions
@@ -20898,6 +20898,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/platformTypes/genericVarianceViolation"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("inferenceFrom.kt")
public void testInferenceFrom() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/genericVarianceViolation/inferenceFrom.kt");
}
@Test
@TestMetadata("listSuperType.kt")
public void testListSuperType() throws Exception {
@@ -20898,6 +20898,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/platformTypes/genericVarianceViolation"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("inferenceFrom.kt")
public void testInferenceFrom() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/genericVarianceViolation/inferenceFrom.kt");
}
@Test
@TestMetadata("listSuperType.kt")
public void testListSuperType() throws Exception {
@@ -409,7 +409,7 @@ private fun JavaClassifierType.toConeKotlinTypeForFlexibleBound(
JavaToKotlinClassMap.mapJavaToKotlin(classifier.fqName!!)
} ?: classifier.classId!!
if (isLowerBound) {
if (isLowerBound || argumentsMakeSenseOnlyForMutableContainer(classId, session)) {
classId = classId.readOnlyToMutable() ?: classId
}
@@ -460,6 +460,26 @@ private fun JavaClassifierType.toConeKotlinTypeForFlexibleBound(
}
}
// Returns true for covariant read-only container that has mutable pair with invariant parameter
// List<in A> does not make sense, but MutableList<in A> does
// Same for Map<K, in V>
// But both Iterable<in A>, MutableIterable<in A> don't make sense as they are covariant, so return false
private fun JavaClassifierType.argumentsMakeSenseOnlyForMutableContainer(
classId: ClassId,
session: FirSession,
): Boolean {
if (!JavaToKotlinClassMap.isReadOnly(classId.asSingleFqName().toUnsafe())) return false
val mutableClassId = classId.readOnlyToMutable() ?: return false
if (!typeArguments.lastOrNull().isSuperWildcard()) return false
val mutableLastParameterVariance =
(mutableClassId.toLookupTag().toSymbol(session)?.fir as? FirRegularClass)?.typeParameters?.lastOrNull()?.symbol?.fir?.variance
?: return false
return mutableLastParameterVariance != OUT_VARIANCE
}
private fun FirRegularClass.createRawArguments(
session: FirSession,
defaultArgs: List<ConeStarProjection>,
@@ -0,0 +1,13 @@
// FIR_IDENTICAL
// SKIP_TXT
// FILE: JavaClass.java
import org.jetbrains.annotations.NotNull;
public class JavaClass {
public static void add(final @NotNull java.util.List<? super CharSequence> addedLibraries) {}
}
// FILE: main.kt
fun bar() {
JavaClass.add(ArrayList())
}
@@ -11,8 +11,8 @@ public class A {
fun main(a: A, ml: MutableList<String>, l: List<String>) {
a.foo(ml)
a.foo(l)
a.foo(<!ARGUMENT_TYPE_MISMATCH!>l<!>)
a.bar(ml)
a.bar(l)
a.bar(<!ARGUMENT_TYPE_MISMATCH!>ml<!>)
a.bar(<!ARGUMENT_TYPE_MISMATCH!>l<!>)
}
@@ -24,7 +24,7 @@ FILE fqName:<root> fileName:/v8arrayToList.kt
CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in <root>.V8Array' type=<root>.V8Array origin=null
VAR name:list type:kotlin.collections.List<kotlin.String> [val]
TYPE_OP type=kotlin.collections.List<kotlin.String> origin=CAST typeOperand=kotlin.collections.List<kotlin.String>
CALL 'public open fun toList (array: @[FlexibleNullability] <root>.V8Array?): @[FlexibleNullability] kotlin.collections.List<*>? declared in <root>.Utils' type=@[FlexibleNullability] kotlin.collections.List<*>? origin=null
CALL 'public open fun toList (array: @[FlexibleNullability] <root>.V8Array?): @[FlexibleNullability] kotlin.collections.MutableList<in @[FlexibleNullability] kotlin.Any?>? declared in <root>.Utils' type=@[FlexibleNullability] kotlin.collections.MutableList<in @[FlexibleNullability] kotlin.Any?>? origin=null
array: GET_VAR 'val array: <root>.V8Array [val] declared in <root>.box' type=<root>.V8Array origin=null
RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in <root>'
CALL 'public abstract fun get (index: kotlin.Int): E of kotlin.collections.List [operator] declared in kotlin.collections.List' type=kotlin.String origin=null
@@ -1,7 +1,7 @@
public open class MethodWithMappedClasses : R|kotlin/Any| {
public open fun <T : R|ft<kotlin/Any, kotlin/Any?>|> copy(dest: R|ft<kotlin/collections/MutableList<in ft<T, T?>>, kotlin/collections/List<*>?>|, src: R|ft<kotlin/collections/MutableList<ft<T, T?>>, kotlin/collections/List<ft<T, T?>>?>|): R|kotlin/Unit|
public open fun <T : R|ft<kotlin/Any, kotlin/Any?>|> copy(dest: R|ft<kotlin/collections/MutableList<in ft<T, T?>>, kotlin/collections/MutableList<in ft<T, T?>>?>|, src: R|ft<kotlin/collections/MutableList<ft<T, T?>>, kotlin/collections/List<ft<T, T?>>?>|): R|kotlin/Unit|
public open fun <T : R|ft<kotlin/Any, kotlin/Any?>|> copyMap(dest: R|ft<kotlin/collections/MutableMap<ft<kotlin/String, kotlin/String?>, in ft<T, T?>>, kotlin/collections/Map<ft<kotlin/String, kotlin/String?>, *>?>|, src: R|ft<kotlin/collections/MutableMap<ft<kotlin/String, kotlin/String?>, ft<T, T?>>, kotlin/collections/Map<ft<kotlin/String, kotlin/String?>, ft<T, T?>>?>|): R|kotlin/Unit|
public open fun <T : R|ft<kotlin/Any, kotlin/Any?>|> copyMap(dest: R|ft<kotlin/collections/MutableMap<ft<kotlin/String, kotlin/String?>, in ft<T, T?>>, kotlin/collections/MutableMap<ft<kotlin/String, kotlin/String?>, in ft<T, T?>>?>|, src: R|ft<kotlin/collections/MutableMap<ft<kotlin/String, kotlin/String?>, ft<T, T?>>, kotlin/collections/Map<ft<kotlin/String, kotlin/String?>, ft<T, T?>>?>|): R|kotlin/Unit|
public constructor(): R|test/MethodWithMappedClasses|
@@ -1,5 +1,5 @@
public open class MethodWithTypeParameters : R|kotlin/Any| {
public open fun <A : R|ft<kotlin/Any, kotlin/Any?>|, B : R|ft<java/lang/Runnable, java/lang/Runnable?>|, R|ft<kotlin/collections/MutableList<ft<kotlin/Cloneable, kotlin/Cloneable?>>, kotlin/collections/List<ft<kotlin/Cloneable, kotlin/Cloneable?>>?>|> foo(a: R|ft<A, A?>|, b: R|ft<kotlin/collections/MutableList<out ft<B, B?>>, kotlin/collections/List<out ft<B, B?>>?>|, list: R|ft<kotlin/collections/MutableList<in ft<kotlin/String, kotlin/String?>>, kotlin/collections/List<*>?>|): R|kotlin/Unit|
public open fun <A : R|ft<kotlin/Any, kotlin/Any?>|, B : R|ft<java/lang/Runnable, java/lang/Runnable?>|, R|ft<kotlin/collections/MutableList<ft<kotlin/Cloneable, kotlin/Cloneable?>>, kotlin/collections/List<ft<kotlin/Cloneable, kotlin/Cloneable?>>?>|> foo(a: R|ft<A, A?>|, b: R|ft<kotlin/collections/MutableList<out ft<B, B?>>, kotlin/collections/List<out ft<B, B?>>?>|, list: R|ft<kotlin/collections/MutableList<in ft<kotlin/String, kotlin/String?>>, kotlin/collections/MutableList<in ft<kotlin/String, kotlin/String?>>?>|): R|kotlin/Unit|
public constructor(): R|test/MethodWithTypeParameters|
@@ -20904,6 +20904,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/platformTypes/genericVarianceViolation"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("inferenceFrom.kt")
public void testInferenceFrom() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/genericVarianceViolation/inferenceFrom.kt");
}
@Test
@TestMetadata("listSuperType.kt")
public void testListSuperType() throws Exception {
@@ -43,3 +43,5 @@ interface JavaWildcardType : JavaType {
val bound: JavaType?
val isExtends: Boolean
}
fun JavaType?.isSuperWildcard(): Boolean = (this as? JavaWildcardType)?.let { it.bound != null && !it.isExtends } ?: false
@@ -184,8 +184,6 @@ class JavaTypeResolver(
private fun JavaClassifierType.argumentsMakeSenseOnlyForMutableContainer(
readOnlyContainer: ClassDescriptor
): Boolean {
fun JavaType?.isSuperWildcard(): Boolean = (this as? JavaWildcardType)?.let { it.bound != null && !it.isExtends } ?: false
if (!typeArguments.lastOrNull().isSuperWildcard()) return false
val mutableLastParameterVariance = JavaToKotlinClassMapper.convertReadOnlyToMutable(readOnlyContainer)
.typeConstructor.parameters.lastOrNull()?.variance ?: return false
@@ -18320,6 +18320,11 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/platformTypes/genericVarianceViolation"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@TestMetadata("inferenceFrom.kt")
public void testInferenceFrom() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/genericVarianceViolation/inferenceFrom.kt");
}
@TestMetadata("listSuperType.kt")
public void testListSuperType() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/genericVarianceViolation/listSuperType.kt");