[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
@@ -10579,6 +10579,16 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/extensions/contextReceivers"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@TestMetadata("ambiguityInGroupSimple.kt")
public void testAmbiguityInGroupSimple() throws Exception {
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/ambiguityInGroupSimple.kt");
}
@TestMetadata("ambiguityInGroupWithInheritance.kt")
public void testAmbiguityInGroupWithInheritance() throws Exception {
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/ambiguityInGroupWithInheritance.kt");
}
@TestMetadata("dp.kt")
public void testDp() throws Exception {
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/dp.kt");
@@ -10576,6 +10576,18 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/extensions/contextReceivers"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("ambiguityInGroupSimple.kt")
public void testAmbiguityInGroupSimple() throws Exception {
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/ambiguityInGroupSimple.kt");
}
@Test
@TestMetadata("ambiguityInGroupWithInheritance.kt")
public void testAmbiguityInGroupWithInheritance() throws Exception {
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/ambiguityInGroupWithInheritance.kt");
}
@Test
@TestMetadata("dp.kt")
public void testDp() throws Exception {
@@ -10576,6 +10576,18 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/extensions/contextReceivers"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("ambiguityInGroupSimple.kt")
public void testAmbiguityInGroupSimple() throws Exception {
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/ambiguityInGroupSimple.kt");
}
@Test
@TestMetadata("ambiguityInGroupWithInheritance.kt")
public void testAmbiguityInGroupWithInheritance() throws Exception {
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/ambiguityInGroupWithInheritance.kt");
}
@Test
@TestMetadata("dp.kt")
public void testDp() throws Exception {
@@ -1198,6 +1198,7 @@ public interface Errors {
// Context receivers
DiagnosticFactory1<KtElement, String> NO_CONTEXT_RECEIVER = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<KtElement, String> MULTIPLE_ARGUMENTS_APPLICABLE_FOR_CONTEXT_RECEIVER = DiagnosticFactory1.create(ERROR);
// Error sets
ImmutableSet<? extends DiagnosticFactory<?>> UNRESOLVED_REFERENCE_DIAGNOSTICS = ImmutableSet.of(
@@ -1089,6 +1089,7 @@ public class DefaultErrorMessages {
MAP.put(CONTRACT_NOT_ALLOWED, "{0}", TO_STRING);
MAP.put(NO_CONTEXT_RECEIVER, "No required context receiver found: {0}", TO_STRING);
MAP.put(MULTIPLE_ARGUMENTS_APPLICABLE_FOR_CONTEXT_RECEIVER, "Multiple arguments applicable for context receiver: {0}", TO_STRING);
MAP.setImmutable();
@@ -162,7 +162,7 @@ public class BodyResolver {
descriptor, localContext != null ? localContext.inferenceSession : null
),
scope -> new LexicalScopeImpl(
scope, descriptor, scope.isOwnerDescriptorAccessibleByLabel(), scope.getImplicitReceivers(),
scope, descriptor, scope.isOwnerDescriptorAccessibleByLabel(), scope.getImplicitReceiver(), scope.getContextReceiversGroup(),
LexicalScopeKind.CONSTRUCTOR_HEADER
),
localContext
@@ -439,7 +439,7 @@ public class BodyResolver {
) {
// Initializing a scope will report errors if any.
new LexicalScopeImpl(
scopeForConstructorResolution, descriptor, true, Collections.emptyList(), LexicalScopeKind.CLASS_HEADER,
scopeForConstructorResolution, descriptor, true, null, Collections.emptyList(), LexicalScopeKind.CLASS_HEADER,
new TraceBasedLocalRedeclarationChecker(trace, overloadChecker),
new Function1<LexicalScopeImpl.InitializeHandler, Unit>() {
@Override
@@ -780,8 +780,8 @@ public class BodyResolver {
LexicalScope originalScope,
ConstructorDescriptor unsubstitutedPrimaryConstructor
) {
return new LexicalScopeImpl(originalScope, unsubstitutedPrimaryConstructor, false, Collections.emptyList(),
LexicalScopeKind.DEFAULT_VALUE, LocalRedeclarationChecker.DO_NOTHING.INSTANCE,
return new LexicalScopeImpl(originalScope, unsubstitutedPrimaryConstructor, false, null,
Collections.emptyList(), LexicalScopeKind.DEFAULT_VALUE, LocalRedeclarationChecker.DO_NOTHING.INSTANCE,
handler -> {
for (ValueParameterDescriptor valueParameter : unsubstitutedPrimaryConstructor.getValueParameters()) {
handler.addVariableDescriptor(valueParameter);
@@ -863,12 +863,7 @@ public class BodyResolver {
LexicalScope accessorDeclaringScope = c.getDeclaringScope(accessor);
assert accessorDeclaringScope != null : "Scope for accessor " + accessor.getText() + " should exists";
LexicalScope headerScope = ScopeUtils.makeScopeForPropertyHeader(accessorDeclaringScope, descriptor);
List<ReceiverParameterDescriptor> implicitReceivers = new ArrayList<>();
ReceiverParameterDescriptor extensionReceiverParameter = descriptor.getExtensionReceiverParameter();
if (extensionReceiverParameter != null) {
implicitReceivers.add(extensionReceiverParameter);
}
return new LexicalScopeImpl(headerScope, descriptor, true, implicitReceivers,
return new LexicalScopeImpl(headerScope, descriptor, true, descriptor.getExtensionReceiverParameter(), descriptor.getContextReceiverParameters(),
LexicalScopeKind.PROPERTY_ACCESSOR_BODY);
}
@@ -1029,7 +1024,7 @@ public class BodyResolver {
KtProperty property = (KtProperty) function.getParent();
SourceElement propertySourceElement = KotlinSourceElementKt.toSourceElement(property);
SyntheticFieldDescriptor fieldDescriptor = new SyntheticFieldDescriptor(accessorDescriptor, propertySourceElement);
innerScope = new LexicalScopeImpl(innerScope, functionDescriptor, true, Collections.emptyList(),
innerScope = new LexicalScopeImpl(innerScope, functionDescriptor, true, null, Collections.emptyList(),
LexicalScopeKind.PROPERTY_ACCESSOR_BODY,
LocalRedeclarationChecker.DO_NOTHING.INSTANCE, handler -> {
handler.addVariableDescriptor(fieldDescriptor);
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.resolve;
import com.google.common.collect.Lists;
import kotlin.Unit;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.descriptors.*;
@@ -25,7 +24,6 @@ import org.jetbrains.kotlin.resolve.scopes.*;
import org.jetbrains.kotlin.types.*;
import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
import java.util.ArrayList;
import java.util.List;
public class FunctionDescriptorUtil {
@@ -67,20 +65,9 @@ public class FunctionDescriptorUtil {
@NotNull FunctionDescriptor descriptor,
@NotNull LocalRedeclarationChecker redeclarationChecker
) {
List<ReceiverParameterDescriptor> implicitReceivers = new ArrayList<>();
ReceiverParameterDescriptor extensionReceiverParameter = descriptor.getExtensionReceiverParameter();
if (descriptor.getExtensionReceiverParameter() != null) {
implicitReceivers.add(extensionReceiverParameter);
}
List<ReceiverParameterDescriptor> contextReceiverParameters = descriptor.getContextReceiverParameters();
if (!contextReceiverParameters.isEmpty()) {
implicitReceivers.addAll(
Lists.reverse(contextReceiverParameters)
);
}
return new LexicalScopeImpl(
outerScope, descriptor, true, implicitReceivers,
LexicalScopeKind.FUNCTION_INNER_SCOPE, redeclarationChecker,
outerScope, descriptor, true, descriptor.getExtensionReceiverParameter(),
descriptor.getContextReceiverParameters(), LexicalScopeKind.FUNCTION_INNER_SCOPE, redeclarationChecker,
handler -> {
for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) {
handler.addClassifierDescriptor(typeParameter);
@@ -102,6 +102,15 @@ class DiagnosticReporterByTrackingStrategy(
)
)
}
MultipleArgumentsApplicableForContextReceiver::class.java -> {
val callElement = psiKotlinCall.psiCall.callElement
trace.report(
MULTIPLE_ARGUMENTS_APPLICABLE_FOR_CONTEXT_RECEIVER.on(
callElement,
(diagnostic as MultipleArgumentsApplicableForContextReceiver).receiverDescriptor.value.toString()
)
)
}
}
}
@@ -49,7 +49,8 @@ object DslScopeViolationCallChecker : CallChecker {
) {
val receiversUntilOneFromTheCall =
context.scope.parentsWithSelf
.flatMap { (it as? LexicalScope)?.implicitReceivers ?: emptyList() }
.filterIsInstance<LexicalScope>()
.flatMap { listOfNotNull(it.implicitReceiver) + it.contextReceiversGroup }
.map { it.value }
.takeWhile { it != callImplicitReceiver }.toList()
@@ -366,8 +366,13 @@ class NewResolutionOldInference(
) : ImplicitScopeTower {
private val cache = HashMap<ReceiverValue, ReceiverValueWithSmartCastInfo>()
override fun getImplicitReceivers(scope: LexicalScope): List<ReceiverValueWithSmartCastInfo> =
scope.implicitReceivers.map { cache.getOrPut(it.value) { resolutionContext.transformToReceiverWithSmartCastInfo(it.value) } }
override fun getImplicitReceiver(scope: LexicalScope): ReceiverValueWithSmartCastInfo? =
scope.implicitReceiver?.value?.let {
cache.getOrPut(it) { resolutionContext.transformToReceiverWithSmartCastInfo(it) }
}
override fun getContextReceivers(scope: LexicalScope): List<ReceiverValueWithSmartCastInfo> =
scope.contextReceiversGroup.map { cache.getOrPut(it.value) { resolutionContext.transformToReceiverWithSmartCastInfo(it.value) } }
override fun getNameForGivenImportAlias(name: Name): Name? =
(resolutionContext.call.callElement.containingFile as? KtFile)?.getNameForGivenImportAlias(name)
@@ -400,8 +400,16 @@ class PSICallResolver(
override val implicitsResolutionFilter: ImplicitsExtensionsResolutionFilter get() = this@PSICallResolver.implicitsResolutionFilter
private val cache = HashMap<ReceiverParameterDescriptor, ReceiverValueWithSmartCastInfo>()
override fun getImplicitReceivers(scope: LexicalScope): List<ReceiverValueWithSmartCastInfo> =
scope.implicitReceivers.map { cache.getOrPut(it) { context.transformToReceiverWithSmartCastInfo(it.value) } }
override fun getImplicitReceiver(scope: LexicalScope): ReceiverValueWithSmartCastInfo? {
val implicitReceiver = scope.implicitReceiver ?: return null
return cache.getOrPut(implicitReceiver) {
context.transformToReceiverWithSmartCastInfo(implicitReceiver.value)
}
}
override fun getContextReceivers(scope: LexicalScope): List<ReceiverValueWithSmartCastInfo> =
scope.contextReceiversGroup.map { cache.getOrPut(it) { context.transformToReceiverWithSmartCastInfo(it.value) } }
override fun getNameForGivenImportAlias(name: Name): Name? =
(context.call.callElement.containingFile as? KtFile)?.getNameForGivenImportAlias(name)
@@ -33,7 +33,7 @@ class ClassResolutionScopesSupport(
private val getOuterScope: () -> LexicalScope
) {
private fun scopeWithGenerics(parent: LexicalScope): LexicalScopeImpl {
return LexicalScopeImpl(parent, classDescriptor, false, emptyList(), LexicalScopeKind.CLASS_HEADER) {
return LexicalScopeImpl(parent, classDescriptor, false, null, emptyList(), LexicalScopeKind.CLASS_HEADER) {
classDescriptor.declaredTypeParameters.forEach { addClassifierDescriptor(it) }
}
}
@@ -67,7 +67,8 @@ class ClassResolutionScopesSupport(
scopeWithGenerics,
classDescriptor,
true,
classDescriptor.contextReceivers + classDescriptor.thisAsReceiverParameter,
classDescriptor.thisAsReceiverParameter,
classDescriptor.contextReceivers,
LexicalScopeKind.CLASS_MEMBER_SCOPE
)
}
@@ -94,7 +95,8 @@ class ClassResolutionScopesSupport(
val lexicalChainedScope = LexicalChainedScope.create(
parentForNewScope, ownerDescriptor,
isOwnerDescriptorAccessibleByLabel = false,
implicitReceivers = listOfNotNull(companionObjectDescriptor?.thisAsReceiverParameter),
implicitReceiver = companionObjectDescriptor?.thisAsReceiverParameter,
contextReceiversGroup = emptyList(),
kind = LexicalScopeKind.CLASS_INHERITANCE,
classDescriptor.staticScope,
classDescriptor.unsubstitutedInnerClassesScope,
@@ -144,6 +146,7 @@ fun scopeForInitializerResolution(
classDescriptor.scopeForMemberDeclarationResolution,
parentDescriptor,
false,
null,
emptyList(),
LexicalScopeKind.CLASS_INITIALIZER
) {
@@ -50,7 +50,7 @@ class ValueParameterResolver(
inferenceSession: InferenceSession?
) {
val scopeForDefaultValue =
LexicalScopeImpl(declaringScope, declaringScope.ownerDescriptor, false, listOf(), LexicalScopeKind.DEFAULT_VALUE)
LexicalScopeImpl(declaringScope, declaringScope.ownerDescriptor, false, null, listOf(), LexicalScopeKind.DEFAULT_VALUE)
val contextForDefaultValue = ExpressionTypingContext.newContext(
trace, scopeForDefaultValue, dataFlowInfo, TypeUtils.NO_EXPECTED_TYPE,
@@ -87,3 +87,30 @@ private fun ConstraintSystemBuilder.addConstraintIfCompatible(
}
!hasContradiction
}
fun ConstraintSystemBuilder.isSubtypeConstraintCompatible(
lowerType: KotlinTypeMarker,
upperType: KotlinTypeMarker,
position: ConstraintPosition
): Boolean = isConstraintCompatible(lowerType, upperType, position, ConstraintKind.LOWER)
private fun ConstraintSystemBuilder.isConstraintCompatible(
lowerType: KotlinTypeMarker,
upperType: KotlinTypeMarker,
position: ConstraintPosition,
kind: ConstraintKind
): Boolean {
var isCompatible = false
runTransaction {
if (!hasContradiction) {
when (kind) {
ConstraintKind.LOWER -> addSubtypeConstraint(lowerType, upperType, position)
ConstraintKind.UPPER -> addSubtypeConstraint(upperType, lowerType, position)
ConstraintKind.EQUALITY -> addEqualityConstraint(lowerType, upperType, position)
}
}
isCompatible = !hasContradiction
false
}
return isCompatible
}
@@ -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
@@ -0,0 +1,11 @@
interface C1 {
fun foo() {}
}
interface C2 {
fun foo() {}
}
context(C1, C2)
fun bar() {
foo()
}
@@ -0,0 +1,11 @@
interface C1 {
fun foo() {}
}
interface C2 {
fun foo() {}
}
context(C1, C2)
fun bar() {
<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>()
}
@@ -0,0 +1,17 @@
package
public fun bar(): kotlin.Unit
public interface C1 {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface C2 {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,14 @@
interface Common
interface C1 : Common
interface C2 : Common
context(Common)
fun foo() {}
fun Common.bar() {}
context(C1, C2)
fun test() {
foo()
bar()
}
@@ -0,0 +1,14 @@
interface Common
interface C1 : Common
interface C2 : Common
context(Common)
fun foo() {}
fun Common.bar() {}
context(C1, C2)
fun test() {
<!MULTIPLE_ARGUMENTS_APPLICABLE_FOR_CONTEXT_RECEIVER!>foo()<!>
bar()
}
@@ -0,0 +1,23 @@
package
public fun foo(): kotlin.Unit
public fun test(): kotlin.Unit
public fun Common.bar(): kotlin.Unit
public interface C1 : Common {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface C2 : Common {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface Common {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -10582,6 +10582,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/extensions/contextReceivers"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("ambiguityInGroupSimple.kt")
public void testAmbiguityInGroupSimple() throws Exception {
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/ambiguityInGroupSimple.kt");
}
@Test
@TestMetadata("ambiguityInGroupWithInheritance.kt")
public void testAmbiguityInGroupWithInheritance() throws Exception {
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/ambiguityInGroupWithInheritance.kt");
}
@Test
@TestMetadata("dp.kt")
public void testDp() throws Exception {
@@ -148,7 +148,7 @@ public class ExpectedResolveDataUtil {
emptyModule.initialize(PackageFragmentProvider.Empty.INSTANCE);
LexicalScopeImpl lexicalScope = new LexicalScopeImpl(ImportingScope.Empty.INSTANCE, classDescriptor, false,
Collections.singletonList(classDescriptor.getThisAsReceiverParameter()),
classDescriptor.getThisAsReceiverParameter(), Collections.emptyList(),
LexicalScopeKind.SYNTHETIC);
LanguageVersionSettings languageVersionSettings = CommonConfigurationKeysKt.getLanguageVersionSettings(environment.getConfiguration());
@@ -100,7 +100,7 @@ public class DefaultModalityModifiersTest extends KotlinTestWithEnvironment {
DeclarationDescriptor classDescriptor =
bindingContext.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, aClass);
return new LexicalScopeImpl(
ScopeUtilsKt.memberScopeAsImportingScope(libraryScope), root, false, Collections.emptyList(),
ScopeUtilsKt.memberScopeAsImportingScope(libraryScope), root, false, null, Collections.emptyList(),
LexicalScopeKind.SYNTHETIC, LocalRedeclarationChecker.DO_NOTHING.INSTANCE,
handler -> {
handler.addClassifierDescriptor((ClassifierDescriptor) classDescriptor);
@@ -551,7 +551,7 @@ public class KotlinTypeCheckerTest extends KotlinTestWithEnvironment {
);
LexicalScope scope = new LexicalScopeImpl(scopeWithImports, scopeWithImports.getOwnerDescriptor(), false,
Collections.singletonList(receiverParameterDescriptor), LexicalScopeKind.SYNTHETIC);
receiverParameterDescriptor, Collections.emptyList(), LexicalScopeKind.SYNTHETIC);
assertType(scope, expression, expectedType);
}
@@ -91,7 +91,7 @@ public class TypeSubstitutorTest extends KotlinTestWithEnvironment {
LocalRedeclarationChecker redeclarationChecker =
new ThrowingLocalRedeclarationChecker(new OverloadChecker(TypeSpecificityComparator.NONE.INSTANCE));
LexicalScope typeParameters = new LexicalScopeImpl(
topLevelScope, module, false, Collections.emptyList(), LexicalScopeKind.SYNTHETIC,
topLevelScope, module, false, null, Collections.emptyList(), LexicalScopeKind.SYNTHETIC,
redeclarationChecker,
handler -> {
for (TypeParameterDescriptor parameterDescriptor : contextClass.getTypeConstructor().getParameters()) {
@@ -101,7 +101,8 @@ public class TypeSubstitutorTest extends KotlinTestWithEnvironment {
}
);
return LexicalChainedScope.Companion.create(
typeParameters, module, false, Collections.emptyList(), LexicalScopeKind.SYNTHETIC,
typeParameters, module, false, null, Collections.emptyList(),
LexicalScopeKind.SYNTHETIC,
contextClass.getDefaultType().getMemberScope(),
module.getBuiltIns().getBuiltInsPackageScope()
);
@@ -198,7 +198,7 @@ public class TypeUnifierTest extends KotlinTestWithEnvironment {
private TypeProjection makeType(String typeStr) {
LexicalScope withX = new LexicalScopeImpl(
builtinsImportingScope, module,
false, Collections.emptyList(), LexicalScopeKind.SYNTHETIC, LocalRedeclarationChecker.DO_NOTHING.INSTANCE,
false, null, Collections.emptyList(), LexicalScopeKind.SYNTHETIC, LocalRedeclarationChecker.DO_NOTHING.INSTANCE,
handler -> {
handler.addClassifierDescriptor(x);
handler.addClassifierDescriptor(y);
@@ -374,7 +374,8 @@ class LazyScriptDescriptor(
outerScope,
receiverClassDescriptor,
true,
listOf(receiverClassDescriptor.thisAsReceiverParameter),
receiverClassDescriptor.thisAsReceiverParameter,
listOf(),
LexicalScopeKind.CLASS_MEMBER_SCOPE
).addImportingScope(
AllUnderImportScope.create(receiverClassDescriptor, emptyList())
@@ -41,7 +41,8 @@ class ReplImplicitsExtensionsResolutionFilter(
): Sequence<ScopeWithImplicitsExtensionsResolutionInfo> {
val processedReceivers = mutableSetOf<String>()
return scopes.map { scope ->
val receivers = (scope as? LexicalScope)?.implicitReceivers?.map { it.value }
val receivers = (if (scope is LexicalScope) listOfNotNull(scope.implicitReceiver) + scope.contextReceiversGroup else null)
?.map { it.value }
val keep = receivers?.all {
lock.read {
when (val descriptorFqName = (it as? ImplicitClassReceiver)?.declarationDescriptor?.fqNameSafe?.asString()) {