From 891a036b595422a905f938c2247094dfea5a6f9f Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Wed, 7 Dec 2016 17:16:00 +0300 Subject: [PATCH] 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 --- .../jetbrains/kotlin/codegen/StackValue.java | 9 +---- .../ProtectedSyntheticExtensionCallChecker.kt | 2 ++ .../synthetic/JavaSyntheticPropertiesScope.kt | 4 +-- .../synthetic/SamAdapterFunctionsScope.kt | 34 +++++++++--------- .../synthetic/syntheticExtensionsUtils.kt | 12 ++++--- .../calls/tower/NewResolutionOldInference.kt | 3 +- .../resolve/calls/results/FlatSignature.kt | 7 ++-- .../results/OverloadingConflictResolver.kt | 6 +++- .../resolve/calls/tower/ImplicitScopeTower.kt | 2 -- .../calls/tower/ScopeTowerProcessors.kt | 34 ++++++++++++++++-- .../kotlin/resolve/calls/tower/TowerLevels.kt | 32 ++++++++++------- .../resolve/calls/tower/TowerResolver.kt | 14 ++++---- .../samByProjectedType/genericInReturnType.kt | 2 +- .../syntheticSAMExtensions.kt | 4 +-- .../samAdapters/InnerClassInGeneric.kt | 2 +- .../samAdapters/Protected.kt | 4 +-- .../samAdapters/overloadResolution.kt | 36 +++++++++++++++++++ .../samAdapters/overloadResolution.txt | 15 ++++++++ .../samAdapters/overloadResolutionStatic.kt | 36 +++++++++++++++++++ .../samAdapters/overloadResolutionStatic.txt | 19 ++++++++++ .../forEachRemainingNullability.kt | 2 +- .../checkers/DiagnosticsTestGenerated.java | 12 +++++++ 22 files changed, 223 insertions(+), 68 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/overloadResolution.kt create mode 100644 compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/overloadResolution.txt create mode 100644 compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/overloadResolutionStatic.kt create mode 100644 compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/overloadResolutionStatic.txt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java index 90581b05937..41d99bedd04 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java @@ -49,7 +49,6 @@ import org.jetbrains.kotlin.resolve.jvm.AsmTypes; import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind; import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature; import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue; -import org.jetbrains.kotlin.synthetic.SamAdapterExtensionFunctionDescriptor; import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.org.objectweb.asm.Label; import org.jetbrains.org.objectweb.asm.Type; @@ -517,13 +516,7 @@ public abstract class StackValue { ReceiverParameterDescriptor dispatchReceiverParameter = descriptor.getDispatchReceiverParameter(); ReceiverParameterDescriptor extensionReceiverParameter = descriptor.getExtensionReceiverParameter(); - if (descriptor.getOriginal() instanceof SamAdapterExtensionFunctionDescriptor) { - callDispatchReceiver = callExtensionReceiver; - callExtensionReceiver = null; - dispatchReceiverParameter = extensionReceiverParameter; - extensionReceiverParameter = null; - } - else if (descriptor instanceof SyntheticFieldDescriptor) { + if (descriptor instanceof SyntheticFieldDescriptor) { dispatchReceiverParameter = ((SyntheticFieldDescriptor) descriptor).getDispatchReceiverParameterForBackend(); } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ProtectedSyntheticExtensionCallChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ProtectedSyntheticExtensionCallChecker.kt index 1cb0f990a09..9dabfce44b6 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ProtectedSyntheticExtensionCallChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ProtectedSyntheticExtensionCallChecker.kt @@ -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 } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/JavaSyntheticPropertiesScope.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/JavaSyntheticPropertiesScope.kt index c252140f3ff..c967b5eeb22 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/JavaSyntheticPropertiesScope.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/JavaSyntheticPropertiesScope.kt @@ -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, diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/SamAdapterFunctionsScope.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/SamAdapterFunctionsScope.kt index 8ff0a9775d0..372a6d81500 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/SamAdapterFunctionsScope.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/SamAdapterFunctionsScope.kt @@ -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, name: Name, location: LookupLocation): Collection { var result: SmartList? = 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): Collection { return receiverTypes.flatMapTo(LinkedHashSet()) { type -> type.memberScope.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS) .filterIsInstance() - .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 + private val fromSourceFunctionTypeParameters: Map 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(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 diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/syntheticExtensionsUtils.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/syntheticExtensionsUtils.kt index 5a0fd9672e4..f02f4b14019 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/syntheticExtensionsUtils.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/syntheticExtensionsUtils.kt @@ -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 } } -} \ No newline at end of file +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt index 03fcda8f903..664d9b70e0e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt @@ -189,8 +189,7 @@ class NewResolutionOldInference( ) candidateResolver.performResolutionForCandidateCall(callCandidateResolutionContext, basicCallContext.checkArguments) // todo - val diagnostics = listOfNotNull(SynthesizedDescriptorDiagnostic.check { candidate.descriptor.isSynthesized }, - createPreviousResolveError(resolvedCall.status)) + val diagnostics = listOfNotNull(createPreviousResolveError(resolvedCall.status)) MyCandidate(ResolutionCandidateStatus(diagnostics), resolvedCall) } if (basicCallContext.collectAllCandidates) { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/results/FlatSignature.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/results/FlatSignature.kt index ee50dba839d..f59845424ac 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/results/FlatSignature.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/results/FlatSignature.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.MemberDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.utils.singletonOrEmptyList @@ -43,7 +44,8 @@ class FlatSignature private constructor( val hasExtensionReceiver: Boolean, val hasVarargs: Boolean, val numDefaults: Int, - val isPlatform: Boolean + val isPlatform: Boolean, + val isSyntheticMember: Boolean ) { val isGeneric = typeParameters.isNotEmpty() @@ -63,7 +65,8 @@ class FlatSignature private constructor( hasExtensionReceiver = extensionReceiverType != null, hasVarargs = descriptor.valueParameters.any { it.varargElementType != null }, numDefaults = numDefaults, - isPlatform = descriptor is MemberDescriptor && descriptor.isPlatform + isPlatform = descriptor is MemberDescriptor && descriptor.isPlatform, + isSyntheticMember = descriptor is SyntheticMemberDescriptor<*> ) } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/results/OverloadingConflictResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/results/OverloadingConflictResolver.kt index 09406030cde..20075a8eb8b 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/results/OverloadingConflictResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/results/OverloadingConflictResolver.kt @@ -133,6 +133,10 @@ class OverloadingConflictResolver( CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS -> findMaximallySpecificCall(candidates, discriminateGenerics, isDebuggerContext) + ?: findMaximallySpecificCall( + candidates.filterNotTo(mutableSetOf()) { createFlatSignature(it).isSyntheticMember }, + discriminateGenerics, isDebuggerContext + ) } // null means ambiguity between variables @@ -219,7 +223,7 @@ class OverloadingConflictResolver( } /** - * Returns `true` if [call1] is definitely not less specific than [call2], + * Returns `true` if [call1] is definitely more or equally specific [call2], * `false` otherwise. */ private fun compareCallsByUsedArguments( diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ImplicitScopeTower.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ImplicitScopeTower.kt index 9115f5543c8..36fea4def76 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ImplicitScopeTower.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ImplicitScopeTower.kt @@ -67,7 +67,6 @@ data class ResolutionCandidateStatus(val diagnostics: List enum class ResolutionCandidateApplicability { RESOLVED, // call success or has uncompleted inference or in other words possible successful candidate - RESOLVED_SYNTHESIZED, // todo remove it (need for SAM adapters which created inside some MemberScope) RESOLVED_LOW_PRIORITY, CONVENTION_ERROR, // missing infix, operator etc MAY_THROW_RUNTIME_ERROR, // unsafe call or unstable smart cast @@ -89,7 +88,6 @@ class UsedSmartCastForDispatchReceiver(val smartCastType: KotlinType): Resolutio object ErrorDescriptorDiagnostic : ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED) // todo discuss and change to INAPPLICABLE object LowPriorityDescriptorDiagnostic : ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY) -object SynthesizedDescriptorDiagnostic : ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED) object DynamicDescriptorDiagnostic: ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY) object UnstableSmartCastDiagnostic: ResolutionDiagnostic(ResolutionCandidateApplicability.MAY_THROW_RUNTIME_ERROR) object ExtensionWithStaticTypeWithDynamicReceiver: ResolutionDiagnostic(ResolutionCandidateApplicability.HIDDEN) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerProcessors.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerProcessors.kt index e2c32005108..4b533e46df0 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerProcessors.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerProcessors.kt @@ -67,8 +67,9 @@ internal class ExplicitReceiverScopeTowerProcessor { - val members = ReceiverScopeTowerLevel(scopeTower, explicitReceiver) - .collectCandidates(null).filter { !it.requiresExtensionReceiver } + val members = + MemberScopeTowerLevel(scopeTower, explicitReceiver) + .collectCandidates(null).filter { !it.requiresExtensionReceiver } return members.map { candidateFactory.createCandidate(it, ExplicitReceiverKind.DISPATCH_RECEIVER, extensionReceiver = null) } } @@ -118,6 +119,35 @@ private class NoExplicitReceiverScopeTowerProcessor emptyList() } + +} +private fun > processCommonAndSyntheticMembers( + receiverForMember: ReceiverValueWithSmartCastInfo, + scopeTowerLevel: ScopeTowerLevel, + collectCandidates: CandidatesCollector, + candidateFactory: CandidateFactory, + isExplicitReceiver: Boolean +): List { + val (members, syntheticExtension) = + scopeTowerLevel.collectCandidates(null) + .filter { + it.descriptor.dispatchReceiverParameter == null || it.descriptor.extensionReceiverParameter == null + }.partition { !it.requiresExtensionReceiver } + + return members.map { + candidateFactory.createCandidate( + it, + if (isExplicitReceiver) ExplicitReceiverKind.DISPATCH_RECEIVER else ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, + extensionReceiver = null + ) + } + + syntheticExtension.map { + candidateFactory.createCandidate( + it, + if (isExplicitReceiver) ExplicitReceiverKind.EXTENSION_RECEIVER else ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, + extensionReceiver = receiverForMember + ) + } } private fun > createSimpleProcessor( diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt index f8e5f8ac58a..3d0adb2b3bf 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt @@ -40,6 +40,7 @@ import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.typeUtil.getImmediateSuperclassNotAny import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.kotlin.utils.addIfNotNull +import org.jetbrains.kotlin.utils.singletonOrEmptyList import org.jetbrains.kotlin.utils.toReadOnlyList import java.util.* @@ -62,7 +63,6 @@ internal abstract class AbstractScopeTowerLevel( } else { if (descriptor.hasLowPriorityInOverloadResolution()) diagnostics.add(LowPriorityDescriptorDiagnostic) - if (descriptor.isSynthesized) diagnostics.add(SynthesizedDescriptorDiagnostic) if (dispatchReceiverSmartCastType != null) diagnostics.add(UsedSmartCastForDispatchReceiver(dispatchReceiverSmartCastType)) val shouldSkipVisibilityCheck = scopeTower.isDebuggerContext @@ -81,11 +81,13 @@ internal abstract class AbstractScopeTowerLevel( // todo KT-9538 Unresolved inner class via subclass reference // todo add static methods & fields with error -internal class ReceiverScopeTowerLevel( +internal class MemberScopeTowerLevel( scopeTower: ImplicitScopeTower, val dispatchReceiver: ReceiverValueWithSmartCastInfo ): AbstractScopeTowerLevel(scopeTower) { + private val syntheticScopes = scopeTower.syntheticScopes + private fun collectMembers( getMembers: ResolutionScope.(KotlinType?) -> Collection ): Collection> { @@ -100,7 +102,11 @@ internal class ReceiverScopeTowerLevel( for (possibleType in dispatchReceiver.possibleTypes) { possibleType.memberScope.getMembers(possibleType).mapTo(unstableCandidates ?: result) { - createCandidateDescriptor(it, dispatchReceiver.smartCastReceiver(possibleType), unstableError, dispatchReceiverSmartCastType = possibleType) + createCandidateDescriptor( + it, + dispatchReceiver.smartCastReceiver(possibleType), + unstableError, dispatchReceiverSmartCastType = possibleType + ) } } @@ -139,7 +145,8 @@ internal class ReceiverScopeTowerLevel( override fun getFunctions(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection> { return collectMembers { - getContributedFunctions(name, location) + it.getInnerConstructors(name, location) + getContributedFunctions(name, location) + it.getInnerConstructors(name, location) + + syntheticScopes.collectSyntheticExtensionFunctions(it.singletonOrEmptyList(), name, location) } } } @@ -204,16 +211,17 @@ internal class SyntheticScopeBasedTowerLevel( } } - override fun getObjects(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection> - = emptyList() + override fun getObjects( + name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo? + ): Collection> = + emptyList() - override fun getFunctions(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection> { - if (extensionReceiver == null) return emptyList() + override fun getFunctions( + name: Name, + extensionReceiver: ReceiverValueWithSmartCastInfo? + ): Collection> = + emptyList() - return syntheticScopes.collectSyntheticExtensionFunctions(extensionReceiver.allTypes, name, location).map { - createCandidateDescriptor(it, dispatchReceiver = null) - } - } } internal class HidesMembersTowerLevel(scopeTower: ImplicitScopeTower): AbstractScopeTowerLevel(scopeTower) { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt index f45d4482f33..ef4923119c7 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt @@ -89,7 +89,7 @@ class TowerResolver { if (scope is LexicalScope) { if (!scope.kind.withLocalDescriptors) result.add(ScopeBasedTowerLevel(this, scope)) - getImplicitReceiver(scope)?.let { result.add(ReceiverScopeTowerLevel(this, it)) } + getImplicitReceiver(scope)?.let { result.add(MemberScopeTowerLevel(this, it)) } } else { result.add(ImportingScopeBasedTowerLevel(this, scope as ImportingScope)) @@ -119,7 +119,7 @@ class TowerResolver { TowerData.TowerLevel(hidesMembersLevel).process()?.let { return it } // possibly there is explicit member TowerData.Empty.process()?.let { return it } - // synthetic member for explicit receiver + // synthetic property for explicit receiver TowerData.TowerLevel(syntheticLevel).process()?.let { return it } // local non-extensions or extension for explicit receiver @@ -140,9 +140,9 @@ class TowerResolver { TowerData.BothTowerLevelAndImplicitReceiver(hidesMembersLevel, implicitReceiver).process()?.let { return it } // members of implicit receiver or member extension for explicit receiver - TowerData.TowerLevel(ReceiverScopeTowerLevel(this, implicitReceiver)).process()?.let { return it } + TowerData.TowerLevel(MemberScopeTowerLevel(this, implicitReceiver)).process()?.let { return it } - // synthetic members + // synthetic properties TowerData.BothTowerLevelAndImplicitReceiver(syntheticLevel, implicitReceiver).process()?.let { return it } // invokeExtension on local variable @@ -233,19 +233,17 @@ class TowerResolver { private var currentCandidates: Collection = emptyList() private var currentLevel: ResolutionCandidateApplicability? = null - override fun getSuccessfulCandidates(): Collection? = getResolved() ?: getResolvedSynthetic() + override fun getSuccessfulCandidates(): Collection? = getResolved() fun getResolved() = currentCandidates.check { currentLevel == ResolutionCandidateApplicability.RESOLVED } - fun getResolvedSynthetic() = currentCandidates.check { currentLevel == ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED } - fun getResolvedLowPriority() = currentCandidates.check { currentLevel == ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY } fun getErrors() = currentCandidates.check { currentLevel == null || currentLevel!! > ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY } - override fun getFinalCandidates() = getResolved() ?: getResolvedSynthetic() ?: getResolvedLowPriority() ?: getErrors() ?: emptyList() + override fun getFinalCandidates() = getResolved() ?: getResolvedLowPriority() ?: getErrors() ?: emptyList() override fun addCandidates(candidates: Collection) { val minimalLevel = candidates.map { getStatus(it).resultingApplicability }.min()!! diff --git a/compiler/testData/diagnostics/tests/j+k/samByProjectedType/genericInReturnType.kt b/compiler/testData/diagnostics/tests/j+k/samByProjectedType/genericInReturnType.kt index 96c6f57c812..8912bdade0e 100644 --- a/compiler/testData/diagnostics/tests/j+k/samByProjectedType/genericInReturnType.kt +++ b/compiler/testData/diagnostics/tests/j+k/samByProjectedType/genericInReturnType.kt @@ -47,6 +47,6 @@ fun main() { x -> x.toString() } - A.baz(block) + A.baz(block) A.baz(block2) } diff --git a/compiler/testData/diagnostics/tests/scopes/protectedVisibility/syntheticSAMExtensions.kt b/compiler/testData/diagnostics/tests/scopes/protectedVisibility/syntheticSAMExtensions.kt index dafd94ed2c9..f78f0593017 100644 --- a/compiler/testData/diagnostics/tests/scopes/protectedVisibility/syntheticSAMExtensions.kt +++ b/compiler/testData/diagnostics/tests/scopes/protectedVisibility/syntheticSAMExtensions.kt @@ -11,7 +11,7 @@ class Data(var x: A) class B : A() { fun baz(a: A, b: B, d: Data) { - a.foo { } + a.foo { } b.foo { } @@ -20,7 +20,7 @@ class B : A() { } if (d.x is B) { - d.x.foo {} + d.x.foo {} } } } diff --git a/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/InnerClassInGeneric.kt b/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/InnerClassInGeneric.kt index f99a6cd28f9..9a58bd55427 100644 --- a/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/InnerClassInGeneric.kt +++ b/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/InnerClassInGeneric.kt @@ -1,7 +1,7 @@ // FILE: KotlinFile.kt fun foo(javaClass: JavaClass): Int { val inner = javaClass.createInner() - return inner.doSomething(1, "") { } + return inner.doSomething(1, "") { } } // FILE: JavaClass.java diff --git a/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/Protected.kt b/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/Protected.kt index e5c45e0be05..0c42aaf1f66 100644 --- a/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/Protected.kt +++ b/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/Protected.kt @@ -12,7 +12,7 @@ fun foo(javaClass: JavaClass) { class X : JavaClass() { fun foo(other: JavaClass) { doSomething { bar() } - other.doSomething { bar() } + other.doSomething { bar() } } } @@ -21,4 +21,4 @@ fun bar(){} // FILE: JavaClass.java public class JavaClass { protected void doSomething(Runnable runnable) { runnable.run(); } -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/overloadResolution.kt b/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/overloadResolution.kt new file mode 100644 index 00000000000..ef369301d6e --- /dev/null +++ b/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/overloadResolution.kt @@ -0,0 +1,36 @@ +// !CHECK_TYPE +// FILE: A.java +public class A { + public int foo(Runnable r) { return 0; } + public String foo(Object r) { return null;} + + public int bar(Runnable r) { return 1; } + public String bar(CharSequence r) { return null; } +} + +// FILE: 1.kt +fun fn() {} +fun x(a: A, r: Runnable) { + a.foo(::fn) checkType { _() } + a.foo {} checkType { _() } + + a.foo(null) checkType { _() } + a.foo(Runnable { }) checkType { _() } + a.foo(r) checkType { _() } + + a.foo(123) checkType { _() } + a.foo("") checkType { _() } + + a.bar(::fn) checkType { _() } + a.bar {} checkType { _() } + + a.bar(r) checkType { _() } + + a.bar(null) + + a.bar(null as Runnable?) checkType { _() } + a.bar(null as CharSequence?) checkType { _() } + + a.bar("") checkType { _() } + a.bar(123) +} diff --git a/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/overloadResolution.txt b/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/overloadResolution.txt new file mode 100644 index 00000000000..c6b3ca874bd --- /dev/null +++ b/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/overloadResolution.txt @@ -0,0 +1,15 @@ +package + +public fun fn(): kotlin.Unit +public fun x(/*0*/ a: A, /*1*/ r: java.lang.Runnable): kotlin.Unit + +public open class A { + public constructor A() + public open fun bar(/*0*/ r: java.lang.Runnable!): kotlin.Int + public open fun bar(/*0*/ r: kotlin.CharSequence!): kotlin.String! + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun foo(/*0*/ r: java.lang.Runnable!): kotlin.Int + public open fun foo(/*0*/ r: kotlin.Any!): kotlin.String! + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/overloadResolutionStatic.kt b/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/overloadResolutionStatic.kt new file mode 100644 index 00000000000..eb2b0ffc892 --- /dev/null +++ b/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/overloadResolutionStatic.kt @@ -0,0 +1,36 @@ +// !CHECK_TYPE +// FILE: A.java +public class A { + public static int foo(Runnable r) { return 0; } + public static String foo(Object r) { return null;} + + public static int bar(Runnable r) { return 1; } + public static String bar(CharSequence r) { return null; } +} + +// FILE: 1.kt +fun fn() {} +fun x(r: Runnable) { + A.foo(::fn) checkType { _() } + A.foo {} checkType { _() } + + A.foo(null) checkType { _() } + A.foo(Runnable { }) checkType { _() } + A.foo(r) checkType { _() } + + A.foo(123) checkType { _() } + A.foo("") checkType { _() } + + A.bar(::fn) checkType { _() } + A.bar {} checkType { _() } + + A.bar(r) checkType { _() } + + A.bar(null) + + A.bar(null as Runnable?) checkType { _() } + A.bar(null as CharSequence?) checkType { _() } + + A.bar("") checkType { _() } + A.bar(123) +} diff --git a/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/overloadResolutionStatic.txt b/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/overloadResolutionStatic.txt new file mode 100644 index 00000000000..91eb6e2de87 --- /dev/null +++ b/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/overloadResolutionStatic.txt @@ -0,0 +1,19 @@ +package + +public fun fn(): kotlin.Unit +public fun x(/*0*/ r: java.lang.Runnable): kotlin.Unit + +public open class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun bar(/*0*/ r: (() -> kotlin.Unit)!): kotlin.Int + public open fun bar(/*0*/ r: java.lang.Runnable!): kotlin.Int + public open fun bar(/*0*/ r: kotlin.CharSequence!): kotlin.String! + public final /*synthesized*/ fun foo(/*0*/ r: (() -> kotlin.Unit)!): kotlin.Int + public open fun foo(/*0*/ r: java.lang.Runnable!): kotlin.Int + public open fun foo(/*0*/ r: kotlin.Any!): kotlin.String! +} diff --git a/compiler/testData/diagnostics/testsWithJava8/targetedBuiltIns/forEachRemainingNullability.kt b/compiler/testData/diagnostics/testsWithJava8/targetedBuiltIns/forEachRemainingNullability.kt index 02a97209289..faf6de77ee2 100644 --- a/compiler/testData/diagnostics/testsWithJava8/targetedBuiltIns/forEachRemainingNullability.kt +++ b/compiler/testData/diagnostics/testsWithJava8/targetedBuiltIns/forEachRemainingNullability.kt @@ -30,7 +30,7 @@ abstract class MyIt7 : Iterator { fun foo(x: Iterator, y: Iterator) { - x.forEachRemaining(null) + x.forEachRemaining(null) x.forEachRemaining { it -> it.length } x.forEachRemaining { it -> it?.length } diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 56ae965e6b1..6c47d02f717 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -20763,6 +20763,18 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("overloadResolution.kt") + public void testOverloadResolution() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/overloadResolution.kt"); + doTest(fileName); + } + + @TestMetadata("overloadResolutionStatic.kt") + public void testOverloadResolutionStatic() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/overloadResolutionStatic.kt"); + doTest(fileName); + } + @TestMetadata("PackageLocal.kt") public void testPackageLocal() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/PackageLocal.kt");