Skip to content

Commit 4423399

Browse files
committed
[CS] Use apply component locator for verifyThatArgumentIsHashable
For a method key path use the locator for the apply itself rather than the member, ensuring we handle invalid cases where the apply is the first component, and providing more accurate location info.
1 parent 61d0486 commit 4423399

File tree

8 files changed

+26
-16
lines changed

8 files changed

+26
-16
lines changed

include/swift/Sema/ConstraintLocator.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,10 @@ class ConstraintLocator : public llvm::FoldingSetNode {
260260
/// of the key path at some index.
261261
bool isKeyPathMemberComponent() const;
262262

263+
/// Determine whether this locator points to an apply component of the key
264+
/// path at some index.
265+
bool isKeyPathApplyComponent() const;
266+
263267
/// Determine whether this locator points to the member found
264268
/// via key path dynamic member lookup.
265269
bool isForKeyPathDynamicMemberLookup() const;

lib/Sema/CSDiagnostics.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6405,7 +6405,8 @@ SourceLoc KeyPathSubscriptIndexHashableFailure::getLoc() const {
64056405
auto *locator = getLocator();
64066406

64076407
if (locator->isKeyPathSubscriptComponent() ||
6408-
locator->isKeyPathMemberComponent()) {
6408+
locator->isKeyPathMemberComponent() ||
6409+
locator->isKeyPathApplyComponent()) {
64096410
auto *KPE = castToExpr<KeyPathExpr>(getAnchor());
64106411
if (auto kpElt = locator->findFirst<LocatorPathElt::KeyPathComponent>())
64116412
return KPE->getComponents()[kpElt->getIndex()].getLoc();
@@ -6417,7 +6418,7 @@ SourceLoc KeyPathSubscriptIndexHashableFailure::getLoc() const {
64176418
bool KeyPathSubscriptIndexHashableFailure::diagnoseAsError() {
64186419
auto *locator = getLocator();
64196420
emitDiagnostic(diag::expr_keypath_arg_or_index_not_hashable,
6420-
!locator->isKeyPathMemberComponent(),
6421+
!locator->isKeyPathApplyComponent(),
64216422
resolveType(NonConformingType));
64226423
return true;
64236424
}

lib/Sema/CSDiagnostics.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1707,9 +1707,10 @@ class KeyPathSubscriptIndexHashableFailure final : public FailureDiagnostic {
17071707
KeyPathSubscriptIndexHashableFailure(const Solution &solution, Type type,
17081708
ConstraintLocator *locator)
17091709
: FailureDiagnostic(solution, locator), NonConformingType(type) {
1710-
assert((locator->isResultOfKeyPathDynamicMemberLookup() ||
1711-
locator->isKeyPathSubscriptComponent()) ||
1712-
locator->isKeyPathMemberComponent());
1710+
assert(locator->isResultOfKeyPathDynamicMemberLookup() ||
1711+
locator->isKeyPathSubscriptComponent() ||
1712+
locator->isKeyPathMemberComponent() ||
1713+
locator->isKeyPathApplyComponent());
17131714
}
17141715

17151716
SourceLoc getLoc() const override;

lib/Sema/CSGen.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,7 +1198,6 @@ namespace {
11981198
/// component kind.
11991199
Type addApplyConstraints(
12001200
Expr *anchor, Type memberTy, ArgumentList *argList,
1201-
ConstraintLocator *memberComponentLoc,
12021201
ConstraintLocator *applyComponentLoc,
12031202
SmallVectorImpl<TypeVariableType *> *addedTypeVars = nullptr) {
12041203
// Locators used in this expression.
@@ -1225,7 +1224,7 @@ namespace {
12251224
for (auto index : indices(params)) {
12261225
const auto &param = params[index];
12271226
CS.verifyThatArgumentIsHashable(index, param.getParameterType(),
1228-
memberComponentLoc, loc);
1227+
applyComponentLoc, loc);
12291228
}
12301229

12311230
// Add the constraint that the index expression's type be convertible
@@ -3895,11 +3894,8 @@ namespace {
38953894

38963895
case KeyPathExpr::Component::Kind::UnresolvedApply:
38973896
case KeyPathExpr::Component::Kind::Apply: {
3898-
auto prevMemberLocator = CS.getConstraintLocator(
3899-
locator, LocatorPathElt::KeyPathComponent(i - 1));
39003897
base = addApplyConstraints(E, base, component.getArgs(),
3901-
prevMemberLocator, memberLocator,
3902-
&componentTypeVars);
3898+
memberLocator, &componentTypeVars);
39033899
break;
39043900
}
39053901

lib/Sema/CSSimplify.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9221,9 +9221,10 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
92219221
// If this is an implicit Hashable conformance check generated for each
92229222
// index argument of the keypath subscript component, we could just treat
92239223
// it as though it conforms.
9224-
if ((loc->isResultOfKeyPathDynamicMemberLookup() ||
9225-
loc->isKeyPathSubscriptComponent()) ||
9226-
loc->isKeyPathMemberComponent()) {
9224+
if (loc->isResultOfKeyPathDynamicMemberLookup() ||
9225+
loc->isKeyPathSubscriptComponent() ||
9226+
loc->isKeyPathMemberComponent() ||
9227+
loc->isKeyPathApplyComponent()) {
92279228
if (protocol ==
92289229
getASTContext().getProtocol(KnownProtocolKind::Hashable)) {
92299230
auto *fix =

lib/Sema/ConstraintLocator.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,13 @@ bool ConstraintLocator::isKeyPathMemberComponent() const {
627627
});
628628
}
629629

630+
bool ConstraintLocator::isKeyPathApplyComponent() const {
631+
return hasKeyPathComponent(this, [](auto kind) {
632+
return kind == KeyPathExpr::Component::Kind::Apply ||
633+
kind == KeyPathExpr::Component::Kind::UnresolvedApply;
634+
});
635+
}
636+
630637
bool ConstraintLocator::isForKeyPathDynamicMemberLookup() const {
631638
auto path = getPath();
632639
return !path.empty() && path.back().isKeyPathDynamicMember();
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
// {"kind":"typecheck","signature":"swift::constraints::ConstraintSystem::simplifyConformsToConstraint(swift::Type, swift::ProtocolDecl*, swift::constraints::ConstraintKind, swift::constraints::ConstraintLocatorBuilder, swift::optionset::OptionSet<swift::constraints::ConstraintSystem::TypeMatchFlags, unsigned int>)","signatureAssert":"Assertion failed: (Index < Length && \"Invalid index!\"), function operator[]"}
2-
// RUN: not --crash %target-swift-frontend -typecheck %s
2+
// RUN: not %target-swift-frontend -typecheck %s
33
\_(error)
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
// {"kind":"typecheck","signature":"swift::constraints::ConstraintSystem::getCalleeLocator(swift::constraints::ConstraintLocator*, bool, llvm::function_ref<swift::Type (swift::Expr*)>, llvm::function_ref<swift::Type (swift::Type)>, llvm::function_ref<std::__1::optional<swift::constraints::SelectedOverload> (swift::constraints::ConstraintLocator*)>)","signatureAssert":"Assertion failed: (Index < Length && \"Invalid index!\"), function operator[]"}
2-
// RUN: not --crash %target-swift-frontend -typecheck %s
2+
// RUN: not %target-swift-frontend -typecheck %s
33
struct a func b(c : [Int]) {
44
\ a(c.map{})

0 commit comments

Comments
 (0)