Base dynamic support in new resolve

This commit is contained in:
Stanislav Erokhin
2015-11-27 14:38:39 +03:00
parent 2987576a0a
commit e92c314b46
4 changed files with 32 additions and 6 deletions
@@ -35,10 +35,13 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallImpl
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCallImpl
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl
import org.jetbrains.kotlin.resolve.calls.results.ResolutionResultsHandler
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
import org.jetbrains.kotlin.resolve.calls.tasks.DynamicCallableDescriptors
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategyForInvoke
import org.jetbrains.kotlin.resolve.scopes.receivers.*
import org.jetbrains.kotlin.types.isDynamic
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addToStdlib.check
import org.jetbrains.kotlin.utils.sure
@@ -46,7 +49,8 @@ import org.jetbrains.kotlin.utils.sure
class NewResolveOldInference(
val candidateResolver: CandidateResolver,
val towerResolver: TowerResolver,
val resolutionResultsHandler: ResolutionResultsHandler
val resolutionResultsHandler: ResolutionResultsHandler,
val dynamicCallableDescriptors: DynamicCallableDescriptors
) {
fun runResolve(
@@ -57,7 +61,8 @@ class NewResolveOldInference(
): OverloadResolutionResultsImpl<*> {
val explicitReceiver = context.call.explicitReceiver.check { it.exists() }
val scopeTower = ScopeTowerImpl(context, explicitReceiver, context.call.createLookupLocation())
val dynamicScope = dynamicCallableDescriptors.createDynamicDescriptorScope(context.call, context.scope.ownerDescriptor)
val scopeTower = ScopeTowerImpl(context, dynamicScope, explicitReceiver, context.call.createLookupLocation())
val baseContext = Context(scopeTower, name, context, tracing)
@@ -74,7 +79,7 @@ class NewResolveOldInference(
val call = (context.call as? CallTransformer.CallForImplicitInvoke).sure {
"Call should be CallForImplicitInvoke, but it is: ${context.call}"
}
createCollectorWithReceiverValueOrEmpty(explicitReceiver) {
createProcessorWithReceiverValueOrEmpty(explicitReceiver) {
createCallTowerProcessorForExplicitInvoke(baseContext, call.dispatchReceiver, it)
}
}
@@ -87,7 +92,7 @@ class NewResolveOldInference(
return convertToOverloadResults(candidates, tracing, context)
}
private fun createCollectorWithReceiverValueOrEmpty(
private fun createProcessorWithReceiverValueOrEmpty(
explicitReceiver: Receiver?,
create: (ReceiverValue?) -> ScopeTowerProcessor<Candidate>
): ScopeTowerProcessor<Candidate> {
@@ -100,7 +105,6 @@ class NewResolveOldInference(
}
}
private fun createFunctionTowerProcessor(baseContext: Context, explicitReceiver: Receiver?): CompositeScopeTowerProcessor<Candidate> {
// a.foo() -- simple function call
val simpleFunction = createFunctionProcessor(baseContext, explicitReceiver)
@@ -109,7 +113,7 @@ class NewResolveOldInference(
val invokeProcessor = InvokeTowerProcessor(baseContext, explicitReceiver)
// a.foo() -- property foo is extension function with receiver a -- a.invoke()
val invokeExtensionProcessor = createCollectorWithReceiverValueOrEmpty(explicitReceiver) { InvokeExtensionTowerProcessor(baseContext, it) }
val invokeExtensionProcessor = createProcessorWithReceiverValueOrEmpty(explicitReceiver) { InvokeExtensionTowerProcessor(baseContext, it) }
return CompositeScopeTowerProcessor(simpleFunction, invokeProcessor, invokeExtensionProcessor)
}
@@ -178,6 +182,14 @@ class NewResolveOldInference(
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()
&& !towerCandidate.descriptor.extensionReceiverParameter!!.value.type.isDynamic()) {
candidateCall.addStatus(ResolutionStatus.RECEIVER_PRESENCE_ERROR)
return Candidate(ResolutionCandidateStatus(listOf(ExtensionWithStaticTypeWithDynamicReceiver)), candidateCall)
}
val callCandidateResolutionContext = CallCandidateResolutionContext.create(
candidateCall, basicCallContext, candidateTrace, tracing, basicCallContext.call,
ReceiverValue.NO_RECEIVER, CandidateResolveMode.FULLY // todo
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.types.KotlinType
@@ -33,6 +34,8 @@ interface ScopeTower {
val lexicalScope: LexicalScope
val dynamicScope: MemberScope
val location: LookupLocation
val dataFlowInfo: DataFlowDecorator
@@ -91,6 +94,8 @@ class UsedSmartCastForDispatchReceiver(val smartCastType: KotlinType): Resolutio
object ErrorDescriptorDiagnostic : ResolutionDiagnostic(ResolutionCandidateApplicability.INAPPLICABLE)
object SynthesizedDescriptorDiagnostic: ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED)
object DynamicDescriptorDiagnostic: ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED)
object UnstableSmartCastDiagnostic: ResolutionDiagnostic(ResolutionCandidateApplicability.MAY_THROW_RUNTIME_ERROR)
object ExtensionWithStaticTypeWithDynamicReceiver: ResolutionDiagnostic(ResolutionCandidateApplicability.INAPPLICABLE)
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.scopes.ImportingScope
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier
import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
@@ -43,6 +44,7 @@ internal class CandidateWithBoundDispatchReceiverImpl<D : CallableDescriptor>(
internal class ScopeTowerImpl(
resolutionContext: ResolutionContext<*>,
override val dynamicScope: MemberScope,
private val explicitReceiver: Receiver?,
override val location: LookupLocation
): ScopeTower {
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.isDynamic
import org.jetbrains.kotlin.utils.addIfNotNull
import java.util.*
@@ -147,6 +148,12 @@ internal class ReceiverScopeTowerLevel(
}
}
if (dispatchReceiver.type.isDynamic()) {
scopeTower.dynamicScope.members().mapTo(result) {
createCandidateDescriptor(it, dispatchReceiver, DynamicDescriptorDiagnostic)
}
}
return result
}