Skip to content

Commit 399d349

Browse files
committed
[ConstraintSystem] Add a tailored ambiguity diagnostic for non-conforming result type
1 parent b07c887 commit 399d349

File tree

3 files changed

+45
-4
lines changed

3 files changed

+45
-4
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,10 @@ ERROR(no_candidates_match_result_type,none,
267267
"no '%0' candidates produce the expected contextual result type %1",
268268
(StringRef, Type))
269269

270+
ERROR(no_overloads_have_result_type_conformance,none,
271+
"no '%0' overloads produce result type that conforms to %1",
272+
(StringRef, Type))
273+
270274
ERROR(no_candidates_match_argument_type,none,
271275
"no '%0' candidates produce the expected type %1 for parameter #%2",
272276
(StringRef, Type, unsigned))
@@ -559,6 +563,10 @@ NOTE(cannot_convert_candidate_result_to_contextual_type,none,
559563
"%0 produces %1, not the expected contextual result type %2",
560564
(DeclName, Type, Type))
561565

566+
NOTE(overload_result_type_does_not_conform,none,
567+
"result type %1 of %0 does not conform to %2",
568+
(DeclName, Type, Type))
569+
562570
// for ... in expression
563571
ERROR(cannot_convert_sequence_element_value,none,
564572
"cannot convert sequence element type %0 to expected type %1",

lib/Sema/ConstraintSystem.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4261,7 +4261,10 @@ static bool diagnoseAmbiguityWithContextualType(
42614261

42624262
assert(contextualTy);
42634263

4264-
DE.diagnose(getLoc(anchor), diag::no_candidates_match_result_type,
4264+
DE.diagnose(getLoc(anchor),
4265+
contextualTy->is<ProtocolType>()
4266+
? diag::no_overloads_have_result_type_conformance
4267+
: diag::no_candidates_match_result_type,
42654268
name.getBaseName().userFacingName(), contextualTy);
42664269

42674270
for (const auto &solution : solutions) {
@@ -4275,9 +4278,12 @@ static bool diagnoseAmbiguityWithContextualType(
42754278

42764279
if (isExpr<ApplyExpr>(anchor) || isExpr<SubscriptExpr>(anchor)) {
42774280
auto fnType = type->castTo<FunctionType>();
4278-
DE.diagnose(loc,
4279-
diag::cannot_convert_candidate_result_to_contextual_type,
4280-
decl->getName(), fnType->getResult(), contextualTy);
4281+
DE.diagnose(
4282+
loc,
4283+
contextualTy->is<ProtocolType>()
4284+
? diag::overload_result_type_does_not_conform
4285+
: diag::cannot_convert_candidate_result_to_contextual_type,
4286+
decl->getName(), fnType->getResult(), contextualTy);
42814287
} else {
42824288
DE.diagnose(loc, diag::found_candidate_type, type);
42834289
}

test/Constraints/overload.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,3 +264,30 @@ for (key, values) in oldName { // expected-error{{cannot find 'oldName' in scope
264264
print(key, idx, value)
265265
}
266266
}
267+
268+
// rdar://97396399 - crash in swift::DiagnosticEngine::formatDiagnosticText
269+
func rdar97396399() {
270+
// Has to be overloaded to make sure that contextual type is not recorded during constraint generation
271+
func test(_: () -> Void) {}
272+
func test(_: (Int) -> Void) {}
273+
274+
// Multiple different overloads, none of which conform to Sequence
275+
func fn(_: Int) -> Int {}
276+
// expected-note@-1 {{found candidate with type '(Int) -> Int'}}
277+
// expected-note@-2 {{result type 'Int' of 'fn' does not conform to 'Sequence'}}
278+
func fn(_: Int) -> Double {}
279+
// expected-note@-1 {{found candidate with type '(Int) -> Double'}}
280+
// expected-note@-2 {{result type 'Double' of 'fn' does not conform to 'Sequence'}}
281+
282+
test {
283+
for x in fn { // expected-error {{no 'fn' overloads produce result type that conforms to 'Sequence'}}
284+
print(x)
285+
}
286+
}
287+
288+
test {
289+
for x in fn(42) { // expected-error {{no 'fn' overloads produce result type that conforms to 'Sequence'}}
290+
print(x)
291+
}
292+
}
293+
}

0 commit comments

Comments
 (0)