mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Sema] Diagnose method arg captures that are not Hashable/Equatable.
This commit is contained in:
@@ -719,8 +719,8 @@ ERROR(expr_swift_keypath_empty, none,
|
|||||||
"key path must have at least one component", ())
|
"key path must have at least one component", ())
|
||||||
ERROR(expr_string_interpolation_outside_string,none,
|
ERROR(expr_string_interpolation_outside_string,none,
|
||||||
"string interpolation can only appear inside a string literal", ())
|
"string interpolation can only appear inside a string literal", ())
|
||||||
ERROR(expr_keypath_subscript_index_not_hashable, none,
|
ERROR(expr_keypath_arg_or_index_not_hashable, none,
|
||||||
"subscript index of type %0 in a key path must be Hashable", (Type))
|
"%select{method argument|subscript index}0 of type %1 in a key path must be Hashable", (bool, Type))
|
||||||
ERROR(expr_smart_keypath_application_type_mismatch,none,
|
ERROR(expr_smart_keypath_application_type_mismatch,none,
|
||||||
"key path of type %0 cannot be applied to a base of type %1",
|
"key path of type %0 cannot be applied to a base of type %1",
|
||||||
(Type, Type))
|
(Type, Type))
|
||||||
|
|||||||
@@ -256,6 +256,10 @@ public:
|
|||||||
/// of the key path at some index.
|
/// of the key path at some index.
|
||||||
bool isKeyPathSubscriptComponent() const;
|
bool isKeyPathSubscriptComponent() const;
|
||||||
|
|
||||||
|
/// Determine whether this locator points to a member component
|
||||||
|
/// of the key path at some index.
|
||||||
|
bool isKeyPathMemberComponent() const;
|
||||||
|
|
||||||
/// Determine whether this locator points to the member found
|
/// Determine whether this locator points to the member found
|
||||||
/// via key path dynamic member lookup.
|
/// via key path dynamic member lookup.
|
||||||
bool isForKeyPathDynamicMemberLookup() const;
|
bool isForKeyPathDynamicMemberLookup() const;
|
||||||
|
|||||||
@@ -6347,7 +6347,8 @@ bool AnyObjectKeyPathRootFailure::diagnoseAsError() {
|
|||||||
SourceLoc KeyPathSubscriptIndexHashableFailure::getLoc() const {
|
SourceLoc KeyPathSubscriptIndexHashableFailure::getLoc() const {
|
||||||
auto *locator = getLocator();
|
auto *locator = getLocator();
|
||||||
|
|
||||||
if (locator->isKeyPathSubscriptComponent()) {
|
if (locator->isKeyPathSubscriptComponent() ||
|
||||||
|
locator->isKeyPathMemberComponent()) {
|
||||||
auto *KPE = castToExpr<KeyPathExpr>(getAnchor());
|
auto *KPE = castToExpr<KeyPathExpr>(getAnchor());
|
||||||
if (auto kpElt = locator->findFirst<LocatorPathElt::KeyPathComponent>())
|
if (auto kpElt = locator->findFirst<LocatorPathElt::KeyPathComponent>())
|
||||||
return KPE->getComponents()[kpElt->getIndex()].getLoc();
|
return KPE->getComponents()[kpElt->getIndex()].getLoc();
|
||||||
@@ -6357,7 +6358,9 @@ SourceLoc KeyPathSubscriptIndexHashableFailure::getLoc() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool KeyPathSubscriptIndexHashableFailure::diagnoseAsError() {
|
bool KeyPathSubscriptIndexHashableFailure::diagnoseAsError() {
|
||||||
emitDiagnostic(diag::expr_keypath_subscript_index_not_hashable,
|
auto *locator = getLocator();
|
||||||
|
emitDiagnostic(diag::expr_keypath_arg_or_index_not_hashable,
|
||||||
|
!locator->isKeyPathMemberComponent(),
|
||||||
resolveType(NonConformingType));
|
resolveType(NonConformingType));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1707,8 +1707,9 @@ public:
|
|||||||
KeyPathSubscriptIndexHashableFailure(const Solution &solution, Type type,
|
KeyPathSubscriptIndexHashableFailure(const Solution &solution, Type type,
|
||||||
ConstraintLocator *locator)
|
ConstraintLocator *locator)
|
||||||
: FailureDiagnostic(solution, locator), NonConformingType(type) {
|
: FailureDiagnostic(solution, locator), NonConformingType(type) {
|
||||||
assert(locator->isResultOfKeyPathDynamicMemberLookup() ||
|
assert((locator->isResultOfKeyPathDynamicMemberLookup() ||
|
||||||
locator->isKeyPathSubscriptComponent());
|
locator->isKeyPathSubscriptComponent()) ||
|
||||||
|
locator->isKeyPathMemberComponent());
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceLoc getLoc() const override;
|
SourceLoc getLoc() const override;
|
||||||
|
|||||||
@@ -9073,8 +9073,9 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
|
|||||||
// If this is an implicit Hashable conformance check generated for each
|
// If this is an implicit Hashable conformance check generated for each
|
||||||
// index argument of the keypath subscript component, we could just treat
|
// index argument of the keypath subscript component, we could just treat
|
||||||
// it as though it conforms.
|
// it as though it conforms.
|
||||||
if (loc->isResultOfKeyPathDynamicMemberLookup() ||
|
if ((loc->isResultOfKeyPathDynamicMemberLookup() ||
|
||||||
loc->isKeyPathSubscriptComponent()) {
|
loc->isKeyPathSubscriptComponent()) ||
|
||||||
|
loc->isKeyPathMemberComponent()) {
|
||||||
if (protocol ==
|
if (protocol ==
|
||||||
getASTContext().getProtocol(KnownProtocolKind::Hashable)) {
|
getASTContext().getProtocol(KnownProtocolKind::Hashable)) {
|
||||||
auto *fix =
|
auto *fix =
|
||||||
|
|||||||
@@ -607,6 +607,25 @@ bool ConstraintLocator::isKeyPathSubscriptComponent() const {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ConstraintLocator::isKeyPathMemberComponent() const {
|
||||||
|
auto *anchor = getAsExpr(getAnchor());
|
||||||
|
auto *KPE = dyn_cast_or_null<KeyPathExpr>(anchor);
|
||||||
|
if (!KPE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
using ComponentKind = KeyPathExpr::Component::Kind;
|
||||||
|
return llvm::any_of(getPath(), [&](const LocatorPathElt &elt) {
|
||||||
|
auto keyPathElt = elt.getAs<LocatorPathElt::KeyPathComponent>();
|
||||||
|
if (!keyPathElt)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto index = keyPathElt->getIndex();
|
||||||
|
auto &component = KPE->getComponents()[index];
|
||||||
|
return component.getKind() == ComponentKind::Member ||
|
||||||
|
component.getKind() == ComponentKind::UnresolvedMember;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
bool ConstraintLocator::isForKeyPathDynamicMemberLookup() const {
|
bool ConstraintLocator::isForKeyPathDynamicMemberLookup() const {
|
||||||
auto path = getPath();
|
auto path = getPath();
|
||||||
return !path.empty() && path.back().isKeyPathDynamicMember();
|
return !path.empty() && path.back().isKeyPathDynamicMember();
|
||||||
|
|||||||
Reference in New Issue
Block a user