FIR: Fix loading read-only collection Java types with incorrect variance
This commit is contained in:
committed by
TeamCityServer
parent
5ade831665
commit
18e93b50d9
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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>,
|
||||
|
||||
Vendored
+13
@@ -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())
|
||||
}
|
||||
Vendored
+3
-3
@@ -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
|
||||
|
||||
+2
-2
@@ -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
-1
@@ -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|
|
||||
|
||||
|
||||
Generated
+6
@@ -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
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user