Skip to content

Commit c982706

Browse files
committed
[CSFix] Fix keypath subscript index to conform to Hashable
1 parent 3288299 commit c982706

File tree

3 files changed

+66
-1
lines changed

3 files changed

+66
-1
lines changed

lib/Sema/CSFix.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,3 +396,15 @@ AllowInaccessibleMember::create(ConstraintSystem &cs, ValueDecl *member,
396396
ConstraintLocator *locator) {
397397
return new (cs.getAllocator()) AllowInaccessibleMember(cs, member, locator);
398398
}
399+
400+
bool TreatKeyPathSubscriptIndexAsHashable::diagnose(Expr *root,
401+
bool asNote) const {
402+
return false;
403+
}
404+
405+
TreatKeyPathSubscriptIndexAsHashable *
406+
TreatKeyPathSubscriptIndexAsHashable::create(ConstraintSystem &cs, Type type,
407+
ConstraintLocator *locator) {
408+
return new (cs.getAllocator())
409+
TreatKeyPathSubscriptIndexAsHashable(cs, type, locator);
410+
}

lib/Sema/CSFix.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ enum class FixKind : uint8_t {
136136
/// If there is a matching inaccessible member - allow it as if there
137137
/// no access control.
138138
AllowInaccessibleMember,
139+
140+
/// Using subscript references in the keypath requires that each
141+
// of the index arguments to be Hashable.
142+
TreatKeyPathSubscriptIndexAsHashable,
139143
};
140144

141145
class ConstraintFix {
@@ -737,6 +741,26 @@ class AllowInaccessibleMember final : public ConstraintFix {
737741
ConstraintLocator *locator);
738742
};
739743

744+
class TreatKeyPathSubscriptIndexAsHashable final : public ConstraintFix {
745+
Type NonConformingType;
746+
747+
TreatKeyPathSubscriptIndexAsHashable(ConstraintSystem &cs, Type type,
748+
ConstraintLocator *locator)
749+
: ConstraintFix(cs, FixKind::TreatKeyPathSubscriptIndexAsHashable,
750+
locator),
751+
NonConformingType(type) {}
752+
753+
public:
754+
std::string getName() const override {
755+
return "treat keypath subscript index as conforming to Hashable";
756+
}
757+
758+
bool diagnose(Expr *root, bool asNote = false) const override;
759+
760+
static TreatKeyPathSubscriptIndexAsHashable *
761+
create(ConstraintSystem &cs, Type type, ConstraintLocator *locator);
762+
};
763+
740764
} // end namespace constraints
741765
} // end namespace swift
742766

lib/Sema/CSSimplify.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,21 @@ ConstraintSystem::TypeMatchResult constraints::matchCallArguments(
983983
const auto &param = params[paramIdx];
984984
auto paramTy = param.getOldType();
985985

986+
// Each of the index parameters has to conform to Hashable
987+
// to be viable for use as a keypath subscript component.
988+
if (keyPathSubscriptComponent) {
989+
auto *hashable =
990+
cs.getASTContext().getProtocol(KnownProtocolKind::Hashable);
991+
// Standard library might be broken.
992+
if (!hashable)
993+
return cs.getTypeMatchFailure(locator);
994+
995+
cs.addConstraint(
996+
ConstraintKind::ConformsTo, paramTy, hashable->getDeclaredType(),
997+
cs.getConstraintLocator(keyPathSubscriptComponent,
998+
LocatorPathElt::getTupleElement(paramIdx)));
999+
}
1000+
9861001
if (param.isAutoClosure())
9871002
paramTy = paramTy->castTo<FunctionType>()->getResult();
9881003

@@ -3140,8 +3155,21 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
31403155
if (!recordFix(fix))
31413156
return SolutionKind::Solved;
31423157
}
3158+
3159+
// If this is an implicit Hashable conformance check generated for each
3160+
// index argument of the keypath subscript component, we could just treat
3161+
// it as though it conforms.
3162+
if (auto *component = getAsKeyPathSubscriptComponent(*this, anchor, path)) {
3163+
if (protocol ==
3164+
getASTContext().getProtocol(KnownProtocolKind::Hashable)) {
3165+
auto *fix = TreatKeyPathSubscriptIndexAsHashable::create(*this, type,
3166+
component);
3167+
if (!recordFix(fix))
3168+
return SolutionKind::Solved;
3169+
}
3170+
}
31433171
}
3144-
3172+
31453173
// There's nothing more we can do; fail.
31463174
return SolutionKind::Error;
31473175
}
@@ -6276,6 +6304,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
62766304
case FixKind::AllowClosureParameterDestructuring:
62776305
case FixKind::MoveOutOfOrderArgument:
62786306
case FixKind::AllowInaccessibleMember:
6307+
case FixKind::TreatKeyPathSubscriptIndexAsHashable:
62796308
llvm_unreachable("handled elsewhere");
62806309
}
62816310

0 commit comments

Comments
 (0)