[FE] Report ambiguity in all possible cases
This commit is contained in:
committed by
TeamCityServer
parent
37495bcba0
commit
814777ba8c
+3
-8
@@ -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")
|
||||
|
||||
+3
-9
@@ -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
|
||||
|
||||
+3
-9
@@ -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(
|
||||
|
||||
+1
@@ -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();
|
||||
|
||||
|
||||
+4
@@ -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) {
|
||||
|
||||
+25
@@ -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) {
|
||||
|
||||
+22
@@ -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()
|
||||
}
|
||||
+22
@@ -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()<!>
|
||||
}
|
||||
+7
-2
@@ -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
|
||||
}
|
||||
Vendored
-11
@@ -1,11 +0,0 @@
|
||||
interface C1 {
|
||||
fun foo() {}
|
||||
}
|
||||
interface C2 {
|
||||
fun foo() {}
|
||||
}
|
||||
|
||||
context(C1, C2)
|
||||
fun bar() {
|
||||
foo()
|
||||
}
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
interface C1 {
|
||||
fun foo() {}
|
||||
}
|
||||
interface C2 {
|
||||
fun foo() {}
|
||||
}
|
||||
|
||||
context(C1, C2)
|
||||
fun bar() {
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>()
|
||||
}
|
||||
-17
@@ -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
|
||||
}
|
||||
-14
@@ -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()
|
||||
}
|
||||
Vendored
-14
@@ -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()
|
||||
}
|
||||
Generated
+3
-9
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user