Skip to content

Commit 29cb7dd

Browse files
committed
[Diagnostics] Handle ambiguities related to use of nil literal
When `nil` is passed as an argument to call with multiple overloads it's possible that this would result in ambiguity where matched expected argument type doesn't conform to `ExpressibleByNilLiteral`. To handle situations like this locator for contextual mismatch has to be adjusted to point to the call where `nil` is used, so `diagnoseAmbiguityWithFixes` can identify multiple overloads and produce a correct ambiguity diagnostic. Resolves: rdar://75514153
1 parent af3dcf0 commit 29cb7dd

File tree

3 files changed

+41
-2
lines changed

3 files changed

+41
-2
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6151,6 +6151,26 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
61516151
getContextualTypePurpose(Nil)))
61526152
: locator);
61536153

6154+
// Only requirement placed directly on `nil` literal is
6155+
// `ExpressibleByNilLiteral`, so if `nil` is an argument
6156+
// to an application, let's update locator accordingly to
6157+
// diagnose possible ambiguities with multiple mismatched
6158+
// overload choices.
6159+
if (fixLocator->directlyAt<NilLiteralExpr>()) {
6160+
if (auto argInfo =
6161+
isArgumentExpr(castToExpr(fixLocator->getAnchor()))) {
6162+
Expr *application;
6163+
unsigned argIdx;
6164+
6165+
std::tie(application, argIdx) = *argInfo;
6166+
6167+
fixLocator = getConstraintLocator(
6168+
application,
6169+
{LocatorPathElt::ApplyArgument(),
6170+
LocatorPathElt::ApplyArgToParam(argIdx, argIdx, /*flags=*/{})});
6171+
}
6172+
}
6173+
61546174
// Here the roles are reversed - `nil` is something we are trying to
61556175
// convert to `type` by making sure that it conforms to a specific
61566176
// protocol.

test/ClangImporter/objc_parse.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,12 @@ func keyedSubscripting(_ b: B, idx: A, a: A) {
184184
dict[NSString()] = a
185185
let value = dict[NSString()]
186186

187-
dict[nil] = a // expected-error {{'nil' is not compatible with expected argument type 'NSCopying'}}
188-
let q = dict[nil] // expected-error {{'nil' is not compatible with expected argument type 'NSCopying'}}
187+
// notes attached to the partially matching declarations for both following subscripts:
188+
// - override subscript(_: Any) -> Any? -> 'nil' is not compatible with expected argument type 'Any' at position #1
189+
// - open subscript(key: NSCopying) -> Any? { get set } -> 'nil' is not compatible with expected argument type 'NSCopying' at position #1
190+
191+
dict[nil] = a // expected-error {{no exact matches in call to subscript}}
192+
let q = dict[nil] // expected-error {{no exact matches in call to subscript}}
189193
_ = q
190194
}
191195

test/Constraints/optional.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,3 +484,18 @@ func rdar75146811() {
484484
// expected-error@-1 {{cannot convert value of type '[Double]?' to expected argument type 'Double'}}
485485
test_named(x: &(arr)) // expected-error {{cannot convert value of type '[Double]?' to expected argument type 'Double'}}
486486
}
487+
488+
// rdar://75514153 - Unable to produce a diagnostic for ambiguities related to use of `nil`
489+
func rdar75514153() {
490+
func test_no_label(_: Int) {} // expected-note 2 {{'nil' is not compatible with expected argument type 'Int' at position #1}}
491+
func test_no_label(_: String) {} // expected-note 2 {{'nil' is not compatible with expected argument type 'String' at position #1}}
492+
493+
test_no_label(nil) // expected-error {{no exact matches in call to local function 'test_no_label'}}
494+
test_no_label((nil)) // expected-error {{no exact matches in call to local function 'test_no_label'}}
495+
496+
func test_labeled(_: Int, x: Int) {} // expected-note 2 {{'nil' is not compatible with expected argument type 'Int' at position #2}}
497+
func test_labeled(_: Int, x: String) {} // expected-note 2 {{'nil' is not compatible with expected argument type 'String' at position #2}}
498+
499+
test_labeled(42, x: nil) // expected-error {{no exact matches in call to local function 'test_labeled'}}
500+
test_labeled(42, x: (nil)) // expected-error {{no exact matches in call to local function 'test_labeled'}}
501+
}

0 commit comments

Comments
 (0)