Skip to content

Commit dbe6ba1

Browse files
committed
[ConstraintSystem] Retrieve contextual type from a solution for ambiguities
In ambiguity scenarios solutions are not applied back to the constraint system, so it might not always have contextual type information when it was recorded e.g. for a multi-statement closure. Resolves: rdar://97396399 (cherry picked from commit b07c887) (cherry picked from commit 399d349) (cherry picked from commit c300edb)
1 parent 390fda6 commit dbe6ba1

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
@@ -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",

include/swift/Sema/ConstraintSystem.h

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

1425+
Type getContextualType(ASTNode anchor) const {
1426+
for (const auto &entry : contextualTypes) {
1427+
if (entry.first == anchor) {
1428+
return simplifyType(entry.second.getType());
1429+
}
1430+
}
1431+
return Type();
1432+
}
1433+
14251434
/// For a given locator describing a function argument conversion, or a
14261435
/// constraint within an argument conversion, returns information about the
14271436
/// 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
@@ -4219,27 +4219,31 @@ static bool diagnoseAmbiguityWithContextualType(
42194219

42204220
auto anchor = locator->getAnchor();
42214221
auto name = result->choices.front().getName();
4222-
DE.diagnose(getLoc(anchor), diag::no_candidates_match_result_type,
4223-
name.getBaseName().userFacingName(),
4224-
cs.getContextualType(anchor, /*forConstraint=*/false));
4222+
auto contextualTy = solution.getContextualType(anchor);
4223+
4224+
assert(contextualTy);
4225+
4226+
DE.diagnose(getLoc(anchor),
4227+
contextualTy->is<ProtocolType>()
4228+
? diag::no_overloads_have_result_type_conformance
4229+
: diag::no_candidates_match_result_type,
4230+
name.getBaseName().userFacingName(), contextualTy);
42254231

42264232
for (const auto &solution : solutions) {
42274233
auto overload = solution.getOverloadChoice(calleeLocator);
42284234
if (auto *decl = overload.choice.getDeclOrNull()) {
4229-
auto loc = decl->getLoc();
4230-
if (loc.isInvalid())
4231-
continue;
4232-
42334235
auto type = solution.simplifyType(overload.boundType);
42344236

42354237
if (isExpr<ApplyExpr>(anchor) || isExpr<SubscriptExpr>(anchor)) {
42364238
auto fnType = type->castTo<FunctionType>();
42374239
DE.diagnose(
4238-
loc, diag::cannot_convert_candidate_result_to_contextual_type,
4239-
decl->getName(), fnType->getResult(),
4240-
cs.getContextualType(anchor, /*forConstraint=*/false));
4240+
decl,
4241+
contextualTy->is<ProtocolType>()
4242+
? diag::overload_result_type_does_not_conform
4243+
: diag::cannot_convert_candidate_result_to_contextual_type,
4244+
decl->getName(), fnType->getResult(), contextualTy);
42414245
} else {
4242-
DE.diagnose(loc, diag::found_candidate_type, type);
4246+
DE.diagnose(decl, diag::found_candidate_type, type);
42434247
}
42444248
}
42454249
}

test/Constraints/overload.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,3 +257,30 @@ func rdar79672230() {
257257
var t: MyType = MyType()
258258
test(&t) // expected-error {{no exact matches in call to local function 'test'}}
259259
}
260+
261+
// rdar://97396399 - crash in swift::DiagnosticEngine::formatDiagnosticText
262+
func rdar97396399() {
263+
// Has to be overloaded to make sure that contextual type is not recorded during constraint generation
264+
func test(_: () -> Void) {}
265+
func test(_: (Int) -> Void) {}
266+
267+
// Multiple different overloads, none of which conform to Sequence
268+
func fn(_: Int) -> Int {}
269+
// expected-note@-1 {{found candidate with type '(Int) -> Int'}}
270+
// expected-note@-2 {{result type 'Int' of 'fn' does not conform to 'Sequence'}}
271+
func fn(_: Int) -> Double {}
272+
// expected-note@-1 {{found candidate with type '(Int) -> Double'}}
273+
// expected-note@-2 {{result type 'Double' of 'fn' does not conform to 'Sequence'}}
274+
275+
test {
276+
for x in fn { // expected-error {{no 'fn' overloads produce result type that conforms to 'Sequence'}}
277+
print(x)
278+
}
279+
}
280+
281+
test {
282+
for x in fn(42) { // expected-error {{no 'fn' overloads produce result type that conforms to 'Sequence'}}
283+
print(x)
284+
}
285+
}
286+
}

0 commit comments

Comments
 (0)