[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.
This commit is contained in:
Pavel Yaskevich
2023-05-08 16:16:30 -07:00
parent 143b0160d2
commit 5f8e3eb6f6
2 changed files with 35 additions and 3 deletions

View File

@@ -2785,6 +2785,23 @@ assessRequirementFailureImpact(ConstraintSystem &cs, Type requirementType,
impact += choiceImpact - 1;
}
}
// If this requirement is associated with a call that is itself
// incorrect, let's increase impact to indicate that this failure
// has a compounding effect on viability of the overload choice it
// comes from.
if (locator.endsWith<LocatorPathElt::AnyRequirement>()) {
if (auto *expr = getAsExpr(anchor)) {
if (auto *call = getAsExpr<ApplyExpr>(cs.getParentExpr(expr))) {
if (call->getFn() == expr &&
llvm::any_of(cs.getFixes(), [&](const auto &fix) {
return getAsExpr(fix->getAnchor()) == call;
}))
impact += 2;
}
}
}
return impact;
}
@@ -8409,6 +8426,15 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
return SolutionKind::Solved;
}
// Conformance constraint that is introduced by an implicit conversion
// for example to `AnyHashable`.
if (kind == ConstraintKind::ConformsTo &&
loc->isLastElement<LocatorPathElt::ApplyArgToParam>()) {
auto *fix = AllowArgumentMismatch::create(*this, type, protocolTy, loc);
return recordFix(fix, /*impact=*/2) ? SolutionKind::Error
: SolutionKind::Solved;
}
// If this is an implicit Hashable conformance check generated for each
// index argument of the keypath subscript component, we could just treat
// it as though it conforms.

View File

@@ -661,10 +661,7 @@ example21890157.property = "confusing" // expected-error {{value of optional ty
struct UnaryOp {}
_ = -UnaryOp() // expected-error {{unary operator '-' cannot be applied to an operand of type 'UnaryOp'}}
// expected-note@-1 {{overloads for '-' exist with these partially matching parameter lists: (Double), (Float)}}
// <rdar://problem/23433271> Swift compiler segfault in failure diagnosis
func f23433271(_ x : UnsafePointer<Int>) {}
@@ -1551,3 +1548,12 @@ func rdar86611718(list: [Int]) {
String(list.count())
// expected-error@-1 {{cannot call value of non-function type 'Int'}}
}
// rdar://108977234 - failed to produce diagnostic when argument to AnyHashable parameter doesn't conform to Hashable protocol
do {
struct NonHashable {}
func test(result: inout [AnyHashable], value: NonHashable) {
result.append(value) // expected-error {{argument type 'NonHashable' does not conform to expected type 'Hashable'}}
}
}