Fix "rewrite at slice LEXICAL_SCOPE" during callable reference resolution
Following the TODO in CallableReferencesResolutionUtils.kt, delete the suspicious scope and use the new resolution process with the qualifier which was obtained after the resolution of LHS. However, by default the tower resolution algorithm also considers each qualifier as a class value as well, which would be wrong here because resolution of LHS as a "value" happens earlier in DoubleColonExpressionResolver and with slightly different rules. To avoid that, do not mix in the "explicit receiver" scope tower processor when creating processors for callable reference resolution. Also delete unused functions and classes related to deleted scope, refactor Scopes.kt #KT-8596 Fixed
This commit is contained in:
+10
-42
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.CALLABLE_REFERENCE_LHS_NOT_A_CLASS
|
||||
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.CallResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
@@ -30,19 +31,14 @@ import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache
|
||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults
|
||||
import org.jetbrains.kotlin.resolve.calls.util.CallMaker
|
||||
import org.jetbrains.kotlin.resolve.scopes.BaseLexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.ScopeUtils
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.memberScopeAsImportingScope
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
|
||||
private fun <D : CallableDescriptor> ResolveArgumentsMode.acceptResolution(results: OverloadResolutionResults<D>, trace: TemporaryTraceAndCache) {
|
||||
when (this) {
|
||||
@@ -55,7 +51,7 @@ private fun <D : CallableDescriptor> ResolveArgumentsMode.acceptResolution(resul
|
||||
|
||||
private fun resolvePossiblyAmbiguousCallableReference(
|
||||
reference: KtSimpleNameExpression,
|
||||
receiver: ReceiverValue?,
|
||||
receiver: Receiver?,
|
||||
context: ResolutionContext<*>,
|
||||
resolutionMode: ResolveArgumentsMode,
|
||||
callResolver: CallResolver
|
||||
@@ -84,32 +80,7 @@ fun resolvePossiblyAmbiguousCallableReference(
|
||||
): OverloadResolutionResults<CallableDescriptor>? {
|
||||
val reference = callableReferenceExpression.callableReference
|
||||
|
||||
fun resolveInScope(traceTitle: String, classifier: ClassifierDescriptor, staticScope: MemberScope): OverloadResolutionResults<CallableDescriptor> {
|
||||
|
||||
// todo: drop this class when new resolve will be finished
|
||||
class StaticScopeAsLexicalScope(val staticScope: MemberScope) : BaseLexicalScope(staticScope.memberScopeAsImportingScope(), classifier) {
|
||||
override val kind: LexicalScopeKind
|
||||
get() = LexicalScopeKind.CALLABLE_REFERENCE
|
||||
|
||||
override fun printStructure(p: Printer) {
|
||||
p.println(toString())
|
||||
}
|
||||
|
||||
override fun toString(): String = "${javaClass.canonicalName} for $staticScope"
|
||||
|
||||
// this method is needed for correct rewrite LEXICAL_SCOPE in trace
|
||||
override fun equals(other: Any?) = other is StaticScopeAsLexicalScope && other.staticScope == staticScope
|
||||
override fun hashCode() = staticScope.hashCode()
|
||||
}
|
||||
|
||||
val temporaryTraceAndCache = TemporaryTraceAndCache.create(context, traceTitle, reference)
|
||||
val newContext = context.replaceTraceAndCache(temporaryTraceAndCache).replaceScope(StaticScopeAsLexicalScope(staticScope))
|
||||
val results = resolvePossiblyAmbiguousCallableReference(reference, null, newContext, resolutionMode, callResolver)
|
||||
resolutionMode.acceptResolution(results, temporaryTraceAndCache)
|
||||
return results
|
||||
}
|
||||
|
||||
fun resolveWithReceiver(traceTitle: String, receiver: ReceiverValue): OverloadResolutionResults<CallableDescriptor> {
|
||||
fun resolveWithReceiver(traceTitle: String, receiver: Receiver?): OverloadResolutionResults<CallableDescriptor> {
|
||||
val temporaryTraceAndCache = TemporaryTraceAndCache.create(context, traceTitle, reference)
|
||||
val newContext = context.replaceTraceAndCache(temporaryTraceAndCache)
|
||||
val results = resolvePossiblyAmbiguousCallableReference(reference, receiver, newContext, resolutionMode, callResolver)
|
||||
@@ -127,14 +98,11 @@ fun resolvePossiblyAmbiguousCallableReference(
|
||||
return null
|
||||
}
|
||||
|
||||
val possibleStatic = resolveInScope("resolve unbound callable reference in static scope", classifier, classifier.staticScope)
|
||||
if (possibleStatic.isSomething()) return possibleStatic
|
||||
|
||||
val possibleNested = resolveInScope(
|
||||
"resolve unbound callable reference in static nested classes scope", classifier,
|
||||
ScopeUtils.getStaticNestedClassesScope(classifier)
|
||||
)
|
||||
if (possibleNested.isSomething()) return possibleNested
|
||||
val qualifier = context.trace.get(BindingContext.QUALIFIER, callableReferenceExpression.receiverExpression!!)
|
||||
if (qualifier is ClassQualifier) {
|
||||
val possibleStatic = resolveWithReceiver("resolve unbound callable reference in static scope", qualifier)
|
||||
if (possibleStatic.isSomething()) return possibleStatic
|
||||
}
|
||||
|
||||
val possibleWithReceiver = resolveWithReceiver("resolve unbound callable reference with receiver", TransientReceiver(lhsType))
|
||||
if (possibleWithReceiver.isSomething()) return possibleWithReceiver
|
||||
|
||||
+2
-2
@@ -95,8 +95,8 @@ class NewResolutionOldInference(
|
||||
val simpleContextF = outer.SimpleContext<FunctionDescriptor>(scopeTower, name, context, tracing)
|
||||
val simpleContextV = outer.SimpleContext<VariableDescriptor>(scopeTower, name, context, tracing)
|
||||
return CompositeScopeTowerProcessor(
|
||||
createFunctionProcessor(simpleContextF, explicitReceiver),
|
||||
createVariableProcessor(simpleContextV, explicitReceiver)
|
||||
createFunctionProcessor(simpleContextF, explicitReceiver, classValueReceiver = false),
|
||||
createVariableProcessor(simpleContextV, explicitReceiver, classValueReceiver = false)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user