Skip to content

Commit 0457a72

Browse files
authored
Merge pull request #60222 from xedin/rdar-97396399
[ConstraintSystem] Retrieve contextual type from a solution for ambiguities
2 parents 5a5c904 + c300edb commit 0457a72

File tree

4 files changed

+59
-11
lines changed

4 files changed

+59
-11
lines changed

include/swift/AST/DiagnosticsSema.def

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

266+
ERROR(no_overloads_have_result_type_conformance,none,
267+
"no '%0' overloads produce result type that conforms to %1",
268+
(StringRef, Type))
269+
266270
ERROR(no_candidates_match_argument_type,none,
267271
"no '%0' candidates produce the expected type %1 for parameter #%2",
268272
(StringRef, Type, unsigned))
@@ -555,6 +559,10 @@ NOTE(cannot_convert_candidate_result_to_contextual_type,none,
555559
"%0 produces %1, not the expected contextual result type %2",
556560
(DeclName, Type, Type))
557561

562+
NOTE(overload_result_type_does_not_conform,none,
563+
"result type %1 of %0 does not conform to %2",
564+
(DeclName, Type, Type))
565+
558566
// for ... in expression
559567
ERROR(cannot_convert_sequence_element_value,none,
560568
"cannot convert sequence element type %0 to expected type %1",

include/swift/Sema/ConstraintSystem.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,6 +1489,15 @@ class Solution {
14891489
/// types where possible.
14901490
Type resolveInterfaceType(Type type) const;
14911491

1492+
Type getContextualType(ASTNode anchor) const {
1493+
for (const auto &entry : contextualTypes) {
1494+
if (entry.first == anchor) {
1495+
return simplifyType(entry.second.getType());
1496+
}
1497+
}
1498+
return Type();
1499+
}
1500+
14921501
/// For a given locator describing a function argument conversion, or a
14931502
/// constraint within an argument conversion, returns information about the
14941503
/// application of the argument to its parameter. If the locator is not

lib/Sema/ConstraintSystem.cpp

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4245,27 +4245,31 @@ static bool diagnoseAmbiguityWithContextualType(
42454245

42464246
auto anchor = locator->getAnchor();
42474247
auto name = result->choices.front().getName();
4248-
DE.diagnose(getLoc(anchor), diag::no_candidates_match_result_type,
4249-
name.getBaseName().userFacingName(),
4250-
cs.getContextualType(anchor, /*forConstraint=*/false));
4248+
auto contextualTy = solution.getContextualType(anchor);
4249+
4250+
assert(contextualTy);
4251+
4252+
DE.diagnose(getLoc(anchor),
4253+
contextualTy->is<ProtocolType>()
4254+
? diag::no_overloads_have_result_type_conformance
4255+
: diag::no_candidates_match_result_type,
4256+
name.getBaseName().userFacingName(), contextualTy);
42514257

42524258
for (const auto &solution : solutions) {
42534259
auto overload = solution.getOverloadChoice(calleeLocator);
42544260
if (auto *decl = overload.choice.getDeclOrNull()) {
4255-
auto loc = decl->getLoc();
4256-
if (loc.isInvalid())
4257-
continue;
4258-
42594261
auto type = solution.simplifyType(overload.boundType);
42604262

42614263
if (isExpr<ApplyExpr>(anchor) || isExpr<SubscriptExpr>(anchor)) {
42624264
auto fnType = type->castTo<FunctionType>();
42634265
DE.diagnose(
4264-
loc, diag::cannot_convert_candidate_result_to_contextual_type,
4265-
decl->getName(), fnType->getResult(),
4266-
cs.getContextualType(anchor, /*forConstraint=*/false));
4266+
decl,
4267+
contextualTy->is<ProtocolType>()
4268+
? diag::overload_result_type_does_not_conform
4269+
: diag::cannot_convert_candidate_result_to_contextual_type,
4270+
decl->getName(), fnType->getResult(), contextualTy);
42674271
} else {
4268-
DE.diagnose(loc, diag::found_candidate_type, type);
4272+
DE.diagnose(decl, diag::found_candidate_type, type);
42694273
}
42704274
}
42714275
}

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)