Fix loading container type from Java
Load immutable flexible upper bound for 'Iterable<? super T>' We load 'Collection<? super CharSequence>' as 'MutableCollection<in CharSequence>' instead of 'MutableCollection<in CharSequence>..Collection<*>' because it's obviously not typesafe to use any 'Collection<*>' as argument for such type. But there'se nothing bad with loading 'Iterable<? super CharSequence>' as 'MutableIterable<*>..Collection<*>'. Same for other declarations that have covariant mutable representation (currently Iterator, ListIterator). Also there are useful use-cases when it's neccessary to use 'Iterable<*>' as an argument for parameter with type 'Iterable<? super T>' (see matchers.kt test). NB: Star-projections appear in examples because types like 'Collection<in CharSequence>' with conflicting use-site projections are invalid in Kotlin, but they are valid in Java.
This commit is contained in:
+16
-4
@@ -148,10 +148,8 @@ class LazyJavaTypeResolver(
|
||||
|
||||
if (javaToKotlin.isReadOnly(kotlinDescriptor)) {
|
||||
if (howThisTypeIsUsedEffectively == MEMBER_SIGNATURE_COVARIANT
|
||||
|| howThisTypeIsUsedEffectively == SUPERTYPE
|
||||
// Convert (Mutable)List<in A> to MutableList<in A>
|
||||
// Same for (Mutable)Map<K, in V>
|
||||
|| javaType.typeArguments.lastOrNull().isSuperWildcard()) {
|
||||
|| howThisTypeIsUsedEffectively == SUPERTYPE
|
||||
|| javaType.argumentsMakeSenseOnlyForMutableContainer(readOnlyContainer = kotlinDescriptor)) {
|
||||
return javaToKotlin.convertReadOnlyToMutable(kotlinDescriptor)
|
||||
}
|
||||
}
|
||||
@@ -159,6 +157,20 @@ class LazyJavaTypeResolver(
|
||||
return kotlinDescriptor
|
||||
}
|
||||
|
||||
// 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(
|
||||
readOnlyContainer: ClassDescriptor
|
||||
): Boolean {
|
||||
if (!typeArguments.lastOrNull().isSuperWildcard()) return false
|
||||
val mutableLastParameterVariance = JavaToKotlinClassMap.INSTANCE.convertReadOnlyToMutable(readOnlyContainer)
|
||||
.typeConstructor.parameters.lastOrNull()?.variance ?: return false
|
||||
|
||||
return mutableLastParameterVariance != OUT_VARIANCE
|
||||
}
|
||||
|
||||
private fun JavaType?.isSuperWildcard(): Boolean = (this as? JavaWildcardType)?.let { it.bound != null && !it.isExtends } ?: false
|
||||
|
||||
private fun isRaw(): Boolean {
|
||||
|
||||
Reference in New Issue
Block a user