Lazy computation of smart cast types for receivers in call resolve

This commit is contained in:
Valentin Kipyatkov
2015-07-20 19:39:16 +03:00
parent 4ec26de2a8
commit fac55b60fa
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.psi.Call
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isOrOverridesSynthesized import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isOrOverridesSynthesized
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastUtils import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastUtils
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.BOTH_RECEIVERS import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.BOTH_RECEIVERS
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.DISPATCH_RECEIVER import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.DISPATCH_RECEIVER
@@ -113,41 +114,46 @@ public class TaskPrioritizer(private val storageManager: StorageManager) {
private fun <D : CallableDescriptor, F : D> doComputeTasks(receiver: ReceiverValue, c: TaskPrioritizerContext<D, F>) { private fun <D : CallableDescriptor, F : D> doComputeTasks(receiver: ReceiverValue, c: TaskPrioritizerContext<D, F>) {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
val receiverWithTypes = ReceiverWithTypes(receiver, c.context)
val resolveInvoke = c.context.call.getDispatchReceiver().exists() val resolveInvoke = c.context.call.getDispatchReceiver().exists()
if (resolveInvoke) { if (resolveInvoke) {
addCandidatesForInvoke(receiver, c) addCandidatesForInvoke(receiverWithTypes, c)
return return
} }
val implicitReceivers = Sets.newLinkedHashSet<ReceiverValue>(JetScopeUtils.getImplicitReceiversHierarchyValues(c.scope)) val implicitReceivers = Sets.newLinkedHashSet<ReceiverValue>(JetScopeUtils.getImplicitReceiversHierarchyValues(c.scope))
if (receiver.exists()) { if (receiver.exists()) {
val receiverTypes = SmartCastUtils.getSmartCastVariants(receiver, c.context) addCandidatesForExplicitReceiver(receiverWithTypes, implicitReceivers, c, isExplicit = true)
addCandidatesForExplicitReceiver(receiver, receiverTypes, implicitReceivers, c, isExplicit = true) addMembers(receiverWithTypes, c, staticMembers = true, isExplicit = true)
addMembers(receiver, receiverTypes, c, staticMembers = true, isExplicit = true)
return return
} }
addCandidatesForNoReceiver(implicitReceivers, c) addCandidatesForNoReceiver(implicitReceivers, c)
} }
private class ReceiverWithTypes(
val value: ReceiverValue,
private val context: ResolutionContext<*>) {
val types: Collection<JetType> by lazy { SmartCastUtils.getSmartCastVariants(value, context) }
}
private fun <D : CallableDescriptor, F : D> addCandidatesForExplicitReceiver( private fun <D : CallableDescriptor, F : D> addCandidatesForExplicitReceiver(
explicitReceiver: ReceiverValue, explicitReceiver: ReceiverWithTypes,
explicitReceiverTypes: Collection<JetType>,
implicitReceivers: Collection<ReceiverValue>, implicitReceivers: Collection<ReceiverValue>,
c: TaskPrioritizerContext<D, F>, c: TaskPrioritizerContext<D, F>,
isExplicit: Boolean isExplicit: Boolean
) { ) {
addMembers(explicitReceiver, explicitReceiverTypes, c, staticMembers = false, isExplicit = isExplicit) addMembers(explicitReceiver, c, staticMembers = false, isExplicit = isExplicit)
if (explicitReceiver.getType().isDynamic()) { if (explicitReceiver.value.type.isDynamic()) {
addCandidatesForDynamicReceiver(explicitReceiver, explicitReceiverTypes, implicitReceivers, c, isExplicit) addCandidatesForDynamicReceiver(explicitReceiver, implicitReceivers, c, isExplicit)
} }
else { else {
addExtensionCandidates(explicitReceiver, explicitReceiverTypes, implicitReceivers, c, isExplicit) addExtensionCandidates(explicitReceiver, implicitReceivers, c, isExplicit)
} }
} }
private fun <D : CallableDescriptor, F : D> addExtensionCandidates( private fun <D : CallableDescriptor, F : D> addExtensionCandidates(
explicitReceiver: ReceiverValue, explicitReceiver: ReceiverWithTypes,
explicitReceiverTypes: Collection<JetType>,
implicitReceivers: Collection<ReceiverValue>, implicitReceivers: Collection<ReceiverValue>,
c: TaskPrioritizerContext<D, F>, c: TaskPrioritizerContext<D, F>,
isExplicit: Boolean isExplicit: Boolean
@@ -158,7 +164,6 @@ public class TaskPrioritizer(private val storageManager: StorageManager) {
addMemberExtensionCandidates( addMemberExtensionCandidates(
implicitReceiver, implicitReceiver,
explicitReceiver, explicitReceiver,
explicitReceiverTypes,
callableDescriptorCollector, callableDescriptorCollector,
c, c,
createKind(EXTENSION_RECEIVER, isExplicit) createKind(EXTENSION_RECEIVER, isExplicit)
@@ -168,8 +173,8 @@ public class TaskPrioritizer(private val storageManager: StorageManager) {
c.result.addCandidates { c.result.addCandidates {
convertWithImpliedThis( convertWithImpliedThis(
c.scope, c.scope,
explicitReceiver, explicitReceiver.value,
callableDescriptorCollector.getExtensionsByName(c.scope, c.name, explicitReceiverTypes, c.context.trace), callableDescriptorCollector.getExtensionsByName(c.scope, c.name, explicitReceiver.types, c.context.trace),
createKind(EXTENSION_RECEIVER, isExplicit), createKind(EXTENSION_RECEIVER, isExplicit),
c.context.call c.context.call
) )
@@ -178,8 +183,7 @@ public class TaskPrioritizer(private val storageManager: StorageManager) {
} }
private fun <D : CallableDescriptor, F : D> addMembers( private fun <D : CallableDescriptor, F : D> addMembers(
explicitReceiver: ReceiverValue, explicitReceiver: ReceiverWithTypes,
explicitReceiverTypes: Collection<JetType>,
c: TaskPrioritizerContext<D, F>, c: TaskPrioritizerContext<D, F>,
staticMembers: Boolean, staticMembers: Boolean,
isExplicit: Boolean isExplicit: Boolean
@@ -187,7 +191,7 @@ public class TaskPrioritizer(private val storageManager: StorageManager) {
for (callableDescriptorCollector in c.callableDescriptorCollectors) { for (callableDescriptorCollector in c.callableDescriptorCollectors) {
c.result.addCandidates { c.result.addCandidates {
val members = Lists.newArrayList<ResolutionCandidate<D>>() val members = Lists.newArrayList<ResolutionCandidate<D>>()
for (type in explicitReceiverTypes) { for (type in explicitReceiver.types) {
val membersForThisVariant = if (staticMembers) { val membersForThisVariant = if (staticMembers) {
callableDescriptorCollector.getStaticMembersByName(type, c.name, c.context.trace) callableDescriptorCollector.getStaticMembersByName(type, c.name, c.context.trace)
} }
@@ -196,7 +200,7 @@ public class TaskPrioritizer(private val storageManager: StorageManager) {
} }
convertWithReceivers( convertWithReceivers(
membersForThisVariant, membersForThisVariant,
explicitReceiver, explicitReceiver.value,
NO_RECEIVER, NO_RECEIVER,
members, members,
createKind(DISPATCH_RECEIVER, isExplicit), createKind(DISPATCH_RECEIVER, isExplicit),
@@ -209,14 +213,13 @@ public class TaskPrioritizer(private val storageManager: StorageManager) {
} }
private fun <D : CallableDescriptor, F : D> addCandidatesForDynamicReceiver( private fun <D : CallableDescriptor, F : D> addCandidatesForDynamicReceiver(
explicitReceiver: ReceiverValue, explicitReceiver: ReceiverWithTypes,
explicitReceiverTypes: Collection<JetType>,
implicitReceivers: Collection<ReceiverValue>, implicitReceivers: Collection<ReceiverValue>,
c: TaskPrioritizerContext<D, F>, c: TaskPrioritizerContext<D, F>,
isExplicit: Boolean isExplicit: Boolean
) { ) {
val onlyDynamicReceivers = c.replaceCollectors(c.callableDescriptorCollectors.onlyDynamicReceivers<D>()) val onlyDynamicReceivers = c.replaceCollectors(c.callableDescriptorCollectors.onlyDynamicReceivers<D>())
addExtensionCandidates(explicitReceiver, explicitReceiverTypes, implicitReceivers, onlyDynamicReceivers, isExplicit) addExtensionCandidates(explicitReceiver, implicitReceivers, onlyDynamicReceivers, isExplicit)
c.result.addCandidates { c.result.addCandidates {
val dynamicScope = DynamicCallableDescriptors.createDynamicDescriptorScope(c.context.call, c.scope.getContainingDeclaration()) val dynamicScope = DynamicCallableDescriptors.createDynamicDescriptorScope(c.context.call, c.scope.getContainingDeclaration())
@@ -225,7 +228,7 @@ public class TaskPrioritizer(private val storageManager: StorageManager) {
it.getNonExtensionsByName(dynamicScope, c.name, c.context.trace) it.getNonExtensionsByName(dynamicScope, c.name, c.context.trace)
} }
convertWithReceivers(dynamicDescriptors, explicitReceiver, NO_RECEIVER, createKind(DISPATCH_RECEIVER, isExplicit), c.context.call) convertWithReceivers(dynamicDescriptors, explicitReceiver.value, NO_RECEIVER, createKind(DISPATCH_RECEIVER, isExplicit), c.context.call)
} }
} }
@@ -236,16 +239,15 @@ public class TaskPrioritizer(private val storageManager: StorageManager) {
private fun <D : CallableDescriptor, F : D> addMemberExtensionCandidates( private fun <D : CallableDescriptor, F : D> addMemberExtensionCandidates(
dispatchReceiver: ReceiverValue, dispatchReceiver: ReceiverValue,
receiverParameter: ReceiverValue, receiverParameter: ReceiverWithTypes,
receiverParameterTypes: Collection<JetType>,
callableDescriptorCollector: CallableDescriptorCollector<D>, callableDescriptorCollector: CallableDescriptorCollector<D>,
c: TaskPrioritizerContext<D, F>, c: TaskPrioritizerContext<D, F>,
receiverKind: ExplicitReceiverKind receiverKind: ExplicitReceiverKind
) { ) {
c.result.addCandidates { c.result.addCandidates {
val memberExtensions = val memberExtensions =
callableDescriptorCollector.getExtensionsByName(dispatchReceiver.getType().getMemberScope(), c.name, receiverParameterTypes, c.context.trace) callableDescriptorCollector.getExtensionsByName(dispatchReceiver.type.memberScope, c.name, receiverParameter.types, c.context.trace)
convertWithReceivers(memberExtensions, dispatchReceiver, receiverParameter, receiverKind, c.context.call) convertWithReceivers(memberExtensions, dispatchReceiver, receiverParameter.value, receiverKind, c.context.call)
} }
} }
@@ -276,23 +278,23 @@ public class TaskPrioritizer(private val storageManager: StorageManager) {
//locals //locals
c.result.addCandidates(localsList) c.result.addCandidates(localsList)
val implicitReceiversWithTypes = implicitReceivers.map { it to SmartCastUtils.getSmartCastVariants(it, c.context) } val implicitReceiversWithTypes = implicitReceivers.map { ReceiverWithTypes(it, c.context) }
//try all implicit receivers as explicit //try all implicit receivers as explicit
for ((implicitReceiver, implicitReceiverTypes) in implicitReceiversWithTypes) { for (implicitReceiver in implicitReceiversWithTypes) {
addCandidatesForExplicitReceiver(implicitReceiver, implicitReceiverTypes, implicitReceivers, c, isExplicit = false) addCandidatesForExplicitReceiver(implicitReceiver, implicitReceivers, c, isExplicit = false)
} }
//nonlocals //nonlocals
c.result.addCandidates(nonlocalsList) c.result.addCandidates(nonlocalsList)
//static (only for better error reporting) //static (only for better error reporting)
for ((implicitReceiver, implicitReceiverTypes) in implicitReceiversWithTypes) { for (implicitReceiver in implicitReceiversWithTypes) {
addMembers(implicitReceiver, implicitReceiverTypes, c, staticMembers = true, isExplicit = false) addMembers(implicitReceiver, c, staticMembers = true, isExplicit = false)
} }
} }
private fun <D : CallableDescriptor, F : D> addCandidatesForInvoke(explicitReceiver: ReceiverValue, c: TaskPrioritizerContext<D, F>) { private fun <D : CallableDescriptor, F : D> addCandidatesForInvoke(explicitReceiver: ReceiverWithTypes, c: TaskPrioritizerContext<D, F>) {
val implicitReceivers = JetScopeUtils.getImplicitReceiversHierarchyValues(c.scope) val implicitReceivers = JetScopeUtils.getImplicitReceiversHierarchyValues(c.scope)
// For 'a.foo()' where foo has function type, // For 'a.foo()' where foo has function type,
@@ -305,9 +307,8 @@ public class TaskPrioritizer(private val storageManager: StorageManager) {
// or for 'invoke' function. // or for 'invoke' function.
// (1) a.foo + foo.invoke() // (1) a.foo + foo.invoke()
if (!explicitReceiver.exists()) { if (!explicitReceiver.value.exists()) {
val variableReceiverTypes = SmartCastUtils.getSmartCastVariants(variableReceiver, c.context) addCandidatesForExplicitReceiver(ReceiverWithTypes(variableReceiver, c.context), implicitReceivers, c, isExplicit = true)
addCandidatesForExplicitReceiver(variableReceiver, variableReceiverTypes, implicitReceivers, c, isExplicit = true)
} }
// (2) foo + a.invoke() // (2) foo + a.invoke()
@@ -316,26 +317,25 @@ public class TaskPrioritizer(private val storageManager: StorageManager) {
//trait A //trait A
//trait Foo { fun A.invoke() } //trait Foo { fun A.invoke() }
if (explicitReceiver.exists()) { if (explicitReceiver.value.exists()) {
//a.foo() //a.foo()
addCandidatesWhenInvokeIsMemberAndExtensionToExplicitReceiver(variableReceiver, explicitReceiver, c, BOTH_RECEIVERS) addCandidatesWhenInvokeIsMemberAndExtensionToExplicitReceiver(variableReceiver, explicitReceiver, c, BOTH_RECEIVERS)
return return
} }
// with (a) { foo() } // with (a) { foo() }
for (implicitReceiver in implicitReceivers) { for (implicitReceiver in implicitReceivers) {
addCandidatesWhenInvokeIsMemberAndExtensionToExplicitReceiver(variableReceiver, implicitReceiver, c, DISPATCH_RECEIVER) addCandidatesWhenInvokeIsMemberAndExtensionToExplicitReceiver(variableReceiver, ReceiverWithTypes(implicitReceiver, c.context), c, DISPATCH_RECEIVER)
} }
} }
private fun <D : CallableDescriptor, F : D> addCandidatesWhenInvokeIsMemberAndExtensionToExplicitReceiver( private fun <D : CallableDescriptor, F : D> addCandidatesWhenInvokeIsMemberAndExtensionToExplicitReceiver(
dispatchReceiver: ReceiverValue, dispatchReceiver: ReceiverValue,
receiverParameter: ReceiverValue, receiverParameter: ReceiverWithTypes,
c: TaskPrioritizerContext<D, F>, c: TaskPrioritizerContext<D, F>,
receiverKind: ExplicitReceiverKind receiverKind: ExplicitReceiverKind
) { ) {
val receiverParameterTypes = SmartCastUtils.getSmartCastVariants(receiverParameter, c.context)
for (callableDescriptorCollector in c.callableDescriptorCollectors) { for (callableDescriptorCollector in c.callableDescriptorCollectors) {
addMemberExtensionCandidates(dispatchReceiver, receiverParameter, receiverParameterTypes, callableDescriptorCollector, c, receiverKind) addMemberExtensionCandidates(dispatchReceiver, receiverParameter, callableDescriptorCollector, c, receiverKind)
} }
} }