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 c8e9a607c03..b49f3cd79c8 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 @@ -46,11 +46,13 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.* import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy import org.jetbrains.kotlin.types.DeferredType import org.jetbrains.kotlin.types.ErrorUtils +import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.isDynamic import org.jetbrains.kotlin.types.typeUtil.containsError import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.utils.addToStdlib.check import org.jetbrains.kotlin.utils.sure +import java.util.* class NewResolutionOldInference( private val candidateResolver: CandidateResolver, @@ -66,14 +68,14 @@ class NewResolutionOldInference( name: Name, tracing: TracingStrategy, scopeTower: ScopeTower, - explicitReceiver: Receiver?, + explicitReceiver: DetailedReceiver?, context: BasicCallResolutionContext ): ScopeTowerProcessor> object Function : ResolutionKind() { override fun createTowerProcessor( outer: NewResolutionOldInference, name: Name, tracing: TracingStrategy, - scopeTower: ScopeTower, explicitReceiver: Receiver?, context: BasicCallResolutionContext + scopeTower: ScopeTower, explicitReceiver: DetailedReceiver?, context: BasicCallResolutionContext ): ScopeTowerProcessor> { val functionContext = outer.SimpleContext(scopeTower, name, context, tracing) return createFunctionProcessor(functionContext, outer.InvokeContext(functionContext), explicitReceiver) @@ -83,7 +85,7 @@ class NewResolutionOldInference( object Variable : ResolutionKind() { override fun createTowerProcessor( outer: NewResolutionOldInference, name: Name, tracing: TracingStrategy, - scopeTower: ScopeTower, explicitReceiver: Receiver?, context: BasicCallResolutionContext + scopeTower: ScopeTower, explicitReceiver: DetailedReceiver?, context: BasicCallResolutionContext ): ScopeTowerProcessor> { val simpleContext = outer.SimpleContext(scopeTower, name, context, tracing) return createVariableAndObjectProcessor(simpleContext, explicitReceiver) @@ -93,7 +95,7 @@ class NewResolutionOldInference( object CallableReference : ResolutionKind() { override fun createTowerProcessor( outer: NewResolutionOldInference, name: Name, tracing: TracingStrategy, - scopeTower: ScopeTower, explicitReceiver: Receiver?, context: BasicCallResolutionContext + scopeTower: ScopeTower, explicitReceiver: DetailedReceiver?, context: BasicCallResolutionContext ): ScopeTowerProcessor> { val simpleContextF = outer.SimpleContext(scopeTower, name, context, tracing) val simpleContextV = outer.SimpleContext(scopeTower, name, context, tracing) @@ -107,7 +109,7 @@ class NewResolutionOldInference( object Invoke : ResolutionKind() { override fun createTowerProcessor( outer: NewResolutionOldInference, name: Name, tracing: TracingStrategy, - scopeTower: ScopeTower, explicitReceiver: Receiver?, context: BasicCallResolutionContext + scopeTower: ScopeTower, explicitReceiver: DetailedReceiver?, context: BasicCallResolutionContext ): ScopeTowerProcessor> { val functionContext = outer.SimpleContext(scopeTower, name, context, tracing) // todo @@ -115,7 +117,7 @@ class NewResolutionOldInference( "Call should be CallForImplicitInvoke, but it is: ${context.call}" } return createProcessorWithReceiverValueOrEmpty(explicitReceiver) { - createCallTowerProcessorForExplicitInvoke(functionContext, call.dispatchReceiver, it) + createCallTowerProcessorForExplicitInvoke(functionContext, context.transformToReceiverWithSmartCastInfo(call.dispatchReceiver), it) } } @@ -124,7 +126,7 @@ class NewResolutionOldInference( class GivenCandidates : ResolutionKind() { override fun createTowerProcessor( outer: NewResolutionOldInference, name: Name, tracing: TracingStrategy, - scopeTower: ScopeTower, explicitReceiver: Receiver?, context: BasicCallResolutionContext + scopeTower: ScopeTower, explicitReceiver: DetailedReceiver?, context: BasicCallResolutionContext ): ScopeTowerProcessor> { throw IllegalStateException("Should be not called") } @@ -138,11 +140,17 @@ class NewResolutionOldInference( tracing: TracingStrategy ): OverloadResolutionResultsImpl { val explicitReceiver = context.call.explicitReceiver + val detailedReceiver = if (explicitReceiver is QualifierReceiver?) { + explicitReceiver + } + else { + context.transformToReceiverWithSmartCastInfo(explicitReceiver as ReceiverValue) + } val dynamicScope = dynamicCallableDescriptors.createDynamicDescriptorScope(context.call, context.scope.ownerDescriptor) val scopeTower = ScopeTowerImpl(context, dynamicScope, syntheticScopes, context.call.createLookupLocation()) - val processor = kind.createTowerProcessor(this, name, tracing, scopeTower, explicitReceiver, context) + val processor = kind.createTowerProcessor(this, name, tracing, scopeTower, detailedReceiver, context) if (context.collectAllCandidates) { return allCandidatesResult(towerResolver.collectAllCandidates(scopeTower, processor)) @@ -240,18 +248,15 @@ class NewResolutionOldInference( override val syntheticScopes: SyntheticScopes, override val location: LookupLocation ): ScopeTower { - override val dataFlowInfo: DataFlowDecorator = object : DataFlowDecorator() { - override fun calculateSmartCastInfo(receiver: ReceiverValue): SmartCastInfo { - val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiver, resolutionContext) - return SmartCastInfo(dataFlowValue.isStable, resolutionContext.dataFlowInfo.getCollectedTypes(dataFlowValue)) - } - } + private val cache = HashMap() + + override fun getImplicitReceiver(scope: LexicalScope): ReceiverValueWithSmartCastInfo? = + scope.implicitReceiver?.value?.let { + cache.getOrPut(it) { resolutionContext.transformToReceiverWithSmartCastInfo(it) } + } override val lexicalScope: LexicalScope get() = resolutionContext.scope - override val implicitReceivers = resolutionContext.scope.getImplicitReceiversHierarchy(). - mapNotNull { it.value.check { !it.type.containsError() } } - override val isDebuggerContext: Boolean get() = resolutionContext.isDebuggerContext } @@ -277,18 +282,19 @@ class NewResolutionOldInference( override fun createCandidate( towerCandidate: CandidateWithBoundDispatchReceiver, explicitReceiverKind: ExplicitReceiverKind, - extensionReceiver: ReceiverValue? + extensionReceiver: ReceiverValueWithSmartCastInfo? ): MyCandidate { + val candidateTrace = TemporaryBindingTrace.create(basicCallContext.trace, "Context for resolve candidate") val candidateCall = ResolvedCallImpl( basicCallContext.call, towerCandidate.descriptor, - towerCandidate.dispatchReceiver, extensionReceiver, + towerCandidate.dispatchReceiver?.receiverValue, extensionReceiver?.receiverValue, explicitReceiverKind, null, candidateTrace, tracing, basicCallContext.dataFlowInfoForArguments // todo may be we should create new mutable info for arguments ) // see spec-docs/dynamic-types.md - if (extensionReceiver != null && extensionReceiver.type.isDynamic() + if (extensionReceiver != null && extensionReceiver.receiverValue.type.isDynamic() && !towerCandidate.descriptor.extensionReceiverParameter!!.value.type.isDynamic()) { return MyCandidate(ResolutionCandidateStatus(listOf(ExtensionWithStaticTypeWithDynamicReceiver)), candidateCall) } @@ -351,7 +357,7 @@ class NewResolutionOldInference( override fun contextForInvoke( variable: MyCandidate, useExplicitReceiver: Boolean - ): Pair>>? { + ): Pair>>? { assert(variable.resolvedCall.status.possibleTransformToSuccess()) { "Incorrect status: ${variable.resolvedCall.status} for variable call: ${variable.resolvedCall} " + "and descriptor: ${variable.resolvedCall.candidateDescriptor}" @@ -381,17 +387,20 @@ class NewResolutionOldInference( .replaceCall(functionCall) .replaceContextDependency(ContextDependency.DEPENDENT) // todo - val scopeTower = functionContext.scopeTower - val newScopeTower = ScopeTowerImpl(basicCallResolutionContext, scopeTower.dynamicScope, scopeTower.syntheticScopes, scopeTower.location) - val newContext = SimpleContext(newScopeTower, OperatorNameConventions.INVOKE, basicCallResolutionContext, tracingForInvoke) + val newContext = SimpleContext(functionContext.scopeTower, OperatorNameConventions.INVOKE, basicCallResolutionContext, tracingForInvoke) - return variableReceiver to newContext + return basicCallResolutionContext.transformToReceiverWithSmartCastInfo(variableReceiver) to newContext } } } +private fun ResolutionContext<*>.transformToReceiverWithSmartCastInfo(receiver: ReceiverValue): ReceiverValueWithSmartCastInfo { + val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiver, this) + return ReceiverValueWithSmartCastInfo(receiver, dataFlowInfo.getCollectedTypes(dataFlowValue), dataFlowValue.isStable) +} + @Deprecated("Temporary error") internal class PreviousResolutionError(candidateLevel: ResolutionCandidateApplicability): ResolutionDiagnostic(candidateLevel) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/InvokeProcessors.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/InvokeProcessors.kt index 7e28f4ca348..baed9c64c02 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/InvokeProcessors.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/InvokeProcessors.kt @@ -21,8 +21,8 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tasks.createSynthesizedInvokes -import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver -import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue +import org.jetbrains.kotlin.resolve.scopes.receivers.DetailedReceiver +import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo import org.jetbrains.kotlin.util.OperatorNameConventions import java.util.* @@ -87,7 +87,7 @@ abstract class AbstractInvokeTowerProcessor, V // todo KT-9522 Allow invoke convention for synthetic property class InvokeTowerProcessor, V : Candidate>( invokeContext: InvokeTowerContext, - explicitReceiver: Receiver? + explicitReceiver: DetailedReceiver? ) : AbstractInvokeTowerProcessor( invokeContext, createVariableAndObjectProcessor(invokeContext.contextForVariable(stripExplicitReceiver = false), explicitReceiver) @@ -103,7 +103,7 @@ class InvokeTowerProcessor, V : Candidate, V : Candidate>( invokeContext: InvokeTowerContext, - private val explicitReceiver: ReceiverValue? + private val explicitReceiver: ReceiverValueWithSmartCastInfo? ) : AbstractInvokeTowerProcessor( invokeContext, createVariableAndObjectProcessor(invokeContext.contextForVariable(stripExplicitReceiver = true), explicitReceiver = null) @@ -121,7 +121,7 @@ class InvokeExtensionTowerProcessor, V : Candi private class InvokeExtensionScopeTowerProcessor>( context: TowerContext, private val invokeCandidateDescriptor: CandidateWithBoundDispatchReceiver, - private val explicitReceiver: ReceiverValue? + private val explicitReceiver: ReceiverValueWithSmartCastInfo? ) : AbstractSimpleScopeTowerProcessor(context) { override fun simpleProcess(data: TowerData): Collection { @@ -139,11 +139,12 @@ private class InvokeExtensionScopeTowerProcessor? { - if (!extensionFunctionReceiver.type.isExtensionFunctionType) return null + val type = extensionFunctionReceiver.receiverValue.type + if (!type.isExtensionFunctionType) return null // todo: missing smart cast? - val invokeDescriptor = extensionFunctionReceiver.type.memberScope.getContributedFunctions(OperatorNameConventions.INVOKE, location).single() + val invokeDescriptor = type.memberScope.getContributedFunctions(OperatorNameConventions.INVOKE, location).single() val synthesizedInvoke = createSynthesizedInvokes(listOf(invokeDescriptor)).single() // here we don't add SynthesizedDescriptor diagnostic because it should has priority as member @@ -153,8 +154,8 @@ private fun ScopeTower.getExtensionInvokeCandidateDescriptor( // case 1.(foo())() or (foo())() fun > createCallTowerProcessorForExplicitInvoke( functionContext: TowerContext, - expressionForInvoke: ReceiverValue, - explicitReceiver: ReceiverValue? + expressionForInvoke: ReceiverValueWithSmartCastInfo, + explicitReceiver: ReceiverValueWithSmartCastInfo? ): ScopeTowerProcessor { val invokeExtensionDescriptor = functionContext.scopeTower.getExtensionInvokeCandidateDescriptor(expressionForInvoke) if (explicitReceiver != null) { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTower.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTower.kt index 9c82324d4f7..624fb86a701 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTower.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTower.kt @@ -22,52 +22,29 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes -import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue +import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo import org.jetbrains.kotlin.types.KotlinType -import java.util.* interface ScopeTower { - /** - * Adds receivers to the list in order of locality, so that the closest (the most local) receiver goes first - * Doesn't include receivers with error types - */ - val implicitReceivers: List - val lexicalScope: LexicalScope + fun getImplicitReceiver(scope: LexicalScope): ReceiverValueWithSmartCastInfo? + val dynamicScope: MemberScope val syntheticScopes: SyntheticScopes val location: LookupLocation - val dataFlowInfo: DataFlowDecorator - val isDebuggerContext: Boolean } -abstract class DataFlowDecorator() { - private val cache = HashMap() - - fun isStableReceiver(receiver: ReceiverValue): Boolean = getSmartCastInfo(receiver).isStable - // doesn't include receiver.type - fun getSmartCastTypes(receiver: ReceiverValue): Set = getSmartCastInfo(receiver).possibleTypes - - - private fun getSmartCastInfo(receiver: ReceiverValue): SmartCastInfo - = cache.getOrPut(receiver) { calculateSmartCastInfo(receiver) } - - protected data class SmartCastInfo(val isStable: Boolean, val possibleTypes: Set) - - protected abstract fun calculateSmartCastInfo(receiver: ReceiverValue): SmartCastInfo -} - interface ScopeTowerLevel { - fun getVariables(name: Name, extensionReceiver: ReceiverValue?): Collection> + fun getVariables(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection> - fun getObjects(name: Name, extensionReceiver: ReceiverValue?): Collection> + fun getObjects(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection> - fun getFunctions(name: Name, extensionReceiver: ReceiverValue?): Collection> + fun getFunctions(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection> } interface CandidateWithBoundDispatchReceiver { @@ -75,7 +52,7 @@ interface CandidateWithBoundDispatchReceiver { val diagnostics: List - val dispatchReceiver: ReceiverValue? + val dispatchReceiver: ReceiverValueWithSmartCastInfo? fun copy(newDescriptor: @UnsafeVariance D): CandidateWithBoundDispatchReceiver } 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 dddbfdd6a27..fbc2264bd28 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 @@ -23,9 +23,7 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.coroutine.CoroutineReceiverValue import org.jetbrains.kotlin.resolve.coroutine.createCoroutineSuspensionFunctionView -import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver -import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver -import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue +import org.jetbrains.kotlin.resolve.scopes.receivers.* import org.jetbrains.kotlin.utils.addToStdlib.check @@ -54,8 +52,8 @@ internal abstract class AbstractSimpleScopeTowerProcessor>( context: TowerContext, - val explicitReceiver: ReceiverValue, - val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection> + val explicitReceiver: ReceiverValueWithSmartCastInfo, + val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) -> Collection> ): AbstractSimpleScopeTowerProcessor(context) { override fun simpleProcess(data: TowerData): Collection { return when (data) { @@ -80,7 +78,7 @@ internal class ExplicitReceiverScopeTowerProcessor>( context: TowerContext, val qualifier: QualifierReceiver, - val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection> + val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) -> Collection> ): AbstractSimpleScopeTowerProcessor(context) { override fun simpleProcess(data: TowerData): Collection { if (data != TowerData.Empty) return emptyList() @@ -94,7 +92,7 @@ private class QualifierScopeTowerProcessor>( context: TowerContext, - val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection> + val collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) -> Collection> ) : AbstractSimpleScopeTowerProcessor(context) { override fun simpleProcess(data: TowerData): Collection = when(data) { @@ -111,7 +109,7 @@ private class NoExplicitReceiverScopeTowerProcessor> createSimpleProcessor( context: TowerContext, - explicitReceiver: Receiver?, + explicitReceiver: DetailedReceiver?, classValueReceiver: Boolean, - collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection> + collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) -> Collection> ) : ScopeTowerProcessor { - if (explicitReceiver is ReceiverValue) { + if (explicitReceiver is ReceiverValueWithSmartCastInfo) { return ExplicitReceiverScopeTowerProcessor(context, explicitReceiver, collectCandidates) } else if (explicitReceiver is QualifierReceiver) { @@ -140,7 +138,7 @@ private fun > createSimpleProcessor( if (!classValueReceiver) return qualifierProcessor // todo enum entry, object. - val classValue = explicitReceiver.classValueReceiver ?: return qualifierProcessor + val classValue = explicitReceiver.classValueReceiverWithSmartCastInfo ?: return qualifierProcessor return CompositeScopeTowerProcessor( qualifierProcessor, ExplicitReceiverScopeTowerProcessor(context, classValue, collectCandidates) @@ -155,25 +153,25 @@ private fun > createSimpleProcessor( } fun > createVariableProcessor( - context: TowerContext, explicitReceiver: Receiver?, classValueReceiver: Boolean = true + context: TowerContext, explicitReceiver: DetailedReceiver?, classValueReceiver: Boolean = true ) = createSimpleProcessor(context, explicitReceiver, classValueReceiver, ScopeTowerLevel::getVariables) fun > createVariableAndObjectProcessor( - context: TowerContext, explicitReceiver: Receiver?, classValueReceiver: Boolean = true + context: TowerContext, explicitReceiver: DetailedReceiver?, classValueReceiver: Boolean = true ) = CompositeScopeTowerProcessor( createVariableProcessor(context, explicitReceiver), createSimpleProcessor(context, explicitReceiver, classValueReceiver, ScopeTowerLevel::getObjects) ) fun > createSimpleFunctionProcessor( - context: TowerContext, explicitReceiver: Receiver?, classValueReceiver: Boolean = true + context: TowerContext, explicitReceiver: DetailedReceiver?, classValueReceiver: Boolean = true ) = createSimpleProcessor(context, explicitReceiver, classValueReceiver, ScopeTowerLevel::getFunctions) fun , V: Candidate> createFunctionProcessor( simpleContext: TowerContext, invokeContext: InvokeTowerContext, - explicitReceiver: Receiver? + explicitReceiver: DetailedReceiver? ): CompositeScopeTowerProcessor { // a.foo() -- simple function call @@ -190,14 +188,14 @@ fun , V: Candidate> createF fun > createProcessorWithReceiverValueOrEmpty( - explicitReceiver: Receiver?, - create: (ReceiverValue?) -> ScopeTowerProcessor + explicitReceiver: DetailedReceiver?, + create: (ReceiverValueWithSmartCastInfo?) -> ScopeTowerProcessor ): ScopeTowerProcessor { return if (explicitReceiver is QualifierReceiver) { - explicitReceiver.classValueReceiver?.let(create) + explicitReceiver.classValueReceiverWithSmartCastInfo?.let(create) ?: KnownResultProcessor(listOf()) } else { - create(explicitReceiver as ReceiverValue?) + create(explicitReceiver as ReceiverValueWithSmartCastInfo?) } } \ No newline at end of file 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 9cd5a37b5e9..737fda7ec59 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 @@ -29,10 +29,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.hasClassValueDescriptor import org.jetbrains.kotlin.resolve.descriptorUtil.hasHidesMembersAnnotation import org.jetbrains.kotlin.resolve.descriptorUtil.hasLowPriorityInOverloadResolution import org.jetbrains.kotlin.resolve.scopes.* -import org.jetbrains.kotlin.resolve.scopes.receivers.CastImplicitClassReceiver -import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver -import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver -import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue +import org.jetbrains.kotlin.resolve.scopes.receivers.* import org.jetbrains.kotlin.resolve.scopes.utils.collectFunctions import org.jetbrains.kotlin.resolve.scopes.utils.collectVariables import org.jetbrains.kotlin.resolve.selectMostSpecificInEachOverridableGroup @@ -49,7 +46,7 @@ internal abstract class AbstractScopeTowerLevel( protected fun createCandidateDescriptor( descriptor: D, - dispatchReceiver: ReceiverValue?, + dispatchReceiver: ReceiverValueWithSmartCastInfo?, specialError: ResolutionDiagnostic? = null, dispatchReceiverSmartCastType: KotlinType? = null ): CandidateWithBoundDispatchReceiver { @@ -67,7 +64,7 @@ internal abstract class AbstractScopeTowerLevel( val shouldSkipVisibilityCheck = scopeTower.isDebuggerContext if (!shouldSkipVisibilityCheck) { Visibilities.findInvisibleMember( - getReceiverValueWithSmartCast(dispatchReceiver, dispatchReceiverSmartCastType), + getReceiverValueWithSmartCast(dispatchReceiver?.receiverValue, dispatchReceiverSmartCastType), descriptor, scopeTower.lexicalScope.ownerDescriptor )?.let { diagnostics.add(VisibilityError(it)) } @@ -82,28 +79,28 @@ internal abstract class AbstractScopeTowerLevel( // todo add static methods & fields with error internal class ReceiverScopeTowerLevel( scopeTower: ScopeTower, - val dispatchReceiver: ReceiverValue + val dispatchReceiver: ReceiverValueWithSmartCastInfo ): AbstractScopeTowerLevel(scopeTower) { private fun collectMembers( getMembers: ResolutionScope.(KotlinType?) -> Collection ): Collection> { val result = ArrayList>(0) - dispatchReceiver.type.memberScope.getMembers(dispatchReceiver.type).mapTo(result) { + val receiverValue = dispatchReceiver.receiverValue + receiverValue.type.memberScope.getMembers(receiverValue.type).mapTo(result) { createCandidateDescriptor(it, dispatchReceiver) } - val smartCastPossibleTypes = scopeTower.dataFlowInfo.getSmartCastTypes(dispatchReceiver) - val unstableError = if (scopeTower.dataFlowInfo.isStableReceiver(dispatchReceiver)) null else UnstableSmartCastDiagnostic + val unstableError = if (dispatchReceiver.isStable) null else UnstableSmartCastDiagnostic val unstableCandidates = if (unstableError != null) ArrayList>(0) else null - for (possibleType in smartCastPossibleTypes) { + for (possibleType in dispatchReceiver.possibleTypes) { possibleType.memberScope.getMembers(possibleType).mapTo(unstableCandidates ?: result) { createCandidateDescriptor(it, dispatchReceiver.smartCastReceiver(possibleType), unstableError, dispatchReceiverSmartCastType = possibleType) } } - if (smartCastPossibleTypes.isNotEmpty()) { + if (dispatchReceiver.possibleTypes.isNotEmpty()) { if (unstableCandidates == null) { result.retainAll(result.selectMostSpecificInEachOverridableGroup { descriptor }) } @@ -112,13 +109,13 @@ internal class ReceiverScopeTowerLevel( } } - if (dispatchReceiver.type.isDynamic()) { + if (receiverValue.type.isDynamic()) { scopeTower.dynamicScope.getMembers(null).mapTo(result) { createCandidateDescriptor(it, dispatchReceiver, DynamicDescriptorDiagnostic) } } - if (dispatchReceiver is CoroutineReceiverValue) { + if (receiverValue is CoroutineReceiverValue) { result.addAll(result.mapNotNull { val suspensionFunctionView = it.descriptor.createCoroutineSuspensionFunctionView() ?: return@mapNotNull null createCandidateDescriptor(suspensionFunctionView, dispatchReceiver) @@ -128,18 +125,22 @@ internal class ReceiverScopeTowerLevel( return result } - private fun ReceiverValue.smartCastReceiver(targetType: KotlinType) - = if (this is ImplicitClassReceiver) CastImplicitClassReceiver(this.classDescriptor, targetType) else this + private fun ReceiverValueWithSmartCastInfo.smartCastReceiver(targetType: KotlinType): ReceiverValueWithSmartCastInfo { + if (receiverValue !is ImplicitClassReceiver) return this - override fun getVariables(name: Name, extensionReceiver: ReceiverValue?): Collection> { + val newReceiverValue = CastImplicitClassReceiver(receiverValue.classDescriptor, targetType) + return ReceiverValueWithSmartCastInfo(newReceiverValue, possibleTypes, isStable) + } + + override fun getVariables(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection> { return collectMembers { getContributedVariables(name, location) } } - override fun getObjects(name: Name, extensionReceiver: ReceiverValue?): Collection> { + override fun getObjects(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection> { return emptyList() } - override fun getFunctions(name: Name, extensionReceiver: ReceiverValue?): Collection> { + override fun getFunctions(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection> { return collectMembers { getContributedFunctions(name, location) + it.getInnerConstructors(name, location) } @@ -147,17 +148,17 @@ internal class ReceiverScopeTowerLevel( } internal class QualifierScopeTowerLevel(scopeTower: ScopeTower, val qualifier: QualifierReceiver) : AbstractScopeTowerLevel(scopeTower) { - override fun getVariables(name: Name, extensionReceiver: ReceiverValue?) = qualifier.staticScope + override fun getVariables(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) = qualifier.staticScope .getContributedVariables(name, location).map { createCandidateDescriptor(it, dispatchReceiver = null) } - override fun getObjects(name: Name, extensionReceiver: ReceiverValue?) = qualifier.staticScope + override fun getObjects(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) = qualifier.staticScope .getContributedObjectVariables(name, location).map { createCandidateDescriptor(it, dispatchReceiver = null) } - override fun getFunctions(name: Name, extensionReceiver: ReceiverValue?) = qualifier.staticScope + override fun getFunctions(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) = qualifier.staticScope .getContributedFunctionsAndConstructors(name, location).map { createCandidateDescriptor(it, dispatchReceiver = null) } @@ -171,17 +172,17 @@ internal open class ScopeBasedTowerLevel protected constructor( internal constructor(scopeTower: ScopeTower, lexicalScope: LexicalScope): this(scopeTower, lexicalScope as ResolutionScope) - override fun getVariables(name: Name, extensionReceiver: ReceiverValue?): Collection> + override fun getVariables(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection> = resolutionScope.getContributedVariables(name, location).map { createCandidateDescriptor(it, dispatchReceiver = null) } - override fun getObjects(name: Name, extensionReceiver: ReceiverValue?): Collection> + override fun getObjects(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection> = resolutionScope.getContributedObjectVariables(name, location).map { createCandidateDescriptor(it, dispatchReceiver = null) } - override fun getFunctions(name: Name, extensionReceiver: ReceiverValue?): Collection> + override fun getFunctions(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection> = resolutionScope.getContributedFunctionsAndConstructors(name, location).map { createCandidateDescriptor(it, dispatchReceiver = null) } @@ -195,41 +196,42 @@ internal class SyntheticScopeBasedTowerLevel( scopeTower: ScopeTower, private val syntheticScopes: SyntheticScopes ): AbstractScopeTowerLevel(scopeTower) { - override fun getVariables(name: Name, extensionReceiver: ReceiverValue?): Collection> { + private val ReceiverValueWithSmartCastInfo.allTypes: Set + get() = possibleTypes + receiverValue.type + + override fun getVariables(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection> { if (extensionReceiver == null) return emptyList() - val extensionReceiverTypes = scopeTower.dataFlowInfo.getAllPossibleTypes(extensionReceiver) - return syntheticScopes.collectSyntheticExtensionProperties(extensionReceiverTypes, name, location).map { + return syntheticScopes.collectSyntheticExtensionProperties(extensionReceiver.allTypes, name, location).map { createCandidateDescriptor(it, dispatchReceiver = null) } } - override fun getObjects(name: Name, extensionReceiver: ReceiverValue?): Collection> + override fun getObjects(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection> = emptyList() - override fun getFunctions(name: Name, extensionReceiver: ReceiverValue?): Collection> { + override fun getFunctions(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?): Collection> { if (extensionReceiver == null) return emptyList() - val extensionReceiverTypes = scopeTower.dataFlowInfo.getAllPossibleTypes(extensionReceiver) - return syntheticScopes.collectSyntheticExtensionFunctions(extensionReceiverTypes, name, location).map { + return syntheticScopes.collectSyntheticExtensionFunctions(extensionReceiver.allTypes, name, location).map { createCandidateDescriptor(it, dispatchReceiver = null) } } } internal class HidesMembersTowerLevel(scopeTower: ScopeTower): AbstractScopeTowerLevel(scopeTower) { - override fun getVariables(name: Name, extensionReceiver: ReceiverValue?) + override fun getVariables(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) = getCandidates(name, extensionReceiver, LexicalScope::collectVariables) - override fun getObjects(name: Name, extensionReceiver: ReceiverValue?) + override fun getObjects(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) = emptyList>() - override fun getFunctions(name: Name, extensionReceiver: ReceiverValue?) + override fun getFunctions(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) = getCandidates(name, extensionReceiver, LexicalScope::collectFunctions) private fun getCandidates( name: Name, - extensionReceiver: ReceiverValue?, + extensionReceiver: ReceiverValueWithSmartCastInfo?, collectCandidates: LexicalScope.(Name, LookupLocation) -> Collection ): Collection> { if (extensionReceiver == null || name !in HIDES_MEMBERS_NAME_LIST) return emptyList() 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 09c2f02d7fb..243a8934bcf 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 @@ -24,7 +24,7 @@ import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStat import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.scopes.ImportingScope import org.jetbrains.kotlin.resolve.scopes.LexicalScope -import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue +import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf import org.jetbrains.kotlin.utils.addToStdlib.check import java.util.* @@ -45,7 +45,7 @@ interface TowerContext> { fun createCandidate( towerCandidate: CandidateWithBoundDispatchReceiver, explicitReceiverKind: ExplicitReceiverKind, - extensionReceiver: ReceiverValue? + extensionReceiver: ReceiverValueWithSmartCastInfo? ): C } @@ -57,14 +57,14 @@ interface InvokeTowerContext, V : Candidate ReceiverValue(foo), context for invoke // null means that there is no invoke on variable - fun contextForInvoke(variable: V, useExplicitReceiver: Boolean): Pair>? + fun contextForInvoke(variable: V, useExplicitReceiver: Boolean): Pair>? } sealed class TowerData { object Empty : TowerData() - class OnlyImplicitReceiver(val implicitReceiver: ReceiverValue): TowerData() + class OnlyImplicitReceiver(val implicitReceiver: ReceiverValueWithSmartCastInfo): TowerData() class TowerLevel(val level: ScopeTowerLevel) : TowerData() - class BothTowerLevelAndImplicitReceiver(val level: ScopeTowerLevel, val implicitReceiver: ReceiverValue) : TowerData() + class BothTowerLevelAndImplicitReceiver(val level: ScopeTowerLevel, val implicitReceiver: ReceiverValueWithSmartCastInfo) : TowerData() } interface ScopeTowerProcessor { @@ -93,7 +93,7 @@ class TowerResolver { if (scope is LexicalScope) { if (!scope.kind.withLocalDescriptors) result.add(ScopeBasedTowerLevel(this, scope)) - scope.implicitReceiver?.let { result.add(ReceiverScopeTowerLevel(this, it.value)) } + getImplicitReceiver(scope)?.let { result.add(ReceiverScopeTowerLevel(this, it)) } } else { result.add(ImportingScopeBasedTowerLevel(this, scope as ImportingScope)) @@ -138,7 +138,7 @@ class TowerResolver { TowerData.TowerLevel(ScopeBasedTowerLevel(this, scope)).process()?.let { return it } } - val implicitReceiver = scope.implicitReceiver?.value + val implicitReceiver = getImplicitReceiver(scope) if (implicitReceiver != null) { // hides members extensions TowerData.BothTowerLevelAndImplicitReceiver(hidesMembersLevel, implicitReceiver).process()?.let { return it } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerUtils.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerUtils.kt index b084bc260d2..e235ec1705f 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerUtils.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerUtils.kt @@ -18,7 +18,7 @@ package org.jetbrains.kotlin.resolve.calls.tower import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor -import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue +import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo val ResolutionCandidateApplicability.isSuccess: Boolean get() = this <= ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY @@ -29,10 +29,8 @@ val CallableDescriptor.isSynthesized: Boolean val CandidateWithBoundDispatchReceiver<*>.requiresExtensionReceiver: Boolean get() = descriptor.extensionReceiverParameter != null -fun DataFlowDecorator.getAllPossibleTypes(receiver: ReceiverValue) = getSmartCastTypes(receiver) + receiver.type - internal class CandidateWithBoundDispatchReceiverImpl( - override val dispatchReceiver: ReceiverValue?, + override val dispatchReceiver: ReceiverValueWithSmartCastInfo?, override val descriptor: D, override val diagnostics: List ) : CandidateWithBoundDispatchReceiver { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/receivers/QualifierReceiver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/receivers/QualifierReceiver.kt index 61d89e51d95..ce8dde58a71 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/receivers/QualifierReceiver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/receivers/QualifierReceiver.kt @@ -18,11 +18,26 @@ package org.jetbrains.kotlin.resolve.scopes.receivers import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.types.KotlinType -interface QualifierReceiver : Receiver { +// this receiver used only for resolution. see subtypes +interface DetailedReceiver + +class ReceiverValueWithSmartCastInfo( + val receiverValue: ReceiverValue, + val possibleTypes: Set, // doesn't include receiver.type + val isStable: Boolean +): DetailedReceiver + + +interface QualifierReceiver : Receiver, DetailedReceiver { val descriptor: DeclarationDescriptor val staticScope: MemberScope val classValueReceiver: ReceiverValue? + + // for qualifiers smart cast is impossible + val classValueReceiverWithSmartCastInfo: ReceiverValueWithSmartCastInfo? + get() = classValueReceiver?.let { ReceiverValueWithSmartCastInfo(it, emptySet(), true) } } \ No newline at end of file