Add temporary hack for wildcards in Collections
By default we would render 'MutableCollection<String>.addAll(Collection<String>)' as '(LCollection<String>;)' (without wildcard) because String is final and effectively it's the same as '(LCollection<? extends String>;)'. But that's wrong signature in a sense that java.util.Collection has different signature: '(LCollection<? extends E>)'. Actually the problem is much wider than collections, it concerns any Java code that uses Kotlin classes with covariant parameters without '? extends E' wildcards. Temporary solution is just to hardcode/enumerate builtin methods with special signature.
This commit is contained in:
@@ -19,16 +19,20 @@ package org.jetbrains.kotlin.codegen
|
||||
import org.jetbrains.kotlin.backend.common.bridges.DescriptorBasedFunctionHandle
|
||||
import org.jetbrains.kotlin.backend.common.bridges.findAllReachableDeclarations
|
||||
import org.jetbrains.kotlin.backend.common.bridges.findConcreteSuperDeclaration
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.load.java.*
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
|
||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature.getSpecialSignatureInfo
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
import org.jetbrains.kotlin.load.java.getOverriddenBuiltinWithDifferentJvmDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtPsiUtil
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getParentCall
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.firstOverridden
|
||||
import org.jetbrains.kotlin.utils.singletonOrEmptyList
|
||||
import java.util.*
|
||||
|
||||
|
||||
@@ -1200,7 +1200,18 @@ public class JetTypeMapper {
|
||||
@NotNull CallableDescriptor callableDescriptor
|
||||
) {
|
||||
sw.writeParameterType(kind);
|
||||
mapType(type, sw, TypeMappingMode.getOptimalModeForValueParameter(type));
|
||||
|
||||
TypeMappingMode typeMappingMode;
|
||||
|
||||
if (TypeMappingUtil.isMethodWithDeclarationSiteWildcards(callableDescriptor) && !type.getArguments().isEmpty()) {
|
||||
typeMappingMode = TypeMappingMode.GENERIC_TYPE; // Render all wildcards
|
||||
}
|
||||
else {
|
||||
typeMappingMode = TypeMappingMode.getOptimalModeForValueParameter(type);
|
||||
}
|
||||
|
||||
mapType(type, sw, typeMappingMode);
|
||||
|
||||
sw.writeParameterTypeEnd();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,11 @@
|
||||
package org.jetbrains.kotlin.codegen.state
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.firstOverridden
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.propertyIfAccessor
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
@@ -67,3 +70,16 @@ public fun getEffectiveVariance(parameterVariance: Variance, projectionKind: Var
|
||||
return Variance.OUT_VARIANCE
|
||||
}
|
||||
|
||||
val CallableDescriptor.isMethodWithDeclarationSiteWildcards: Boolean
|
||||
get() {
|
||||
if (this !is CallableMemberDescriptor) return false
|
||||
return firstOverridden {
|
||||
METHODS_WITH_DECLARATION_SITE_WILDCARDS.containsRaw(it.propertyIfAccessor.fqNameOrNull())
|
||||
} != null
|
||||
}
|
||||
|
||||
private val METHODS_WITH_DECLARATION_SITE_WILDCARDS = setOf(
|
||||
FqName("kotlin.MutableCollection.addAll"),
|
||||
FqName("kotlin.MutableList.addAll"),
|
||||
FqName("kotlin.MutableMap.putAll")
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user