Do not enter in recursion for implicit invoke on variable with un inferred type

This commit is contained in:
Stanislav Erokhin
2015-12-08 15:11:50 +03:00
parent 1dca49cecc
commit 66a031f7a0
6 changed files with 63 additions and 3 deletions
@@ -96,6 +96,7 @@ internal class InvokeTowerProcessor<C>(
// todo filter by operator
override fun createInvokeProcessor(variableCandidate: C): ScopeTowerProcessor<C> {
val (variableReceiver, invokeContext) = functionContext.contextForInvoke(variableCandidate, useExplicitReceiver = false)
?: return KnownResultProcessor(emptyList())
return ExplicitReceiverScopeTowerProcessor(invokeContext, variableReceiver, ScopeTowerLevel::getFunctions)
}
}
@@ -110,6 +111,7 @@ internal class InvokeExtensionTowerProcessor<C>(
override fun createInvokeProcessor(variableCandidate: C): ScopeTowerProcessor<C> {
val (variableReceiver, invokeContext) = functionContext.contextForInvoke(variableCandidate, useExplicitReceiver = true)
?: return KnownResultProcessor(emptyList())
val invokeDescriptor = functionContext.scopeTower.getExtensionInvokeCandidateDescriptor(variableReceiver)
?: return KnownResultProcessor(emptyList())
return InvokeExtensionScopeTowerProcessor(invokeContext, invokeDescriptor, explicitReceiver)
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategyForInvoke
import org.jetbrains.kotlin.resolve.isAnnotatedAsHidden
import org.jetbrains.kotlin.resolve.scopes.receivers.*
import org.jetbrains.kotlin.types.DeferredType
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.isDynamic
import org.jetbrains.kotlin.util.OperatorNameConventions
@@ -243,7 +244,7 @@ class NewResolveOldInference(
return Context(scopeTower, name, basicCallResolutionContext, tracing)
}
override fun contextForInvoke(variable: Candidate, useExplicitReceiver: Boolean): Pair<ReceiverValue, TowerContext<Candidate>> {
override fun contextForInvoke(variable: Candidate, useExplicitReceiver: Boolean): Pair<ReceiverValue, TowerContext<Candidate>>? {
assert(variable.resolvedCall.status.possibleTransformToSuccess()) {
"Incorrect status: ${variable.resolvedCall.status} for variable call: ${variable.resolvedCall} " +
"and descriptor: ${variable.resolvedCall.candidateDescriptor}"
@@ -253,8 +254,13 @@ class NewResolveOldInference(
assert(variable.resolvedCall.status.possibleTransformToSuccess() && calleeExpression != null && variableDescriptor is VariableDescriptor) {
"Unexpected varialbe candidate: $variable"
}
val variableType = (variableDescriptor as VariableDescriptor).type
if (variableType is DeferredType && variableType.isComputing) {
return null // todo: create special check that there is no invoke on variable
}
val variableReceiver = ExpressionReceiver.create(calleeExpression!!,
(variableDescriptor as VariableDescriptor).type,
variableType,
basicCallContext.trace.bindingContext)
// used for smartCasts, see: DataFlowValueFactory.getIdForSimpleNameExpression
tracing.bindReference(variable.resolvedCall.trace, variable.resolvedCall)
@@ -39,7 +39,8 @@ interface TowerContext<C> {
fun contextForVariable(stripExplicitReceiver: Boolean): TowerContext<C>
// foo() -> ReceiverValue(foo), context for invoke
fun contextForInvoke(variable: C, useExplicitReceiver: Boolean): Pair<ReceiverValue, TowerContext<C>>
// null means that there is no invoke on variable
fun contextForInvoke(variable: C, useExplicitReceiver: Boolean): Pair<ReceiverValue, TowerContext<C>>?
}
internal sealed class TowerData {