[FE] Change resolution scheme

This commit is contained in:
Anastasiya Shadrina
2021-06-17 01:10:54 +07:00
committed by TeamCityServer
parent 1f6746dc74
commit 37495bcba0
39 changed files with 455 additions and 113 deletions
@@ -16,12 +16,9 @@ import org.jetbrains.kotlin.resolve.calls.components.CheckReceivers.checkReceive
import org.jetbrains.kotlin.resolve.calls.components.TypeArgumentsToParametersMapper.TypeArgumentsMapping.NoExplicitArguments
import org.jetbrains.kotlin.resolve.calls.components.candidate.CallableReferenceResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.components.candidate.ResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation
import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible
import org.jetbrains.kotlin.resolve.calls.inference.*
import org.jetbrains.kotlin.resolve.calls.inference.components.*
import org.jetbrains.kotlin.resolve.calls.inference.model.*
import org.jetbrains.kotlin.resolve.calls.inference.substitute
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.smartcasts.getReceiverValueWithSmartCast
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.*
@@ -807,30 +804,60 @@ internal object ErrorDescriptorResolutionPart : ResolutionPart() {
}
internal object CheckContextReceiversResolutionPart : ResolutionPart() {
private fun ResolutionCandidate.checkReceiver(
implicitReceivers: Collection<ReceiverValueWithSmartCastInfo>,
private data class ApplicableArgumentWithConstraint(
val argument: SimpleKotlinCallArgument,
val argumentType: UnwrappedType,
val expectedType: UnwrappedType,
val position: ConstraintPosition
)
private fun ResolutionCandidate.findContextReceiver(
implicitReceiversGroups: List<List<ReceiverValueWithSmartCastInfo>>,
candidateContextReceiverParameter: ReceiverParameterDescriptor
): SimpleKotlinCallArgument? {
val csBuilder = getSystem().getBuilder()
for (implicitReceiver in implicitReceivers) {
val argument = ReceiverExpressionKotlinCallArgument(implicitReceiver)
fun ReceiverValueWithSmartCastInfo.createArgumentIfCompatible(): ApplicableArgumentWithConstraint? {
val csBuilder = getSystem().getBuilder()
val argument = ReceiverExpressionKotlinCallArgument(this)
val expectedTypeUnprepared = argument.getExpectedType(candidateContextReceiverParameter, callComponents.languageVersionSettings)
val expectedType = prepareExpectedType(expectedTypeUnprepared)
val argumentType = captureFromTypeParameterUpperBoundIfNeeded(argument.receiver.stableType, expectedType)
val position = ReceiverConstraintPositionImpl(argument)
if (csBuilder.addSubtypeConstraintIfCompatible(argumentType, expectedType, position)) return argument
return if (csBuilder.isSubtypeConstraintCompatible(argumentType, expectedType, position))
ApplicableArgumentWithConstraint(argument, argumentType, expectedType, position)
else null
}
for (implicitReceiverGroup in implicitReceiversGroups) {
val applicableArguments = implicitReceiverGroup.mapNotNull { it.createArgumentIfCompatible() }.toList()
if (applicableArguments.size == 1) {
val (argument, argumentType, expectedType, position) = applicableArguments.single()
csBuilder.addSubtypeConstraint(argumentType, expectedType, position)
return argument
}
if (applicableArguments.size > 1) {
diagnosticsFromResolutionParts.add(MultipleArgumentsApplicableForContextReceiver(candidateContextReceiverParameter))
return null
}
}
diagnosticsFromResolutionParts.add(NoContextReceiver(candidateContextReceiverParameter))
return null
}
override fun ResolutionCandidate.process(workIndex: Int) {
val implicitReceivers = scopeTower.lexicalScope.parentsWithSelf
.flatMap { if (it is LexicalScope) scopeTower.getImplicitReceivers(it) else emptyList() }.toList()
val parentLexicalScopes = scopeTower.lexicalScope.parentsWithSelf.filterIsInstance<LexicalScope>()
val implicitReceiversGroups = mutableListOf<List<ReceiverValueWithSmartCastInfo>>()
for (scope in parentLexicalScopes) {
scopeTower.getImplicitReceiver(scope)?.let { implicitReceiversGroups.add(listOf(it)) }
val contextReceiversGroup = scopeTower.getContextReceivers(scope)
if (contextReceiversGroup.isNotEmpty()) {
implicitReceiversGroups.add(contextReceiversGroup)
}
}
val contextReceiversArguments = mutableListOf<SimpleKotlinCallArgument>()
for (candidateContextReceiverParameter in candidateDescriptor.contextReceiverParameters) {
contextReceiversArguments.add(findContextReceiver(implicitReceivers, candidateContextReceiverParameter) ?: return)
contextReceiversArguments.add(findContextReceiver(implicitReceiversGroups, candidateContextReceiverParameter) ?: return)
}
resolvedCall.contextReceiversArguments = contextReceiversArguments
}
@@ -279,6 +279,12 @@ class NoContextReceiver(val receiverDescriptor: ReceiverParameterDescriptor) : K
}
}
class MultipleArgumentsApplicableForContextReceiver(val receiverDescriptor: ReceiverParameterDescriptor) : KotlinCallDiagnostic(INAPPLICABLE) {
override fun report(reporter: DiagnosticReporter) {
reporter.onCall(this)
}
}
class KotlinConstraintSystemDiagnostic(
val error: ConstraintSystemError
) : KotlinCallDiagnostic(error.applicability) {
@@ -37,7 +37,9 @@ import org.jetbrains.kotlin.types.TypeApproximator
interface ImplicitScopeTower {
val lexicalScope: LexicalScope
fun getImplicitReceivers(scope: LexicalScope): List<ReceiverValueWithSmartCastInfo>
fun getImplicitReceiver(scope: LexicalScope): ReceiverValueWithSmartCastInfo?
fun getContextReceivers(scope: LexicalScope): List<ReceiverValueWithSmartCastInfo>
fun getNameForGivenImportAlias(name: Name): Name?
@@ -201,6 +201,80 @@ internal class MemberScopeTowerLevel(
}
}
internal class ContextReceiversGroupScopeTowerLevel(
scopeTower: ImplicitScopeTower,
val contextReceiversGroup: List<ReceiverValueWithSmartCastInfo>
) : AbstractScopeTowerLevel(scopeTower) {
private val syntheticScopes = scopeTower.syntheticScopes
private fun collectMembers(
getMembers: ResolutionScope.(KotlinType?) -> Collection<CallableDescriptor>
): Collection<CandidateWithBoundDispatchReceiver> {
val result = ArrayList<CandidateWithBoundDispatchReceiver>(0)
for (contextReceiver in contextReceiversGroup) {
val receiverValue = contextReceiver.receiverValue
if (receiverValue.type is AbstractStubType && receiverValue.type.memberScope is ErrorUtils.ErrorScope) {
return arrayListOf()
}
receiverValue.type.memberScope.getMembers(receiverValue.type).mapTo(result) {
createCandidateDescriptor(it, contextReceiver)
}
if (receiverValue.type.isDynamic()) {
scopeTower.dynamicScope.getMembers(null).mapTo(result) {
createCandidateDescriptor(it, contextReceiver, DynamicDescriptorDiagnostic)
}
}
}
return result
}
override fun getVariables(
name: Name,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<CandidateWithBoundDispatchReceiver> {
return contextReceiversGroup.map { contextReceiver ->
collectMembers { getContributedVariablesAndIntercept(name, location, contextReceiver, extensionReceiver, scopeTower) }
}.flatten()
}
override fun getObjects(
name: Name,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<CandidateWithBoundDispatchReceiver> {
return emptyList()
}
override fun getFunctions(
name: Name,
extensionReceiver: ReceiverValueWithSmartCastInfo?
): Collection<CandidateWithBoundDispatchReceiver> {
val collectMembers = { contextReceiver: ReceiverValueWithSmartCastInfo ->
collectMembers {
getContributedFunctionsAndIntercept(
name,
location,
contextReceiver,
extensionReceiver,
scopeTower
) + it.getInnerConstructors(
name,
location
) + syntheticScopes.collectSyntheticMemberFunctions(listOfNotNull(it), name, location)
}
}
return contextReceiversGroup.map(collectMembers).flatten()
}
override fun recordLookup(name: Name) {
for (type in contextReceiversGroup.map { it.allOriginalTypes }.flatten()) {
type.memberScope.recordLookup(name, location)
}
}
}
internal class QualifierScopeTowerLevel(scopeTower: ImplicitScopeTower, val qualifier: QualifierReceiver) :
AbstractScopeTowerLevel(scopeTower) {
override fun getVariables(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) = qualifier.staticScope
@@ -100,6 +100,12 @@ class TowerResolver {
name: Name
): Collection<C> = Task(this, processor, resultCollector, useOrder, name).run()
sealed interface ScopeResolutionStep {
data class LexicalScopesResolution(val resolveExtensionsForImplicitReceiver: Boolean) : ScopeResolutionStep
object ContextReceiversGroupsResolution : ScopeResolutionStep
object ImportingScopesResolution : ScopeResolutionStep
}
private inner class Task<out C : Candidate>(
private val implicitScopeTower: ImplicitScopeTower,
private val processor: ScopeTowerProcessor<C>,
@@ -135,27 +141,40 @@ class TowerResolver {
}
}
lexicalScope.parentsWithSelf.forEach { scope ->
if (scope is LexicalScope) {
if (!scope.kind.withLocalDescriptors) {
addLevel(
ScopeBasedTowerLevel(this@createNonLocalLevels, scope),
scope.mayFitForName(name)
)
}
getImplicitReceivers(scope).forEach {
addLevel(
MemberScopeTowerLevel(this@createNonLocalLevels, it),
it.mayFitForName(name)
)
}
} else {
val parentScopes = lexicalScope.parentsWithSelf
val lexicalScopes = parentScopes.filterIsInstance<LexicalScope>()
lexicalScopes.forEach { scope ->
if (!scope.kind.withLocalDescriptors) {
addLevel(
ImportingScopeBasedTowerLevel(this@createNonLocalLevels, scope as ImportingScope),
ScopeBasedTowerLevel(this@createNonLocalLevels, scope),
scope.mayFitForName(name)
)
}
getImplicitReceiver(scope)?.let {
addLevel(
MemberScopeTowerLevel(this@createNonLocalLevels, it),
it.mayFitForName(name)
)
}
}
lexicalScopes.forEach { scope ->
val contextReceiversGroup = getContextReceivers(scope)
if (contextReceiversGroup.isNotEmpty()) {
addLevel(
ContextReceiversGroupScopeTowerLevel(this@createNonLocalLevels, contextReceiversGroup),
contextReceiversGroup.any { it.mayFitForName(name) }
)
}
}
val importingScopes = parentScopes - lexicalScopes
importingScopes.forEach { scope ->
addLevel(
ImportingScopeBasedTowerLevel(this@createNonLocalLevels, scope as ImportingScope),
scope.mayFitForName(name)
)
}
return mainResult
@@ -189,31 +208,57 @@ class TowerResolver {
TowerData.TowerLevel(localLevel).process()?.let { return it }
}
fun processScope(scope: HierarchicalScope, resolveExtensionsForImplicitReceiver: Boolean): Collection<C>? {
if (scope is LexicalScope) {
// statics
if (!scope.kind.withLocalDescriptors) {
TowerData.TowerLevel(ScopeBasedTowerLevel(implicitScopeTower, scope))
fun processScope(scope: HierarchicalScope, scopeResolutionStep: ScopeResolutionStep): Collection<C>? {
when (scopeResolutionStep) {
is ScopeResolutionStep.LexicalScopesResolution -> if (scope is LexicalScope) {
if (!scope.kind.withLocalDescriptors) {
TowerData.TowerLevel(ScopeBasedTowerLevel(implicitScopeTower, scope))
.process(scope.mayFitForName(name))?.let { return it }
}
implicitScopeTower.getImplicitReceiver(scope)?.let { rv ->
processImplicitReceiver(rv, scopeResolutionStep.resolveExtensionsForImplicitReceiver)?.let { return it }
}
}
is ScopeResolutionStep.ContextReceiversGroupsResolution -> if (scope is LexicalScope) {
val contextReceiversGroup = implicitScopeTower.getContextReceivers(scope)
if (contextReceiversGroup.isNotEmpty()) {
TowerData.TowerLevel(ContextReceiversGroupScopeTowerLevel(implicitScopeTower, contextReceiversGroup))
.process()?.let { return it }
}
}
is ScopeResolutionStep.ImportingScopesResolution -> if (scope is ImportingScope) {
TowerData.TowerLevel(ImportingScopeBasedTowerLevel(implicitScopeTower, scope))
.process(scope.mayFitForName(name))?.let { return it }
}
implicitScopeTower.getImplicitReceivers(scope).forEach { rv ->
processImplicitReceiver(rv, resolveExtensionsForImplicitReceiver)?.let { return it }
}
} else {
TowerData.TowerLevel(ImportingScopeBasedTowerLevel(implicitScopeTower, scope as ImportingScope))
.process(scope.mayFitForName(name))?.let { return it }
}
return null
}
if (implicitScopeTower.implicitsResolutionFilter === ImplicitsExtensionsResolutionFilter.Default) {
for (scope in implicitScopeTower.lexicalScope.parentsWithSelf) {
processScope(scope, true)?.let { return it }
}
val scopes = implicitScopeTower.lexicalScope.parentsWithSelf
scopes.forEach { scope -> processScope(scope, ScopeResolutionStep.LexicalScopesResolution(true))?.let { return it } }
scopes.forEach { scope -> processScope(scope, ScopeResolutionStep.ContextReceiversGroupsResolution)?.let { return it } }
scopes.forEach { scope -> processScope(scope, ScopeResolutionStep.ImportingScopesResolution)?.let { return it } }
} else {
for (scopeInfo in implicitScopeTower.allScopesWithImplicitsResolutionInfo()) {
processScope(scopeInfo.scope, scopeInfo.resolveExtensionsForImplicitReceiver)?.let { return it }
val scopeInfos = implicitScopeTower.allScopesWithImplicitsResolutionInfo()
scopeInfos.forEach { scopeInfo ->
processScope(
scopeInfo.scope,
ScopeResolutionStep.LexicalScopesResolution(scopeInfo.resolveExtensionsForImplicitReceiver)
)?.let { return it }
}
scopeInfos.forEach { scopeInfo ->
processScope(
scopeInfo.scope,
ScopeResolutionStep.ContextReceiversGroupsResolution
)?.let { return it }
}
scopeInfos.forEach { scopeInfo ->
processScope(
scopeInfo.scope,
ScopeResolutionStep.ImportingScopesResolution
)?.let { return it }
}
}
@@ -32,7 +32,8 @@ class LexicalChainedScope private constructor(
parent: LexicalScope,
override val ownerDescriptor: DeclarationDescriptor,
override val isOwnerDescriptorAccessibleByLabel: Boolean,
override val implicitReceivers: List<ReceiverParameterDescriptor>,
override val implicitReceiver: ReceiverParameterDescriptor?,
override val contextReceiversGroup: List<ReceiverParameterDescriptor>,
override val kind: LexicalScopeKind,
// NB. Here can be very special subtypes of MemberScope (e.g., DeprecatedMemberScope).
// Please, do not leak them outside of LexicalChainedScope, because other parts of compiler are not ready to work with them
@@ -80,7 +81,9 @@ class LexicalChainedScope private constructor(
"; for descriptor: ",
ownerDescriptor.name,
" with implicitReceiver: ",
if (implicitReceivers.isEmpty()) "NONE" else implicitReceivers.joinToString { it.value.toString() },
implicitReceiver?.value ?: "NONE",
" with contextReceiversGroup: ",
if (contextReceiversGroup.isEmpty()) "NONE" else contextReceiversGroup.joinToString { it.value.toString() },
" {"
)
p.pushIndent()
@@ -111,13 +114,14 @@ class LexicalChainedScope private constructor(
parent: LexicalScope,
ownerDescriptor: DeclarationDescriptor,
isOwnerDescriptorAccessibleByLabel: Boolean,
implicitReceivers: List<ReceiverParameterDescriptor>,
implicitReceiver: ReceiverParameterDescriptor?,
contextReceiversGroup: List<ReceiverParameterDescriptor>,
kind: LexicalScopeKind,
vararg memberScopes: MemberScope?,
isStaticScope: Boolean = false
): LexicalScope =
LexicalChainedScope(
parent, ownerDescriptor, isOwnerDescriptorAccessibleByLabel, implicitReceivers, kind,
parent, ownerDescriptor, isOwnerDescriptorAccessibleByLabel, implicitReceiver, contextReceiversGroup, kind,
listOfNonEmptyScopes(*memberScopes).toTypedArray(),
isStaticScope
)
@@ -23,7 +23,8 @@ class LexicalScopeImpl @JvmOverloads constructor(
parent: HierarchicalScope,
override val ownerDescriptor: DeclarationDescriptor,
override val isOwnerDescriptorAccessibleByLabel: Boolean,
override val implicitReceivers: List<ReceiverParameterDescriptor>,
override val implicitReceiver: ReceiverParameterDescriptor?,
override val contextReceiversGroup: List<ReceiverParameterDescriptor>,
override val kind: LexicalScopeKind,
redeclarationChecker: LocalRedeclarationChecker = LocalRedeclarationChecker.DO_NOTHING,
initialize: LexicalScopeImpl.InitializeHandler.() -> Unit = {}
@@ -43,7 +44,9 @@ class LexicalScopeImpl @JvmOverloads constructor(
"; for descriptor: ",
ownerDescriptor.name,
" with implicitReceiver: ",
if (implicitReceivers.isEmpty()) "NONE" else implicitReceivers.joinToString { it.value.toString() },
implicitReceiver?.value ?: "NONE",
" with contextReceiversGroup: ",
if (contextReceiversGroup.isEmpty()) "NONE" else contextReceiversGroup.joinToString { it.value.toString() },
" {"
)
p.pushIndent()
@@ -30,7 +30,9 @@ class LexicalWritableScope(
override val kind: LexicalScopeKind
) : LexicalScopeStorage(parent, redeclarationChecker) {
override val implicitReceivers: List<ReceiverParameterDescriptor>
override val implicitReceiver: ReceiverParameterDescriptor?
get() = null
override val contextReceiversGroup: List<ReceiverParameterDescriptor>
get() = emptyList()
private var canWrite: Boolean = true
@@ -111,7 +113,9 @@ class LexicalWritableScope(
"; for descriptor: ",
ownerDescriptor.name,
" with implicitReceivers: ",
if (implicitReceivers.isEmpty()) "NONE" else implicitReceivers.joinToString { it.value.toString() },
implicitReceiver?.value ?: "NONE",
" with contextReceiversGroup: ",
if (contextReceiversGroup.isEmpty()) "NONE" else contextReceiversGroup.joinToString { it.value.toString() },
" {"
)
p.pushIndent()
@@ -36,7 +36,8 @@ public final class ScopeUtils {
@NotNull LexicalScope parent,
@NotNull PropertyDescriptor propertyDescriptor
) {
return new LexicalScopeImpl(parent, propertyDescriptor, false, Collections.emptyList(), LexicalScopeKind.PROPERTY_HEADER,
return new LexicalScopeImpl(parent, propertyDescriptor, false, null, Collections.emptyList(),
LexicalScopeKind.PROPERTY_HEADER,
// redeclaration on type parameters should be reported early, see: DescriptorResolver.resolvePropertyDescriptor()
LocalRedeclarationChecker.DO_NOTHING.INSTANCE,
handler -> {
@@ -52,7 +53,8 @@ public final class ScopeUtils {
@NotNull LexicalScope propertyHeader,
@NotNull PropertyDescriptor propertyDescriptor
) {
return new LexicalScopeImpl(propertyHeader, propertyDescriptor, false, Collections.emptyList(), LexicalScopeKind.PROPERTY_INITIALIZER_OR_DELEGATE);
return new LexicalScopeImpl(propertyHeader, propertyDescriptor, false, null, Collections.emptyList(),
LexicalScopeKind.PROPERTY_INITIALIZER_OR_DELEGATE);
}
@NotNull
@@ -60,14 +62,9 @@ public final class ScopeUtils {
@NotNull LexicalScope parent,
@NotNull VariableDescriptorWithAccessors variableDescriptor
) {
List<ReceiverParameterDescriptor> implicitReceivers = new ArrayList<>();
ReceiverParameterDescriptor extensionReceiverParameter = variableDescriptor.getExtensionReceiverParameter();
if (extensionReceiverParameter != null) {
implicitReceivers.add(extensionReceiverParameter);
}
// todo: very strange scope!
return new LexicalScopeImpl(parent, variableDescriptor, true, implicitReceivers,
LexicalScopeKind.PROPERTY_DELEGATE_METHOD
return new LexicalScopeImpl(parent, variableDescriptor, true, variableDescriptor.getExtensionReceiverParameter(),
/* TODO: Context receivers? */ Collections.emptyList(), LexicalScopeKind.PROPERTY_DELEGATE_METHOD
);
}
@@ -36,7 +36,8 @@ interface LexicalScope : HierarchicalScope {
val ownerDescriptor: DeclarationDescriptor
val isOwnerDescriptorAccessibleByLabel: Boolean
val implicitReceivers: List<ReceiverParameterDescriptor>
val implicitReceiver: ReceiverParameterDescriptor?
val contextReceiversGroup: List<ReceiverParameterDescriptor>
val kind: LexicalScopeKind
@@ -50,7 +51,9 @@ interface LexicalScope : HierarchicalScope {
override val isOwnerDescriptorAccessibleByLabel: Boolean
get() = false
override val implicitReceivers: List<ReceiverParameterDescriptor>
override val implicitReceiver: ReceiverParameterDescriptor?
get() = null
override val contextReceiversGroup: List<ReceiverParameterDescriptor>
get() = emptyList()
override val kind: LexicalScopeKind
@@ -36,7 +36,7 @@ val HierarchicalScope.parents: Sequence<HierarchicalScope>
* Adds receivers to the list in order of locality, so that the closest (the most local) receiver goes first
*/
fun LexicalScope.getImplicitReceiversHierarchy(): List<ReceiverParameterDescriptor> = collectFromMeAndParent {
(it as? LexicalScope)?.implicitReceivers
if (it is LexicalScope) listOfNotNull(it.implicitReceiver) + it.contextReceiversGroup else null
}.flatten()
fun LexicalScope.getDeclarationsByLabel(labelName: Name): Collection<DeclarationDescriptor> = collectAllFromMeAndParent {
@@ -261,7 +261,7 @@ fun LexicalScope.replaceImportingScopes(importingScopeChain: ImportingScope?): L
fun LexicalScope.createScopeForDestructuring(newReceiver: ReceiverParameterDescriptor?): LexicalScope {
return LexicalScopeImpl(
parent, ownerDescriptor, isOwnerDescriptorAccessibleByLabel,
listOfNotNull(newReceiver),
newReceiver, listOf(),
LexicalScopeKind.FUNCTION_HEADER_FOR_DESTRUCTURING
)
}
@@ -324,7 +324,8 @@ class ErrorLexicalScope : LexicalScope {
override val ownerDescriptor: DeclarationDescriptor = ErrorUtils.createErrorClass("<ERROR CLASS FOR ERROR SCOPE>")
override val isOwnerDescriptorAccessibleByLabel: Boolean = false
override val implicitReceivers: List<ReceiverParameterDescriptor> = emptyList()
override val implicitReceiver: ReceiverParameterDescriptor? = null
override val contextReceiversGroup: List<ReceiverParameterDescriptor> = emptyList()
override val kind: LexicalScopeKind = LexicalScopeKind.THROWING
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? = null