Skip to content

Commit c3460f8

Browse files
committed
[Diagnostics] Diagnose keypath subscript components with missing Hashable conformances
1 parent c982706 commit c3460f8

File tree

3 files changed

+45
-1
lines changed

3 files changed

+45
-1
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2398,3 +2398,15 @@ bool InaccessibleMemberFailure::diagnoseAsError() {
23982398
emitDiagnostic(Member, diag::decl_declared_here, Member->getFullName());
23992399
return true;
24002400
}
2401+
2402+
bool KeyPathSubscriptIndexHashableFailure::diagnoseAsError() {
2403+
auto *anchor = cast<KeyPathExpr>(getRawAnchor());
2404+
auto path = getLocator()->getPath();
2405+
const auto &componentIndex = path.back().getValue();
2406+
2407+
auto *indexExpr = anchor->getComponents()[componentIndex].getIndexExpr();
2408+
emitDiagnostic(indexExpr->getLoc(),
2409+
diag::expr_keypath_subscript_index_not_hashable,
2410+
resolveType(NonConformingType));
2411+
return true;
2412+
}

lib/Sema/CSDiagnostics.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -987,6 +987,36 @@ class InaccessibleMemberFailure final : public FailureDiagnostic {
987987
bool diagnoseAsError() override;
988988
};
989989

990+
/// Diagnose an attempt to reference subscript as a keypath component
991+
/// where at least one of the index arguments doesn't conform to Hashable e.g.
992+
///
993+
/// ```swift
994+
/// protocol P {}
995+
///
996+
/// struct S {
997+
/// subscript<T: P>(x: Int, _ y: T) -> Bool { return true }
998+
/// }
999+
///
1000+
/// func foo<T: P>(_ x: Int, _ y: T) {
1001+
/// _ = \S.[x, y]
1002+
/// }
1003+
/// ```
1004+
class KeyPathSubscriptIndexHashableFailure final : public FailureDiagnostic {
1005+
Type NonConformingType;
1006+
1007+
public:
1008+
KeyPathSubscriptIndexHashableFailure(Expr *root, ConstraintSystem &cs,
1009+
Type type, ConstraintLocator *locator)
1010+
: FailureDiagnostic(root, cs, locator), NonConformingType(type) {
1011+
#ifndef NDEBUG
1012+
auto path = locator->getPath();
1013+
assert(!path.empty() && path.back().isKeyPathComponent());
1014+
#endif
1015+
}
1016+
1017+
bool diagnoseAsError() override;
1018+
};
1019+
9901020
} // end namespace constraints
9911021
} // end namespace swift
9921022

lib/Sema/CSFix.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,9 @@ AllowInaccessibleMember::create(ConstraintSystem &cs, ValueDecl *member,
399399

400400
bool TreatKeyPathSubscriptIndexAsHashable::diagnose(Expr *root,
401401
bool asNote) const {
402-
return false;
402+
KeyPathSubscriptIndexHashableFailure failure(root, getConstraintSystem(),
403+
NonConformingType, getLocator());
404+
return failure.diagnose(asNote);
403405
}
404406

405407
TreatKeyPathSubscriptIndexAsHashable *

0 commit comments

Comments
 (0)