[FE] Report ambiguity in all possible cases

This commit is contained in:
Anastasiya Shadrina
2021-06-20 06:27:14 +07:00
committed by TeamCityServer
parent 37495bcba0
commit 814777ba8c
18 changed files with 111 additions and 104 deletions
@@ -10579,14 +10579,9 @@ 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("ambiguityInGroup.kt")
public void testAmbiguityInGroup() throws Exception {
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/ambiguityInGroup.kt");
}
@TestMetadata("dp.kt")
@@ -10577,15 +10577,9 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
}
@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");
@TestMetadata("ambiguityInGroup.kt")
public void testAmbiguityInGroup() throws Exception {
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/ambiguityInGroup.kt");
}
@Test
@@ -10577,15 +10577,9 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
}
@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");
@TestMetadata("ambiguityInGroup.kt")
public void testAmbiguityInGroup() throws Exception {
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/ambiguityInGroup.kt");
}
@Test
@@ -1199,6 +1199,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);
DiagnosticFactory0<KtElement> AMBIBIGUOS_CALL_WITH_IMPLICIT_CONTEXT_RECEIVER = DiagnosticFactory0.create(ERROR);
// Error sets
ImmutableSet<? extends DiagnosticFactory<?>> UNRESOLVED_REFERENCE_DIAGNOSTICS = ImmutableSet.of(
@@ -1090,6 +1090,7 @@ public class DefaultErrorMessages {
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.put(AMBIBIGUOS_CALL_WITH_IMPLICIT_CONTEXT_RECEIVER, "With implicit context receiver, call is ambiguous. Specify the receiver explicitly");
MAP.setImmutable();
@@ -111,6 +111,10 @@ class DiagnosticReporterByTrackingStrategy(
)
)
}
ContextReceiverAmbiguity::class.java -> {
val callElement = psiKotlinCall.psiCall.callElement
trace.report(AMBIBIGUOS_CALL_WITH_IMPLICIT_CONTEXT_RECEIVER.on(callElement))
}
}
}
@@ -112,6 +112,12 @@ abstract class ResolutionDiagnostic(candidateApplicability: CandidateApplicabili
}
}
class ContextReceiverAmbiguity : ResolutionDiagnostic(RESOLVED_WITH_ERROR) {
override fun report(reporter: DiagnosticReporter) {
reporter.onCall(this)
}
}
// todo error for this access from nested class
class VisibilityError(val invisibleMember: DeclarationDescriptorWithVisibility) : ResolutionDiagnostic(RUNTIME_ERROR) {
override fun report(reporter: DiagnosticReporter) {
@@ -153,6 +153,31 @@ private class NoExplicitReceiverScopeTowerProcessor<C : Candidate>(
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
data.implicitReceiver
)
is TowerData.BothTowerLevelAndContextReceiversGroup -> {
val collected = mutableListOf<CandidateWithBoundDispatchReceiver>()
val receiversWithCandidates = mutableMapOf<ReceiverValueWithSmartCastInfo, List<CandidateWithBoundDispatchReceiver>>()
for (contextReceiver in data.contextReceiversGroup) {
val collectedFromReceiver = data.level.collectCandidates(contextReceiver).toMutableList()
collectedFromReceiver.removeIf { collectedCandidate ->
val duplicate = collected.find { it.descriptor == collectedCandidate.descriptor }
if (duplicate != null) {
duplicate.diagnostics.add(ContextReceiverAmbiguity())
true
} else {
false
}
}
collected.addAll(collectedFromReceiver)
receiversWithCandidates[contextReceiver] = collectedFromReceiver
}
receiversWithCandidates.flatMap {
createCandidates(
it.value,
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
it.key
)
}
}
else -> emptyList()
}
@@ -67,6 +67,10 @@ sealed class TowerData {
class OnlyImplicitReceiver(val implicitReceiver: ReceiverValueWithSmartCastInfo) : TowerData()
class TowerLevel(val level: ScopeTowerLevel) : TowerData()
class BothTowerLevelAndImplicitReceiver(val level: ScopeTowerLevel, val implicitReceiver: ReceiverValueWithSmartCastInfo) : TowerData()
class BothTowerLevelAndContextReceiversGroup(
val level: ScopeTowerLevel,
val contextReceiversGroup: List<ReceiverValueWithSmartCastInfo>
) : TowerData()
// Has the same meaning as BothTowerLevelAndImplicitReceiver, but it's only used for names lookup, so it doesn't need implicit receiver
class ForLookupForNoExplicitReceiver(val level: ScopeTowerLevel) : TowerData()
}
@@ -222,9 +226,16 @@ class TowerResolver {
}
is ScopeResolutionStep.ContextReceiversGroupsResolution -> if (scope is LexicalScope) {
val contextReceiversGroup = implicitScopeTower.getContextReceivers(scope)
if (contextReceiversGroup.isNotEmpty()) {
TowerData.TowerLevel(ContextReceiversGroupScopeTowerLevel(implicitScopeTower, contextReceiversGroup))
.process()?.let { return it }
TowerData.BothTowerLevelAndContextReceiversGroup(syntheticLevel, contextReceiversGroup).process()
?.let { return it }
for (nonLocalLevel in nonLocalLevels) {
TowerData.BothTowerLevelAndContextReceiversGroup(nonLocalLevel, contextReceiversGroup).process()
?.let { return it }
}
}
}
is ScopeResolutionStep.ImportingScopesResolution -> if (scope is ImportingScope) {
@@ -0,0 +1,22 @@
interface Common {
fun supertypeMember() {}
}
interface C1 : Common {
fun member() {}
}
interface C2 : Common {
fun member() {}
}
fun Common.supertypeExtension() {}
context(Common)
fun supertypeContextual() {}
context(C1, C2)
fun test() {
supertypeMember()
member()
supertypeExtension()
supertypeContextual()
}
@@ -0,0 +1,22 @@
interface Common {
fun supertypeMember() {}
}
interface C1 : Common {
fun member() {}
}
interface C2 : Common {
fun member() {}
}
fun Common.supertypeExtension() {}
context(Common)
fun supertypeContextual() {}
context(C1, C2)
fun test() {
<!OVERLOAD_RESOLUTION_AMBIGUITY!>supertypeMember<!>()
<!OVERLOAD_RESOLUTION_AMBIGUITY!>member<!>()
<!AMBIBIGUOS_CALL_WITH_IMPLICIT_CONTEXT_RECEIVER!>supertypeExtension()<!>
<!MULTIPLE_ARGUMENTS_APPLICABLE_FOR_CONTEXT_RECEIVER!>supertypeContextual()<!>
}
@@ -1,23 +1,28 @@
package
public fun foo(): kotlin.Unit
public fun supertypeContextual(): kotlin.Unit
public fun test(): kotlin.Unit
public fun Common.bar(): kotlin.Unit
public fun Common.supertypeExtension(): 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 fun member(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun supertypeMember(): kotlin.Unit
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 fun member(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun supertypeMember(): kotlin.Unit
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 fun supertypeMember(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -1,11 +0,0 @@
interface C1 {
fun foo() {}
}
interface C2 {
fun foo() {}
}
context(C1, C2)
fun bar() {
foo()
}
@@ -1,11 +0,0 @@
interface C1 {
fun foo() {}
}
interface C2 {
fun foo() {}
}
context(C1, C2)
fun bar() {
<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>()
}
@@ -1,17 +0,0 @@
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
}
@@ -1,14 +0,0 @@
interface Common
interface C1 : Common
interface C2 : Common
context(Common)
fun foo() {}
fun Common.bar() {}
context(C1, C2)
fun test() {
foo()
bar()
}
@@ -1,14 +0,0 @@
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()
}
@@ -10583,15 +10583,9 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
}
@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");
@TestMetadata("ambiguityInGroup.kt")
public void testAmbiguityInGroup() throws Exception {
runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/ambiguityInGroup.kt");
}
@Test