[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); 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") @TestMetadata("dp.kt")
public void testDp() throws Exception { public void testDp() throws Exception {
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/dp.kt"); 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); 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 @Test
@TestMetadata("dp.kt") @TestMetadata("dp.kt")
public void testDp() throws Exception { 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); 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 @Test
@TestMetadata("dp.kt") @TestMetadata("dp.kt")
public void testDp() throws Exception { public void testDp() throws Exception {
@@ -1198,6 +1198,7 @@ public interface Errors {
// Context receivers // Context receivers
DiagnosticFactory1<KtElement, String> NO_CONTEXT_RECEIVER = DiagnosticFactory1.create(ERROR); DiagnosticFactory1<KtElement, String> NO_CONTEXT_RECEIVER = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<KtElement, String> MULTIPLE_ARGUMENTS_APPLICABLE_FOR_CONTEXT_RECEIVER = DiagnosticFactory1.create(ERROR);
// Error sets // Error sets
ImmutableSet<? extends DiagnosticFactory<?>> UNRESOLVED_REFERENCE_DIAGNOSTICS = ImmutableSet.of( 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(CONTRACT_NOT_ALLOWED, "{0}", TO_STRING);
MAP.put(NO_CONTEXT_RECEIVER, "No required context receiver found: {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(); MAP.setImmutable();
@@ -162,7 +162,7 @@ public class BodyResolver {
descriptor, localContext != null ? localContext.inferenceSession : null descriptor, localContext != null ? localContext.inferenceSession : null
), ),
scope -> new LexicalScopeImpl( scope -> new LexicalScopeImpl(
scope, descriptor, scope.isOwnerDescriptorAccessibleByLabel(), scope.getImplicitReceivers(), scope, descriptor, scope.isOwnerDescriptorAccessibleByLabel(), scope.getImplicitReceiver(), scope.getContextReceiversGroup(),
LexicalScopeKind.CONSTRUCTOR_HEADER LexicalScopeKind.CONSTRUCTOR_HEADER
), ),
localContext localContext
@@ -439,7 +439,7 @@ public class BodyResolver {
) { ) {
// Initializing a scope will report errors if any. // Initializing a scope will report errors if any.
new LexicalScopeImpl( new LexicalScopeImpl(
scopeForConstructorResolution, descriptor, true, Collections.emptyList(), LexicalScopeKind.CLASS_HEADER, scopeForConstructorResolution, descriptor, true, null, Collections.emptyList(), LexicalScopeKind.CLASS_HEADER,
new TraceBasedLocalRedeclarationChecker(trace, overloadChecker), new TraceBasedLocalRedeclarationChecker(trace, overloadChecker),
new Function1<LexicalScopeImpl.InitializeHandler, Unit>() { new Function1<LexicalScopeImpl.InitializeHandler, Unit>() {
@Override @Override
@@ -780,8 +780,8 @@ public class BodyResolver {
LexicalScope originalScope, LexicalScope originalScope,
ConstructorDescriptor unsubstitutedPrimaryConstructor ConstructorDescriptor unsubstitutedPrimaryConstructor
) { ) {
return new LexicalScopeImpl(originalScope, unsubstitutedPrimaryConstructor, false, Collections.emptyList(), return new LexicalScopeImpl(originalScope, unsubstitutedPrimaryConstructor, false, null,
LexicalScopeKind.DEFAULT_VALUE, LocalRedeclarationChecker.DO_NOTHING.INSTANCE, Collections.emptyList(), LexicalScopeKind.DEFAULT_VALUE, LocalRedeclarationChecker.DO_NOTHING.INSTANCE,
handler -> { handler -> {
for (ValueParameterDescriptor valueParameter : unsubstitutedPrimaryConstructor.getValueParameters()) { for (ValueParameterDescriptor valueParameter : unsubstitutedPrimaryConstructor.getValueParameters()) {
handler.addVariableDescriptor(valueParameter); handler.addVariableDescriptor(valueParameter);
@@ -863,12 +863,7 @@ public class BodyResolver {
LexicalScope accessorDeclaringScope = c.getDeclaringScope(accessor); LexicalScope accessorDeclaringScope = c.getDeclaringScope(accessor);
assert accessorDeclaringScope != null : "Scope for accessor " + accessor.getText() + " should exists"; assert accessorDeclaringScope != null : "Scope for accessor " + accessor.getText() + " should exists";
LexicalScope headerScope = ScopeUtils.makeScopeForPropertyHeader(accessorDeclaringScope, descriptor); LexicalScope headerScope = ScopeUtils.makeScopeForPropertyHeader(accessorDeclaringScope, descriptor);
List<ReceiverParameterDescriptor> implicitReceivers = new ArrayList<>(); return new LexicalScopeImpl(headerScope, descriptor, true, descriptor.getExtensionReceiverParameter(), descriptor.getContextReceiverParameters(),
ReceiverParameterDescriptor extensionReceiverParameter = descriptor.getExtensionReceiverParameter();
if (extensionReceiverParameter != null) {
implicitReceivers.add(extensionReceiverParameter);
}
return new LexicalScopeImpl(headerScope, descriptor, true, implicitReceivers,
LexicalScopeKind.PROPERTY_ACCESSOR_BODY); LexicalScopeKind.PROPERTY_ACCESSOR_BODY);
} }
@@ -1029,7 +1024,7 @@ public class BodyResolver {
KtProperty property = (KtProperty) function.getParent(); KtProperty property = (KtProperty) function.getParent();
SourceElement propertySourceElement = KotlinSourceElementKt.toSourceElement(property); SourceElement propertySourceElement = KotlinSourceElementKt.toSourceElement(property);
SyntheticFieldDescriptor fieldDescriptor = new SyntheticFieldDescriptor(accessorDescriptor, propertySourceElement); 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, LexicalScopeKind.PROPERTY_ACCESSOR_BODY,
LocalRedeclarationChecker.DO_NOTHING.INSTANCE, handler -> { LocalRedeclarationChecker.DO_NOTHING.INSTANCE, handler -> {
handler.addVariableDescriptor(fieldDescriptor); handler.addVariableDescriptor(fieldDescriptor);
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.resolve; package org.jetbrains.kotlin.resolve;
import com.google.common.collect.Lists;
import kotlin.Unit; import kotlin.Unit;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.descriptors.*; 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.*;
import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt; import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
import java.util.ArrayList;
import java.util.List; import java.util.List;
public class FunctionDescriptorUtil { public class FunctionDescriptorUtil {
@@ -67,20 +65,9 @@ public class FunctionDescriptorUtil {
@NotNull FunctionDescriptor descriptor, @NotNull FunctionDescriptor descriptor,
@NotNull LocalRedeclarationChecker redeclarationChecker @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( return new LexicalScopeImpl(
outerScope, descriptor, true, implicitReceivers, outerScope, descriptor, true, descriptor.getExtensionReceiverParameter(),
LexicalScopeKind.FUNCTION_INNER_SCOPE, redeclarationChecker, descriptor.getContextReceiverParameters(), LexicalScopeKind.FUNCTION_INNER_SCOPE, redeclarationChecker,
handler -> { handler -> {
for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) { for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) {
handler.addClassifierDescriptor(typeParameter); 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 = val receiversUntilOneFromTheCall =
context.scope.parentsWithSelf context.scope.parentsWithSelf
.flatMap { (it as? LexicalScope)?.implicitReceivers ?: emptyList() } .filterIsInstance<LexicalScope>()
.flatMap { listOfNotNull(it.implicitReceiver) + it.contextReceiversGroup }
.map { it.value } .map { it.value }
.takeWhile { it != callImplicitReceiver }.toList() .takeWhile { it != callImplicitReceiver }.toList()
@@ -366,8 +366,13 @@ class NewResolutionOldInference(
) : ImplicitScopeTower { ) : ImplicitScopeTower {
private val cache = HashMap<ReceiverValue, ReceiverValueWithSmartCastInfo>() private val cache = HashMap<ReceiverValue, ReceiverValueWithSmartCastInfo>()
override fun getImplicitReceivers(scope: LexicalScope): List<ReceiverValueWithSmartCastInfo> = override fun getImplicitReceiver(scope: LexicalScope): ReceiverValueWithSmartCastInfo? =
scope.implicitReceivers.map { cache.getOrPut(it.value) { resolutionContext.transformToReceiverWithSmartCastInfo(it.value) } } 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? = override fun getNameForGivenImportAlias(name: Name): Name? =
(resolutionContext.call.callElement.containingFile as? KtFile)?.getNameForGivenImportAlias(name) (resolutionContext.call.callElement.containingFile as? KtFile)?.getNameForGivenImportAlias(name)
@@ -400,8 +400,16 @@ class PSICallResolver(
override val implicitsResolutionFilter: ImplicitsExtensionsResolutionFilter get() = this@PSICallResolver.implicitsResolutionFilter override val implicitsResolutionFilter: ImplicitsExtensionsResolutionFilter get() = this@PSICallResolver.implicitsResolutionFilter
private val cache = HashMap<ReceiverParameterDescriptor, ReceiverValueWithSmartCastInfo>() private val cache = HashMap<ReceiverParameterDescriptor, ReceiverValueWithSmartCastInfo>()
override fun getImplicitReceivers(scope: LexicalScope): List<ReceiverValueWithSmartCastInfo> = override fun getImplicitReceiver(scope: LexicalScope): ReceiverValueWithSmartCastInfo? {
scope.implicitReceivers.map { cache.getOrPut(it) { context.transformToReceiverWithSmartCastInfo(it.value) } } 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? = override fun getNameForGivenImportAlias(name: Name): Name? =
(context.call.callElement.containingFile as? KtFile)?.getNameForGivenImportAlias(name) (context.call.callElement.containingFile as? KtFile)?.getNameForGivenImportAlias(name)
@@ -33,7 +33,7 @@ class ClassResolutionScopesSupport(
private val getOuterScope: () -> LexicalScope private val getOuterScope: () -> LexicalScope
) { ) {
private fun scopeWithGenerics(parent: LexicalScope): LexicalScopeImpl { 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) } classDescriptor.declaredTypeParameters.forEach { addClassifierDescriptor(it) }
} }
} }
@@ -67,7 +67,8 @@ class ClassResolutionScopesSupport(
scopeWithGenerics, scopeWithGenerics,
classDescriptor, classDescriptor,
true, true,
classDescriptor.contextReceivers + classDescriptor.thisAsReceiverParameter, classDescriptor.thisAsReceiverParameter,
classDescriptor.contextReceivers,
LexicalScopeKind.CLASS_MEMBER_SCOPE LexicalScopeKind.CLASS_MEMBER_SCOPE
) )
} }
@@ -94,7 +95,8 @@ class ClassResolutionScopesSupport(
val lexicalChainedScope = LexicalChainedScope.create( val lexicalChainedScope = LexicalChainedScope.create(
parentForNewScope, ownerDescriptor, parentForNewScope, ownerDescriptor,
isOwnerDescriptorAccessibleByLabel = false, isOwnerDescriptorAccessibleByLabel = false,
implicitReceivers = listOfNotNull(companionObjectDescriptor?.thisAsReceiverParameter), implicitReceiver = companionObjectDescriptor?.thisAsReceiverParameter,
contextReceiversGroup = emptyList(),
kind = LexicalScopeKind.CLASS_INHERITANCE, kind = LexicalScopeKind.CLASS_INHERITANCE,
classDescriptor.staticScope, classDescriptor.staticScope,
classDescriptor.unsubstitutedInnerClassesScope, classDescriptor.unsubstitutedInnerClassesScope,
@@ -144,6 +146,7 @@ fun scopeForInitializerResolution(
classDescriptor.scopeForMemberDeclarationResolution, classDescriptor.scopeForMemberDeclarationResolution,
parentDescriptor, parentDescriptor,
false, false,
null,
emptyList(), emptyList(),
LexicalScopeKind.CLASS_INITIALIZER LexicalScopeKind.CLASS_INITIALIZER
) { ) {
@@ -50,7 +50,7 @@ class ValueParameterResolver(
inferenceSession: InferenceSession? inferenceSession: InferenceSession?
) { ) {
val scopeForDefaultValue = 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( val contextForDefaultValue = ExpressionTypingContext.newContext(
trace, scopeForDefaultValue, dataFlowInfo, TypeUtils.NO_EXPECTED_TYPE, trace, scopeForDefaultValue, dataFlowInfo, TypeUtils.NO_EXPECTED_TYPE,
@@ -87,3 +87,30 @@ private fun ConstraintSystemBuilder.addConstraintIfCompatible(
} }
!hasContradiction !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.TypeArgumentsToParametersMapper.TypeArgumentsMapping.NoExplicitArguments
import org.jetbrains.kotlin.resolve.calls.components.candidate.CallableReferenceResolutionCandidate import org.jetbrains.kotlin.resolve.calls.components.candidate.CallableReferenceResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.components.candidate.ResolutionCandidate import org.jetbrains.kotlin.resolve.calls.components.candidate.ResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation import org.jetbrains.kotlin.resolve.calls.inference.*
import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible
import org.jetbrains.kotlin.resolve.calls.inference.components.* import org.jetbrains.kotlin.resolve.calls.inference.components.*
import org.jetbrains.kotlin.resolve.calls.inference.model.* 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.model.*
import org.jetbrains.kotlin.resolve.calls.smartcasts.getReceiverValueWithSmartCast import org.jetbrains.kotlin.resolve.calls.smartcasts.getReceiverValueWithSmartCast
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.* import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.*
@@ -807,30 +804,60 @@ internal object ErrorDescriptorResolutionPart : ResolutionPart() {
} }
internal object CheckContextReceiversResolutionPart : ResolutionPart() { internal object CheckContextReceiversResolutionPart : ResolutionPart() {
private fun ResolutionCandidate.checkReceiver( private data class ApplicableArgumentWithConstraint(
implicitReceivers: Collection<ReceiverValueWithSmartCastInfo>, val argument: SimpleKotlinCallArgument,
val argumentType: UnwrappedType,
val expectedType: UnwrappedType,
val position: ConstraintPosition
)
private fun ResolutionCandidate.findContextReceiver(
implicitReceiversGroups: List<List<ReceiverValueWithSmartCastInfo>>,
candidateContextReceiverParameter: ReceiverParameterDescriptor candidateContextReceiverParameter: ReceiverParameterDescriptor
): SimpleKotlinCallArgument? { ): SimpleKotlinCallArgument? {
val csBuilder = getSystem().getBuilder()
for (implicitReceiver in implicitReceivers) { fun ReceiverValueWithSmartCastInfo.createArgumentIfCompatible(): ApplicableArgumentWithConstraint? {
val argument = ReceiverExpressionKotlinCallArgument(implicitReceiver) val csBuilder = getSystem().getBuilder()
val argument = ReceiverExpressionKotlinCallArgument(this)
val expectedTypeUnprepared = argument.getExpectedType(candidateContextReceiverParameter, callComponents.languageVersionSettings) val expectedTypeUnprepared = argument.getExpectedType(candidateContextReceiverParameter, callComponents.languageVersionSettings)
val expectedType = prepareExpectedType(expectedTypeUnprepared) val expectedType = prepareExpectedType(expectedTypeUnprepared)
val argumentType = captureFromTypeParameterUpperBoundIfNeeded(argument.receiver.stableType, expectedType) val argumentType = captureFromTypeParameterUpperBoundIfNeeded(argument.receiver.stableType, expectedType)
val position = ReceiverConstraintPositionImpl(argument) 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)) diagnosticsFromResolutionParts.add(NoContextReceiver(candidateContextReceiverParameter))
return null return null
} }
override fun ResolutionCandidate.process(workIndex: Int) { override fun ResolutionCandidate.process(workIndex: Int) {
val implicitReceivers = scopeTower.lexicalScope.parentsWithSelf val parentLexicalScopes = scopeTower.lexicalScope.parentsWithSelf.filterIsInstance<LexicalScope>()
.flatMap { if (it is LexicalScope) scopeTower.getImplicitReceivers(it) else emptyList() }.toList() 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>() val contextReceiversArguments = mutableListOf<SimpleKotlinCallArgument>()
for (candidateContextReceiverParameter in candidateDescriptor.contextReceiverParameters) { for (candidateContextReceiverParameter in candidateDescriptor.contextReceiverParameters) {
contextReceiversArguments.add(findContextReceiver(implicitReceivers, candidateContextReceiverParameter) ?: return) contextReceiversArguments.add(findContextReceiver(implicitReceiversGroups, candidateContextReceiverParameter) ?: return)
} }
resolvedCall.contextReceiversArguments = contextReceiversArguments 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( class KotlinConstraintSystemDiagnostic(
val error: ConstraintSystemError val error: ConstraintSystemError
) : KotlinCallDiagnostic(error.applicability) { ) : KotlinCallDiagnostic(error.applicability) {
@@ -37,7 +37,9 @@ import org.jetbrains.kotlin.types.TypeApproximator
interface ImplicitScopeTower { interface ImplicitScopeTower {
val lexicalScope: LexicalScope 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? 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) : internal class QualifierScopeTowerLevel(scopeTower: ImplicitScopeTower, val qualifier: QualifierReceiver) :
AbstractScopeTowerLevel(scopeTower) { AbstractScopeTowerLevel(scopeTower) {
override fun getVariables(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) = qualifier.staticScope override fun getVariables(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) = qualifier.staticScope
@@ -100,6 +100,12 @@ class TowerResolver {
name: Name name: Name
): Collection<C> = Task(this, processor, resultCollector, useOrder, name).run() ): 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 inner class Task<out C : Candidate>(
private val implicitScopeTower: ImplicitScopeTower, private val implicitScopeTower: ImplicitScopeTower,
private val processor: ScopeTowerProcessor<C>, private val processor: ScopeTowerProcessor<C>,
@@ -135,27 +141,40 @@ class TowerResolver {
} }
} }
lexicalScope.parentsWithSelf.forEach { scope -> val parentScopes = lexicalScope.parentsWithSelf
if (scope is LexicalScope) { val lexicalScopes = parentScopes.filterIsInstance<LexicalScope>()
if (!scope.kind.withLocalDescriptors) { lexicalScopes.forEach { scope ->
addLevel( if (!scope.kind.withLocalDescriptors) {
ScopeBasedTowerLevel(this@createNonLocalLevels, scope),
scope.mayFitForName(name)
)
}
getImplicitReceivers(scope).forEach {
addLevel(
MemberScopeTowerLevel(this@createNonLocalLevels, it),
it.mayFitForName(name)
)
}
} else {
addLevel( addLevel(
ImportingScopeBasedTowerLevel(this@createNonLocalLevels, scope as ImportingScope), ScopeBasedTowerLevel(this@createNonLocalLevels, scope),
scope.mayFitForName(name) 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 return mainResult
@@ -189,31 +208,57 @@ class TowerResolver {
TowerData.TowerLevel(localLevel).process()?.let { return it } TowerData.TowerLevel(localLevel).process()?.let { return it }
} }
fun processScope(scope: HierarchicalScope, resolveExtensionsForImplicitReceiver: Boolean): Collection<C>? { fun processScope(scope: HierarchicalScope, scopeResolutionStep: ScopeResolutionStep): Collection<C>? {
if (scope is LexicalScope) { when (scopeResolutionStep) {
// statics is ScopeResolutionStep.LexicalScopesResolution -> if (scope is LexicalScope) {
if (!scope.kind.withLocalDescriptors) { if (!scope.kind.withLocalDescriptors) {
TowerData.TowerLevel(ScopeBasedTowerLevel(implicitScopeTower, scope)) 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 } .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 return null
} }
if (implicitScopeTower.implicitsResolutionFilter === ImplicitsExtensionsResolutionFilter.Default) { if (implicitScopeTower.implicitsResolutionFilter === ImplicitsExtensionsResolutionFilter.Default) {
for (scope in implicitScopeTower.lexicalScope.parentsWithSelf) { val scopes = implicitScopeTower.lexicalScope.parentsWithSelf
processScope(scope, true)?.let { return it } 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 { } else {
for (scopeInfo in implicitScopeTower.allScopesWithImplicitsResolutionInfo()) { val scopeInfos = implicitScopeTower.allScopesWithImplicitsResolutionInfo()
processScope(scopeInfo.scope, scopeInfo.resolveExtensionsForImplicitReceiver)?.let { return it } 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, parent: LexicalScope,
override val ownerDescriptor: DeclarationDescriptor, override val ownerDescriptor: DeclarationDescriptor,
override val isOwnerDescriptorAccessibleByLabel: Boolean, override val isOwnerDescriptorAccessibleByLabel: Boolean,
override val implicitReceivers: List<ReceiverParameterDescriptor>, override val implicitReceiver: ReceiverParameterDescriptor?,
override val contextReceiversGroup: List<ReceiverParameterDescriptor>,
override val kind: LexicalScopeKind, override val kind: LexicalScopeKind,
// NB. Here can be very special subtypes of MemberScope (e.g., DeprecatedMemberScope). // 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 // 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: ", "; for descriptor: ",
ownerDescriptor.name, ownerDescriptor.name,
" with implicitReceiver: ", " 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() p.pushIndent()
@@ -111,13 +114,14 @@ class LexicalChainedScope private constructor(
parent: LexicalScope, parent: LexicalScope,
ownerDescriptor: DeclarationDescriptor, ownerDescriptor: DeclarationDescriptor,
isOwnerDescriptorAccessibleByLabel: Boolean, isOwnerDescriptorAccessibleByLabel: Boolean,
implicitReceivers: List<ReceiverParameterDescriptor>, implicitReceiver: ReceiverParameterDescriptor?,
contextReceiversGroup: List<ReceiverParameterDescriptor>,
kind: LexicalScopeKind, kind: LexicalScopeKind,
vararg memberScopes: MemberScope?, vararg memberScopes: MemberScope?,
isStaticScope: Boolean = false isStaticScope: Boolean = false
): LexicalScope = ): LexicalScope =
LexicalChainedScope( LexicalChainedScope(
parent, ownerDescriptor, isOwnerDescriptorAccessibleByLabel, implicitReceivers, kind, parent, ownerDescriptor, isOwnerDescriptorAccessibleByLabel, implicitReceiver, contextReceiversGroup, kind,
listOfNonEmptyScopes(*memberScopes).toTypedArray(), listOfNonEmptyScopes(*memberScopes).toTypedArray(),
isStaticScope isStaticScope
) )
@@ -23,7 +23,8 @@ class LexicalScopeImpl @JvmOverloads constructor(
parent: HierarchicalScope, parent: HierarchicalScope,
override val ownerDescriptor: DeclarationDescriptor, override val ownerDescriptor: DeclarationDescriptor,
override val isOwnerDescriptorAccessibleByLabel: Boolean, override val isOwnerDescriptorAccessibleByLabel: Boolean,
override val implicitReceivers: List<ReceiverParameterDescriptor>, override val implicitReceiver: ReceiverParameterDescriptor?,
override val contextReceiversGroup: List<ReceiverParameterDescriptor>,
override val kind: LexicalScopeKind, override val kind: LexicalScopeKind,
redeclarationChecker: LocalRedeclarationChecker = LocalRedeclarationChecker.DO_NOTHING, redeclarationChecker: LocalRedeclarationChecker = LocalRedeclarationChecker.DO_NOTHING,
initialize: LexicalScopeImpl.InitializeHandler.() -> Unit = {} initialize: LexicalScopeImpl.InitializeHandler.() -> Unit = {}
@@ -43,7 +44,9 @@ class LexicalScopeImpl @JvmOverloads constructor(
"; for descriptor: ", "; for descriptor: ",
ownerDescriptor.name, ownerDescriptor.name,
" with implicitReceiver: ", " 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() p.pushIndent()
@@ -30,7 +30,9 @@ class LexicalWritableScope(
override val kind: LexicalScopeKind override val kind: LexicalScopeKind
) : LexicalScopeStorage(parent, redeclarationChecker) { ) : LexicalScopeStorage(parent, redeclarationChecker) {
override val implicitReceivers: List<ReceiverParameterDescriptor> override val implicitReceiver: ReceiverParameterDescriptor?
get() = null
override val contextReceiversGroup: List<ReceiverParameterDescriptor>
get() = emptyList() get() = emptyList()
private var canWrite: Boolean = true private var canWrite: Boolean = true
@@ -111,7 +113,9 @@ class LexicalWritableScope(
"; for descriptor: ", "; for descriptor: ",
ownerDescriptor.name, ownerDescriptor.name,
" with implicitReceivers: ", " 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() p.pushIndent()
@@ -36,7 +36,8 @@ public final class ScopeUtils {
@NotNull LexicalScope parent, @NotNull LexicalScope parent,
@NotNull PropertyDescriptor propertyDescriptor @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() // redeclaration on type parameters should be reported early, see: DescriptorResolver.resolvePropertyDescriptor()
LocalRedeclarationChecker.DO_NOTHING.INSTANCE, LocalRedeclarationChecker.DO_NOTHING.INSTANCE,
handler -> { handler -> {
@@ -52,7 +53,8 @@ public final class ScopeUtils {
@NotNull LexicalScope propertyHeader, @NotNull LexicalScope propertyHeader,
@NotNull PropertyDescriptor propertyDescriptor @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 @NotNull
@@ -60,14 +62,9 @@ public final class ScopeUtils {
@NotNull LexicalScope parent, @NotNull LexicalScope parent,
@NotNull VariableDescriptorWithAccessors variableDescriptor @NotNull VariableDescriptorWithAccessors variableDescriptor
) { ) {
List<ReceiverParameterDescriptor> implicitReceivers = new ArrayList<>();
ReceiverParameterDescriptor extensionReceiverParameter = variableDescriptor.getExtensionReceiverParameter();
if (extensionReceiverParameter != null) {
implicitReceivers.add(extensionReceiverParameter);
}
// todo: very strange scope! // todo: very strange scope!
return new LexicalScopeImpl(parent, variableDescriptor, true, implicitReceivers, return new LexicalScopeImpl(parent, variableDescriptor, true, variableDescriptor.getExtensionReceiverParameter(),
LexicalScopeKind.PROPERTY_DELEGATE_METHOD /* TODO: Context receivers? */ Collections.emptyList(), LexicalScopeKind.PROPERTY_DELEGATE_METHOD
); );
} }
@@ -36,7 +36,8 @@ interface LexicalScope : HierarchicalScope {
val ownerDescriptor: DeclarationDescriptor val ownerDescriptor: DeclarationDescriptor
val isOwnerDescriptorAccessibleByLabel: Boolean val isOwnerDescriptorAccessibleByLabel: Boolean
val implicitReceivers: List<ReceiverParameterDescriptor> val implicitReceiver: ReceiverParameterDescriptor?
val contextReceiversGroup: List<ReceiverParameterDescriptor>
val kind: LexicalScopeKind val kind: LexicalScopeKind
@@ -50,7 +51,9 @@ interface LexicalScope : HierarchicalScope {
override val isOwnerDescriptorAccessibleByLabel: Boolean override val isOwnerDescriptorAccessibleByLabel: Boolean
get() = false get() = false
override val implicitReceivers: List<ReceiverParameterDescriptor> override val implicitReceiver: ReceiverParameterDescriptor?
get() = null
override val contextReceiversGroup: List<ReceiverParameterDescriptor>
get() = emptyList() get() = emptyList()
override val kind: LexicalScopeKind 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 * 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 { fun LexicalScope.getImplicitReceiversHierarchy(): List<ReceiverParameterDescriptor> = collectFromMeAndParent {
(it as? LexicalScope)?.implicitReceivers if (it is LexicalScope) listOfNotNull(it.implicitReceiver) + it.contextReceiversGroup else null
}.flatten() }.flatten()
fun LexicalScope.getDeclarationsByLabel(labelName: Name): Collection<DeclarationDescriptor> = collectAllFromMeAndParent { fun LexicalScope.getDeclarationsByLabel(labelName: Name): Collection<DeclarationDescriptor> = collectAllFromMeAndParent {
@@ -261,7 +261,7 @@ fun LexicalScope.replaceImportingScopes(importingScopeChain: ImportingScope?): L
fun LexicalScope.createScopeForDestructuring(newReceiver: ReceiverParameterDescriptor?): LexicalScope { fun LexicalScope.createScopeForDestructuring(newReceiver: ReceiverParameterDescriptor?): LexicalScope {
return LexicalScopeImpl( return LexicalScopeImpl(
parent, ownerDescriptor, isOwnerDescriptorAccessibleByLabel, parent, ownerDescriptor, isOwnerDescriptorAccessibleByLabel,
listOfNotNull(newReceiver), newReceiver, listOf(),
LexicalScopeKind.FUNCTION_HEADER_FOR_DESTRUCTURING 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 ownerDescriptor: DeclarationDescriptor = ErrorUtils.createErrorClass("<ERROR CLASS FOR ERROR SCOPE>")
override val isOwnerDescriptorAccessibleByLabel: Boolean = false 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 val kind: LexicalScopeKind = LexicalScopeKind.THROWING
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? = null 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); 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 @Test
@TestMetadata("dp.kt") @TestMetadata("dp.kt")
public void testDp() throws Exception { public void testDp() throws Exception {
@@ -148,7 +148,7 @@ public class ExpectedResolveDataUtil {
emptyModule.initialize(PackageFragmentProvider.Empty.INSTANCE); emptyModule.initialize(PackageFragmentProvider.Empty.INSTANCE);
LexicalScopeImpl lexicalScope = new LexicalScopeImpl(ImportingScope.Empty.INSTANCE, classDescriptor, false, LexicalScopeImpl lexicalScope = new LexicalScopeImpl(ImportingScope.Empty.INSTANCE, classDescriptor, false,
Collections.singletonList(classDescriptor.getThisAsReceiverParameter()), classDescriptor.getThisAsReceiverParameter(), Collections.emptyList(),
LexicalScopeKind.SYNTHETIC); LexicalScopeKind.SYNTHETIC);
LanguageVersionSettings languageVersionSettings = CommonConfigurationKeysKt.getLanguageVersionSettings(environment.getConfiguration()); LanguageVersionSettings languageVersionSettings = CommonConfigurationKeysKt.getLanguageVersionSettings(environment.getConfiguration());
@@ -100,7 +100,7 @@ public class DefaultModalityModifiersTest extends KotlinTestWithEnvironment {
DeclarationDescriptor classDescriptor = DeclarationDescriptor classDescriptor =
bindingContext.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, aClass); bindingContext.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, aClass);
return new LexicalScopeImpl( return new LexicalScopeImpl(
ScopeUtilsKt.memberScopeAsImportingScope(libraryScope), root, false, Collections.emptyList(), ScopeUtilsKt.memberScopeAsImportingScope(libraryScope), root, false, null, Collections.emptyList(),
LexicalScopeKind.SYNTHETIC, LocalRedeclarationChecker.DO_NOTHING.INSTANCE, LexicalScopeKind.SYNTHETIC, LocalRedeclarationChecker.DO_NOTHING.INSTANCE,
handler -> { handler -> {
handler.addClassifierDescriptor((ClassifierDescriptor) classDescriptor); handler.addClassifierDescriptor((ClassifierDescriptor) classDescriptor);
@@ -551,7 +551,7 @@ public class KotlinTypeCheckerTest extends KotlinTestWithEnvironment {
); );
LexicalScope scope = new LexicalScopeImpl(scopeWithImports, scopeWithImports.getOwnerDescriptor(), false, LexicalScope scope = new LexicalScopeImpl(scopeWithImports, scopeWithImports.getOwnerDescriptor(), false,
Collections.singletonList(receiverParameterDescriptor), LexicalScopeKind.SYNTHETIC); receiverParameterDescriptor, Collections.emptyList(), LexicalScopeKind.SYNTHETIC);
assertType(scope, expression, expectedType); assertType(scope, expression, expectedType);
} }
@@ -91,7 +91,7 @@ public class TypeSubstitutorTest extends KotlinTestWithEnvironment {
LocalRedeclarationChecker redeclarationChecker = LocalRedeclarationChecker redeclarationChecker =
new ThrowingLocalRedeclarationChecker(new OverloadChecker(TypeSpecificityComparator.NONE.INSTANCE)); new ThrowingLocalRedeclarationChecker(new OverloadChecker(TypeSpecificityComparator.NONE.INSTANCE));
LexicalScope typeParameters = new LexicalScopeImpl( LexicalScope typeParameters = new LexicalScopeImpl(
topLevelScope, module, false, Collections.emptyList(), LexicalScopeKind.SYNTHETIC, topLevelScope, module, false, null, Collections.emptyList(), LexicalScopeKind.SYNTHETIC,
redeclarationChecker, redeclarationChecker,
handler -> { handler -> {
for (TypeParameterDescriptor parameterDescriptor : contextClass.getTypeConstructor().getParameters()) { for (TypeParameterDescriptor parameterDescriptor : contextClass.getTypeConstructor().getParameters()) {
@@ -101,7 +101,8 @@ public class TypeSubstitutorTest extends KotlinTestWithEnvironment {
} }
); );
return LexicalChainedScope.Companion.create( return LexicalChainedScope.Companion.create(
typeParameters, module, false, Collections.emptyList(), LexicalScopeKind.SYNTHETIC, typeParameters, module, false, null, Collections.emptyList(),
LexicalScopeKind.SYNTHETIC,
contextClass.getDefaultType().getMemberScope(), contextClass.getDefaultType().getMemberScope(),
module.getBuiltIns().getBuiltInsPackageScope() module.getBuiltIns().getBuiltInsPackageScope()
); );
@@ -198,7 +198,7 @@ public class TypeUnifierTest extends KotlinTestWithEnvironment {
private TypeProjection makeType(String typeStr) { private TypeProjection makeType(String typeStr) {
LexicalScope withX = new LexicalScopeImpl( LexicalScope withX = new LexicalScopeImpl(
builtinsImportingScope, module, builtinsImportingScope, module,
false, Collections.emptyList(), LexicalScopeKind.SYNTHETIC, LocalRedeclarationChecker.DO_NOTHING.INSTANCE, false, null, Collections.emptyList(), LexicalScopeKind.SYNTHETIC, LocalRedeclarationChecker.DO_NOTHING.INSTANCE,
handler -> { handler -> {
handler.addClassifierDescriptor(x); handler.addClassifierDescriptor(x);
handler.addClassifierDescriptor(y); handler.addClassifierDescriptor(y);
@@ -374,7 +374,8 @@ class LazyScriptDescriptor(
outerScope, outerScope,
receiverClassDescriptor, receiverClassDescriptor,
true, true,
listOf(receiverClassDescriptor.thisAsReceiverParameter), receiverClassDescriptor.thisAsReceiverParameter,
listOf(),
LexicalScopeKind.CLASS_MEMBER_SCOPE LexicalScopeKind.CLASS_MEMBER_SCOPE
).addImportingScope( ).addImportingScope(
AllUnderImportScope.create(receiverClassDescriptor, emptyList()) AllUnderImportScope.create(receiverClassDescriptor, emptyList())
@@ -41,7 +41,8 @@ class ReplImplicitsExtensionsResolutionFilter(
): Sequence<ScopeWithImplicitsExtensionsResolutionInfo> { ): Sequence<ScopeWithImplicitsExtensionsResolutionInfo> {
val processedReceivers = mutableSetOf<String>() val processedReceivers = mutableSetOf<String>()
return scopes.map { scope -> 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 { val keep = receivers?.all {
lock.read { lock.read {
when (val descriptorFqName = (it as? ImplicitClassReceiver)?.declarationDescriptor?.fqNameSafe?.asString()) { when (val descriptorFqName = (it as? ImplicitClassReceiver)?.declarationDescriptor?.fqNameSafe?.asString()) {