Skip to content

Commit f842202

Browse files
committed
[Sema] Eliminate a subscript AnyObject lookup ambiguity
Previously we would always consider an AnyObject subscript lookup to be ambiguous if there was a candidate in both a class and protocol, even if the selectors and types matched. This was due to the protocol's generic signature preventing the signatures from being coalesced. Tweak the logic to strip generic signatures when comparing for AnyObject lookup, matching what we do for @objc methods. Resolves SR-8611. Resolves rdar://43645564 & rdar://62906344.
1 parent 4908123 commit f842202

File tree

2 files changed

+29
-5
lines changed

2 files changed

+29
-5
lines changed

lib/Sema/ConstraintSystem.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,9 +216,19 @@ getDynamicResultSignature(ValueDecl *decl) {
216216
}
217217

218218
if (auto asd = dyn_cast<AbstractStorageDecl>(decl)) {
219+
auto ty = asd->getInterfaceType();
220+
221+
// Strip off a generic signature if we have one. This matches the logic
222+
// for methods, and ensures that we don't take a protocol's generic
223+
// signature into account for a subscript requirement.
224+
if (auto *genericFn = ty->getAs<GenericFunctionType>()) {
225+
ty = FunctionType::get(genericFn->getParams(), genericFn->getResult(),
226+
genericFn->getExtInfo());
227+
}
228+
219229
// Handle properties and subscripts, anchored by the getter's selector.
220230
return std::make_tuple(asd->isStatic(), asd->getObjCGetterSelector(),
221-
asd->getInterfaceType()->getCanonicalType());
231+
ty->getCanonicalType());
222232
}
223233

224234
llvm_unreachable("Not a valid @objc member");

test/Constraints/dynamic_lookup.swift

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,11 @@ func dynamicInitCrash(ao: AnyObject.Type) {
354354
func unambiguousMethodParam(_ x: Int)
355355

356356
subscript(ambiguousSubscript _: Int) -> String { get } // expected-note {{found this candidate}}
357-
subscript(unambiguousSubscript _: String) -> Int { get } // expected-note {{found this candidate}}
357+
subscript(unambiguousSubscript _: String) -> Int { get }
358+
359+
subscript(differentSelectors _: Int) -> Int { // expected-note {{found this candidate}}
360+
@objc(differentSelector1:) get
361+
}
358362
}
359363

360364
class C1 {
@@ -368,7 +372,11 @@ class C1 {
368372
@objc func unambiguousMethodParam(_ x: Int) {}
369373

370374
@objc subscript(ambiguousSubscript _: Int) -> Int { return 0 } // expected-note {{found this candidate}}
371-
@objc subscript(unambiguousSubscript _: String) -> Int { return 0 } // expected-note {{found this candidate}}
375+
@objc subscript(unambiguousSubscript _: String) -> Int { return 0 }
376+
377+
@objc subscript(differentSelectors _: Int) -> Int { // expected-note {{found this candidate}}
378+
@objc(differentSelector2:) get { return 0 }
379+
}
372380
}
373381

374382
class C2 {
@@ -392,9 +400,15 @@ func testAnyObjectAmbiguity(_ x: AnyObject) {
392400
_ = x[singleCandidate: 0]
393401

394402
_ = x[ambiguousSubscript: 0] // expected-error {{ambiguous use of 'subscript(ambiguousSubscript:)'}}
403+
_ = x[ambiguousSubscript: 0] as Int
404+
_ = x[ambiguousSubscript: 0] as String
405+
406+
// SR-8611: Make sure we can coalesce subscripts with the same types and
407+
// selectors through AnyObject lookup.
408+
_ = x[unambiguousSubscript: ""]
395409

396-
// FIX-ME(SR-8611): This is currently ambiguous but shouldn't be.
397-
_ = x[unambiguousSubscript: ""] // expected-error {{ambiguous use of 'subscript(unambiguousSubscript:)'}}
410+
// But not if they have different selectors.
411+
_ = x[differentSelectors: 0] // expected-error {{ambiguous use of 'subscript(differentSelectors:)}}
398412
}
399413

400414
// SR-11648

0 commit comments

Comments
 (0)