Change resolution priority level for SAM adapters

After this change SAM adapters are being resolved in the same group
as members, thus their overload resolution happens simultaneously.

But in the case of overload resolution ambiguity try to filter out all
synthetic members and run the process again.

See the issue and new test for clarification

 #KT-11128 In Progress
This commit is contained in:
Denis Zharkov
2016-12-07 17:16:00 +03:00
parent a4adfb43d4
commit 891a036b59
22 changed files with 223 additions and 68 deletions
@@ -34,6 +34,8 @@ object ProtectedSyntheticExtensionCallChecker : CallChecker {
val sourceFunction = when (descriptor) {
is SyntheticJavaPropertyDescriptor -> descriptor.getMethod
// TODO: this branch becomes unnecessary, because common checks are applied to SAM adapters being resolved as common members
// But this part may be still useful when we enable backward compatibility mode and SAM adapters become extensions again
is SamAdapterExtensionFunctionDescriptor -> descriptor.baseDescriptorForSynthetic
else -> return
}
@@ -291,7 +291,7 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager, private val l
companion object {
fun create(ownerClass: ClassDescriptor, getMethod: FunctionDescriptor, setMethod: FunctionDescriptor?, name: Name, type: KotlinType): MyPropertyDescriptor {
val visibility = syntheticExtensionVisibility(getMethod)
val visibility = syntheticVisibility(getMethod, isUsedForExtension = true)
val descriptor = MyPropertyDescriptor(DescriptorUtils.getContainingModule(ownerClass),
null,
Annotations.EMPTY,
@@ -328,7 +328,7 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager, private val l
PropertySetterDescriptorImpl(descriptor,
setMethod.annotations,
Modality.FINAL,
syntheticExtensionVisibility(setMethod),
syntheticVisibility(setMethod, isUsedForExtension = true),
false,
setMethod.isExternal,
false,
@@ -25,8 +25,7 @@ import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.load.java.sam.SingleAbstractMethodUtils
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
import org.jetbrains.kotlin.resolve.calls.inference.wrapWithCapturingSubstitution
import org.jetbrains.kotlin.resolve.isHiddenInResolution
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.SyntheticScope
@@ -59,8 +58,10 @@ class SamAdapterFunctionsScope(
override fun getSyntheticExtensionFunctions(receiverTypes: Collection<KotlinType>, name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
var result: SmartList<FunctionDescriptor>? = null
for (type in receiverTypes) {
val substitutorForType by lazy { buildMemberScopeSubstitutorForType(type) }
for (function in type.memberScope.getContributedFunctions(name, location)) {
val extension = extensionForFunction(function.original)
val extension = extensionForFunction(function.original)?.substitute(substitutorForType)
if (extension != null) {
if (result == null) {
result = SmartList()
@@ -76,11 +77,16 @@ class SamAdapterFunctionsScope(
}
}
private fun buildMemberScopeSubstitutorForType(type: KotlinType) =
TypeConstructorSubstitution.create(type).wrapWithCapturingSubstitution(needApproximation = true).buildSubstitutor()
override fun getSyntheticExtensionFunctions(receiverTypes: Collection<KotlinType>): Collection<FunctionDescriptor> {
return receiverTypes.flatMapTo(LinkedHashSet<FunctionDescriptor>()) { type ->
type.memberScope.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS)
.filterIsInstance<FunctionDescriptor>()
.mapNotNull { extensionForFunction(it.original) }
.mapNotNull {
extensionForFunction(it.original)?.substitute(buildMemberScopeSubstitutorForType(type))
}
}
}
@@ -100,11 +106,13 @@ class SamAdapterFunctionsScope(
override var baseDescriptorForSynthetic: FunctionDescriptor by Delegates.notNull()
private set
private lateinit var fromSourceFunctionTypeParameters: Map<TypeParameterDescriptor, TypeParameterDescriptor>
private val fromSourceFunctionTypeParameters: Map<TypeParameterDescriptor, TypeParameterDescriptor> by lazy {
baseDescriptorForSynthetic.typeParameters.zip(typeParameters).toMap()
}
companion object {
fun create(sourceFunction: FunctionDescriptor): MyFunctionDescriptor {
val descriptor = MyFunctionDescriptor(DescriptorUtils.getContainingModule(sourceFunction),
val descriptor = MyFunctionDescriptor(sourceFunction.containingDeclaration,
null,
sourceFunction.annotations,
sourceFunction.name,
@@ -114,26 +122,16 @@ class SamAdapterFunctionsScope(
val sourceTypeParams = (sourceFunction.typeParameters).toMutableList()
val ownerClass = sourceFunction.containingDeclaration as ClassDescriptor
//TODO: should we go up parents for getters/setters too?
//TODO: non-inner classes
for (parent in ownerClass.parentsWithSelf) {
if (parent !is ClassDescriptor) break
sourceTypeParams += parent.declaredTypeParameters
}
//TODO: duplicated parameter names
val typeParameters = ArrayList<TypeParameterDescriptor>(sourceTypeParams.size)
val typeSubstitutor = DescriptorSubstitutor.substituteTypeParameters(sourceTypeParams, TypeSubstitution.EMPTY, descriptor, typeParameters)
descriptor.fromSourceFunctionTypeParameters = sourceTypeParams.zip(typeParameters).toMap()
val returnType = typeSubstitutor.safeSubstitute(sourceFunction.returnType!!, Variance.INVARIANT)
val receiverType = typeSubstitutor.safeSubstitute(ownerClass.defaultType, Variance.INVARIANT)
val valueParameters = SingleAbstractMethodUtils.createValueParametersForSamAdapter(sourceFunction, descriptor, typeSubstitutor)
val visibility = syntheticExtensionVisibility(sourceFunction)
val visibility = syntheticVisibility(sourceFunction, isUsedForExtension = false)
descriptor.initialize(receiverType, null, typeParameters, valueParameters, returnType,
descriptor.initialize(null, ownerClass.thisAsReceiverParameter, typeParameters, valueParameters, returnType,
Modality.FINAL, visibility)
descriptor.isOperator = sourceFunction.isOperator
@@ -30,14 +30,18 @@ fun FunctionDescriptor.hasJavaOriginInHierarchy(): Boolean {
fun Visibility.isVisibleOutside() = this != Visibilities.PRIVATE && this != Visibilities.PRIVATE_TO_THIS && this != Visibilities.INVISIBLE_FAKE
fun syntheticExtensionVisibility(originalDescriptor: DeclarationDescriptorWithVisibility): Visibility {
fun syntheticVisibility(originalDescriptor: DeclarationDescriptorWithVisibility, isUsedForExtension: Boolean): Visibility {
val originalVisibility = originalDescriptor.visibility
return when (originalVisibility) {
Visibilities.PUBLIC -> Visibilities.PUBLIC
else -> object : Visibility(originalVisibility.name, originalVisibility.isPublicAPI) {
override fun isVisible(receiver: ReceiverValue?, what: DeclarationDescriptorWithVisibility, from: DeclarationDescriptor)
= originalVisibility.isVisible(Visibilities.ALWAYS_SUITABLE_RECEIVER, originalDescriptor, from)
override fun isVisible(
receiver: ReceiverValue?,
what: DeclarationDescriptorWithVisibility,
from: DeclarationDescriptor
) = originalVisibility.isVisible(
if (isUsedForExtension) Visibilities.ALWAYS_SUITABLE_RECEIVER else receiver, originalDescriptor, from)
override fun mustCheckInImports()
= throw UnsupportedOperationException("Should never be called for this visibility")
@@ -50,4 +54,4 @@ fun syntheticExtensionVisibility(originalDescriptor: DeclarationDescriptorWithVi
}
}
}
}