Skip to content

Commit 2c0b8ca

Browse files
committed
[Diagnostics] Add a tailored diagnostic for function mismatch in argument positions
If parameter has a function type and no argument overload choices match let's diagnose that specifically. Resolves: [SR-12689](https://bugs.swift.org/browse/SR-12689) Resolves: rdar://problem/62481592
1 parent f854cc6 commit 2c0b8ca

File tree

4 files changed

+91
-0
lines changed

4 files changed

+91
-0
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,10 @@ ERROR(no_candidates_match_result_type,none,
253253
"no '%0' candidates produce the expected contextual result type %1",
254254
(StringRef, Type))
255255

256+
ERROR(no_candidates_match_argument_type,none,
257+
"no '%0' candidates produce the expected type %1 for parameter #%2",
258+
(StringRef, Type, unsigned))
259+
256260
ERROR(cannot_infer_closure_parameter_type,none,
257261
"unable to infer type of a closure parameter %0 in the current context",
258262
(StringRef))

lib/Sema/CSFix.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,57 @@ bool AllowFunctionTypeMismatch::diagnose(const Solution &solution,
408408
return coalesceAndDiagnose(solution, {}, asNote);
409409
}
410410

411+
bool AllowFunctionTypeMismatch::diagnoseForAmbiguity(
412+
CommonFixesArray commonFixes) const {
413+
if (ContextualMismatch::diagnoseForAmbiguity(commonFixes))
414+
return true;
415+
416+
auto *locator = getLocator();
417+
// If this is a mismatch between two function types at argument
418+
// position, there is a tailored diagnostic for that.
419+
if (auto argConv =
420+
locator->getLastElementAs<LocatorPathElt::ApplyArgToParam>()) {
421+
auto &cs = getConstraintSystem();
422+
auto &DE = cs.getASTContext().Diags;
423+
auto &solution = *commonFixes[0].first;
424+
425+
auto info = getStructuralTypeContext(solution, locator);
426+
if (!info)
427+
return false;
428+
429+
auto *argLoc = cs.getConstraintLocator(simplifyLocatorToAnchor(locator));
430+
431+
auto overload = solution.getOverloadChoiceIfAvailable(
432+
solution.getCalleeLocator(argLoc));
433+
if (!overload)
434+
return false;
435+
436+
auto name = overload->choice.getName().getBaseName();
437+
DE.diagnose(getLoc(getAnchor()), diag::no_candidates_match_argument_type,
438+
name.userFacingName(), std::get<2>(*info),
439+
argConv->getParamIdx());
440+
441+
for (auto &entry : commonFixes) {
442+
auto &solution = *entry.first;
443+
auto overload = solution.getOverloadChoiceIfAvailable(
444+
solution.getCalleeLocator(argLoc));
445+
446+
if (!(overload && overload->choice.isDecl()))
447+
continue;
448+
449+
auto *decl = overload->choice.getDecl();
450+
if (decl->getLoc().isValid()) {
451+
DE.diagnose(decl, diag::found_candidate_type,
452+
solution.simplifyType(overload->openedType));
453+
}
454+
}
455+
456+
return true;
457+
}
458+
459+
return false;
460+
}
461+
411462
AllowFunctionTypeMismatch *
412463
AllowFunctionTypeMismatch::create(ConstraintSystem &cs, Type lhs, Type rhs,
413464
ConstraintLocator *locator, unsigned index) {

lib/Sema/CSFix.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,6 +1117,8 @@ class AllowFunctionTypeMismatch final : public ContextualMismatch {
11171117
bool asNote = false) const override;
11181118

11191119
bool diagnose(const Solution &solution, bool asNote = false) const override;
1120+
1121+
bool diagnoseForAmbiguity(CommonFixesArray commonFixes) const override;
11201122
};
11211123

11221124

test/Sema/diag_ambiguous_overloads.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,37 @@ func getCounts(_ scheduler: sr5154_Scheduler, _ handler: @escaping ([Count]) ->
126126
})
127127
}
128128

129+
// SR-12689
130+
func SR12689(_ u: UnsafeBufferPointer<UInt16>) {}
131+
132+
let array : [UInt16] = [1, 2]
133+
134+
array.withUnsafeBufferPointer {
135+
SR12689(UnsafeRawPointer($0).bindMemory(to: UInt16.self, capacity: 1)) // expected-error {{cannot convert value of type 'UnsafePointer<UInt16>' to expected argument type 'UnsafeBufferPointer<UInt16>'}}
136+
// expected-error@-1 {{no exact matches in call to initializer}}
137+
// expected-note@-2 {{candidate expects value of type 'UnsafeRawPointer' for parameter #1}}
138+
// expected-note@-3 {{candidate expects value of type 'UnsafeMutableRawPointer' for parameter #1}}
139+
// expected-note@-4 {{candidate expects value of type 'OpaquePointer' for parameter #1}}
140+
// expected-note@-5 {{candidate expects value of type 'Builtin.RawPointer' for parameter #1}}
141+
142+
UnsafeRawPointer($0) as UnsafeBufferPointer<UInt16> // expected-error {{cannot convert value of type 'UnsafeRawPointer' to type 'UnsafeBufferPointer<UInt16>' in coercion}}
143+
// expected-error@-1 {{no exact matches in call to initializer}}
144+
// expected-note@-2 {{found candidate with type '(UnsafeRawPointer) -> UnsafeRawPointer'}}
145+
// expected-note@-3 {{found candidate with type '(Builtin.RawPointer) -> UnsafeRawPointer'}}
146+
// expected-note@-4 {{found candidate with type '(OpaquePointer) -> UnsafeRawPointer'}}
147+
// expected-note@-5 {{found candidate with type '(UnsafeMutableRawPointer) -> UnsafeRawPointer'}}
148+
}
149+
150+
func SR12689_1(_ u: Int) -> String { "" } // expected-note {{found this candidate}} expected-note {{candidate expects value of type 'Int' for parameter #1}}
151+
func SR12689_1(_ u: String) -> Double { 0 } // expected-note {{found this candidate}} expected-note {{candidate expects value of type 'String' for parameter #1}}
152+
func SR12689_2(_ u: Int) {}
153+
154+
SR12689_2(SR12689_1(1 as Double)) // expected-error {{no exact matches in call to global function 'SR12689_1'}}
155+
SR12689_1(1 as Double) as Int // expected-error {{no exact matches in call to global function 'SR12689_1'}}
156+
157+
// Ambiguos OverloadRefExpr
158+
func SR12689_O(_ p: Int) {} // expected-note {{found candidate with type '(Int) -> ()'}}
159+
func SR12689_O(_ p: Double) {} // expected-note {{found candidate with type '(Double) -> ()'}}
160+
func SR12689_3(_ param: (String)-> Void) {}
161+
162+
SR12689_3(SR12689_O) // expected-error {{no 'SR12689_O' candidates produce the expected type '(String) -> Void' for parameter #0}}

0 commit comments

Comments
 (0)