Skip to content

Commit 5f8e3eb

Browse files
committed
[CSSimplify] Detect and diagnose conformance failures related to AnyHashable conversion
Failure of an argument to AnyHashable parameter to conform to Hashable protocol should be detected in `simplifyConformsToConstraint` and fixed there. Doing so requires impact assessment adjustment because regular conformance requirements have default impact of 1, this is going to have argument impact of 2 not avoid clashing with other failures.
1 parent 143b016 commit 5f8e3eb

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2785,6 +2785,23 @@ assessRequirementFailureImpact(ConstraintSystem &cs, Type requirementType,
27852785
impact += choiceImpact - 1;
27862786
}
27872787
}
2788+
2789+
// If this requirement is associated with a call that is itself
2790+
// incorrect, let's increase impact to indicate that this failure
2791+
// has a compounding effect on viability of the overload choice it
2792+
// comes from.
2793+
if (locator.endsWith<LocatorPathElt::AnyRequirement>()) {
2794+
if (auto *expr = getAsExpr(anchor)) {
2795+
if (auto *call = getAsExpr<ApplyExpr>(cs.getParentExpr(expr))) {
2796+
if (call->getFn() == expr &&
2797+
llvm::any_of(cs.getFixes(), [&](const auto &fix) {
2798+
return getAsExpr(fix->getAnchor()) == call;
2799+
}))
2800+
impact += 2;
2801+
}
2802+
}
2803+
}
2804+
27882805
return impact;
27892806
}
27902807

@@ -8409,6 +8426,15 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
84098426
return SolutionKind::Solved;
84108427
}
84118428

8429+
// Conformance constraint that is introduced by an implicit conversion
8430+
// for example to `AnyHashable`.
8431+
if (kind == ConstraintKind::ConformsTo &&
8432+
loc->isLastElement<LocatorPathElt::ApplyArgToParam>()) {
8433+
auto *fix = AllowArgumentMismatch::create(*this, type, protocolTy, loc);
8434+
return recordFix(fix, /*impact=*/2) ? SolutionKind::Error
8435+
: SolutionKind::Solved;
8436+
}
8437+
84128438
// If this is an implicit Hashable conformance check generated for each
84138439
// index argument of the keypath subscript component, we could just treat
84148440
// it as though it conforms.

test/Constraints/diagnostics.swift

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -661,10 +661,7 @@ example21890157.property = "confusing" // expected-error {{value of optional ty
661661

662662

663663
struct UnaryOp {}
664-
665664
_ = -UnaryOp() // expected-error {{unary operator '-' cannot be applied to an operand of type 'UnaryOp'}}
666-
// expected-note@-1 {{overloads for '-' exist with these partially matching parameter lists: (Double), (Float)}}
667-
668665

669666
// <rdar://problem/23433271> Swift compiler segfault in failure diagnosis
670667
func f23433271(_ x : UnsafePointer<Int>) {}
@@ -1551,3 +1548,12 @@ func rdar86611718(list: [Int]) {
15511548
String(list.count())
15521549
// expected-error@-1 {{cannot call value of non-function type 'Int'}}
15531550
}
1551+
1552+
// rdar://108977234 - failed to produce diagnostic when argument to AnyHashable parameter doesn't conform to Hashable protocol
1553+
do {
1554+
struct NonHashable {}
1555+
1556+
func test(result: inout [AnyHashable], value: NonHashable) {
1557+
result.append(value) // expected-error {{argument type 'NonHashable' does not conform to expected type 'Hashable'}}
1558+
}
1559+
}

0 commit comments

Comments
 (0)