Skip to content

Commit bb41492

Browse files
committed
[ConstraintSystem] Properly diagnose operator reference ambiguities
If operator is referenced instead of applied e.g. `arr.sort(by: <)` ambiguities should be diagnosed as `no exact matches` with attached notes describing a failure associated with each potential candidate. Resolves: rdar://problem/62054241
1 parent d8bd62d commit bb41492

File tree

2 files changed

+29
-7
lines changed

2 files changed

+29
-7
lines changed

lib/Sema/ConstraintSystem.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2641,10 +2641,7 @@ static void diagnoseOperatorAmbiguity(ConstraintSystem &cs,
26412641
ConstraintLocator *locator) {
26422642
auto &DE = cs.getASTContext().Diags;
26432643
auto *anchor = castToExpr(locator->getAnchor());
2644-
2645-
auto *applyExpr = dyn_cast_or_null<ApplyExpr>(cs.getParentExpr(anchor));
2646-
if (!applyExpr)
2647-
return;
2644+
auto *applyExpr = cast<ApplyExpr>(cs.getParentExpr(anchor));
26482645

26492646
auto isNameOfStandardComparisonOperator = [](Identifier opName) -> bool {
26502647
return opName.is("==") || opName.is("!=") || opName.is("===") ||
@@ -3028,9 +3025,23 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes(
30283025
DE.diagnose(getLoc(commonAnchor), diag::no_candidates_match_result_type,
30293026
baseName.userFacingName(), getContextualType(anchor));
30303027
} else if (name.isOperator()) {
3031-
diagnoseOperatorAmbiguity(*this, name.getBaseIdentifier(), solutions,
3032-
commonCalleeLocator);
3033-
return true;
3028+
auto *anchor = castToExpr(commonCalleeLocator->getAnchor());
3029+
3030+
// If operator is "applied" e.g. `1 + 2` there are tailored
3031+
// diagnostics in case of ambiguity, but if it's referenced
3032+
// e.g. `arr.sort(by: <)` it's better to produce generic error
3033+
// and a note per candidate.
3034+
if (auto *parentExpr = getParentExpr(anchor)) {
3035+
if (isa<ApplyExpr>(parentExpr)) {
3036+
diagnoseOperatorAmbiguity(*this, name.getBaseIdentifier(), solutions,
3037+
commonCalleeLocator);
3038+
return true;
3039+
}
3040+
}
3041+
3042+
DE.diagnose(anchor->getLoc(), diag::no_overloads_match_exactly_in_call,
3043+
/*isApplication=*/false, decl->getDescriptiveKind(),
3044+
name.isSpecial(), name.getBaseName());
30343045
} else {
30353046
bool isApplication =
30363047
llvm::any_of(ArgumentInfos, [&](const auto &argInfo) {

test/Constraints/operator.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,3 +279,14 @@ func sr12438(_ e: Error) {
279279
func foo<T>(_ a: T, _ op: ((T, T) -> Bool)) {}
280280
foo(e, ==) // expected-error {{type of expression is ambiguous without more context}}
281281
}
282+
283+
// rdar://problem/62054241 - Swift compiler crashes when passing < as the sort function in sorted(by:) and the type of the array is not comparable
284+
func rdar_62054241() {
285+
struct Foo {
286+
let a: Int
287+
}
288+
289+
func test(_ arr: [Foo]) -> [Foo] {
290+
return arr.sorted(by: <) // expected-error {{no exact matches in reference to operator function '<'}}
291+
}
292+
}

0 commit comments

Comments
 (0)