Lazy computation of smart cast types for receivers in call resolve
This commit is contained in:
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user