Skip to content

Commit 67ee821

Browse files
committed
[CS] Allow getCalleeLocator to find key path component callees
In order to do this we need it to take a ConstraintLocator argument so we can tell which component we want the callee for. To make it clear that we're looking for a callee at the anchor, also rename the member to getAnchormostCalleeLocator.
1 parent b8b93eb commit 67ee821

File tree

5 files changed

+86
-32
lines changed

5 files changed

+86
-32
lines changed

lib/Sema/CSApply.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4243,11 +4243,11 @@ namespace {
42434243

42444244
auto locator = cs.getConstraintLocator(
42454245
E, LocatorPathElt::KeyPathComponent(i));
4246-
if (kind == KeyPathExpr::Component::Kind::UnresolvedSubscript) {
4247-
locator =
4248-
cs.getConstraintLocator(locator,
4249-
ConstraintLocator::SubscriptMember);
4250-
}
4246+
4247+
// Adjust the locator such that it includes any additional elements to
4248+
// point to the component's callee, e.g a SubscriptMember for a
4249+
// subscript component.
4250+
locator = cs.getAnchormostCalleeLocator(locator);
42514251

42524252
bool isDynamicMember = false;
42534253
// If this is an unresolved link, make sure we resolved it.

lib/Sema/CSDiagnostics.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ Expr *FailureDiagnostic::getBaseExprFor(Expr *anchor) const {
123123

124124
Optional<SelectedOverload> FailureDiagnostic::getChoiceFor(Expr *expr) const {
125125
auto &cs = getConstraintSystem();
126-
return getOverloadChoiceIfAvailable(cs.getCalleeLocator(expr));
126+
auto *loc = cs.getConstraintLocator(expr);
127+
return getOverloadChoiceIfAvailable(cs.getAnchormostCalleeLocator(loc));
127128
}
128129

129130
Type FailureDiagnostic::resolveInterfaceType(Type type,

lib/Sema/CSGen.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3023,6 +3023,8 @@ namespace {
30233023
}
30243024

30253025
case KeyPathExpr::Component::Kind::TupleElement: {
3026+
// Note: If implemented, the logic in `getAnchormostCalleeLocator`
3027+
// will need updating to return the correct callee locator for this.
30263028
llvm_unreachable("not implemented");
30273029
break;
30283030
}
@@ -3256,7 +3258,9 @@ namespace {
32563258
// Record the labels.
32573259
if (!labelsArePermanent)
32583260
info.Labels = CS.allocateCopy(info.Labels);
3259-
CS.ArgumentInfos[CS.getArgumentInfoLocator(expr)] = info;
3261+
3262+
auto *locator = CS.getConstraintLocator(expr);
3263+
CS.ArgumentInfos[CS.getArgumentInfoLocator(locator)] = info;
32603264
}
32613265
};
32623266

lib/Sema/ConstraintSystem.cpp

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -413,14 +413,49 @@ ConstraintLocator *ConstraintSystem::getConstraintLocator(
413413
return getConstraintLocator(anchor, path, builder.getSummaryFlags());
414414
}
415415

416-
ConstraintLocator *ConstraintSystem::getCalleeLocator(Expr *expr) {
416+
ConstraintLocator *
417+
ConstraintSystem::getAnchormostCalleeLocator(ConstraintLocator *locator) {
418+
auto *anchor = locator->getAnchor();
419+
assert(anchor && "Expected an anchor!");
420+
421+
// If we have a locator that starts with a key path component element, we
422+
// may have a callee given by a property or subscript component.
423+
if (auto componentElt =
424+
locator->getFirstElementAs<LocatorPathElt::KeyPathComponent>()) {
425+
auto *kpExpr = cast<KeyPathExpr>(anchor);
426+
auto component = kpExpr->getComponents()[componentElt->getIndex()];
427+
428+
using ComponentKind = KeyPathExpr::Component::Kind;
429+
switch (component.getKind()) {
430+
case ComponentKind::UnresolvedSubscript:
431+
case ComponentKind::Subscript:
432+
// For a subscript the callee is given by 'component -> subscript member'.
433+
return getConstraintLocator(
434+
anchor, {*componentElt, ConstraintLocator::SubscriptMember});
435+
case ComponentKind::UnresolvedProperty:
436+
case ComponentKind::Property:
437+
// For a property, the choice is just given by the component.
438+
return getConstraintLocator(anchor, *componentElt);
439+
case ComponentKind::TupleElement:
440+
llvm_unreachable("Not implemented by CSGen");
441+
break;
442+
case ComponentKind::Invalid:
443+
case ComponentKind::OptionalForce:
444+
case ComponentKind::OptionalChain:
445+
case ComponentKind::OptionalWrap:
446+
case ComponentKind::Identity:
447+
// These components don't have any callee associated, so just continue.
448+
break;
449+
}
450+
}
451+
417452
// Make sure we handle subscripts before looking at apply exprs. We don't
418453
// want to return a subscript member locator for an expression such as x[](y),
419454
// as its callee is not the subscript, but rather the function it returns.
420-
if (isa<SubscriptExpr>(expr))
421-
return getConstraintLocator(expr, ConstraintLocator::SubscriptMember);
455+
if (isa<SubscriptExpr>(anchor))
456+
return getConstraintLocator(anchor, ConstraintLocator::SubscriptMember);
422457

423-
if (auto *applyExpr = dyn_cast<ApplyExpr>(expr)) {
458+
if (auto *applyExpr = dyn_cast<ApplyExpr>(anchor)) {
424459
auto *fnExpr = applyExpr->getFn();
425460
// For an apply of a metatype, we have a short-form constructor. Unlike
426461
// other locators to callees, these are anchored on the apply expression
@@ -436,27 +471,27 @@ ConstraintLocator *ConstraintSystem::getCalleeLocator(Expr *expr) {
436471
// Otherwise fall through and look for locators anchored on the function
437472
// expr. For CallExprs, this can look through things like parens and
438473
// optional chaining.
439-
if (auto *callExpr = dyn_cast<CallExpr>(expr)) {
440-
expr = callExpr->getDirectCallee();
474+
if (auto *callExpr = dyn_cast<CallExpr>(anchor)) {
475+
anchor = callExpr->getDirectCallee();
441476
} else {
442-
expr = fnExpr;
477+
anchor = fnExpr;
443478
}
444479
}
445480

446-
if (auto *UDE = dyn_cast<UnresolvedDotExpr>(expr)) {
481+
if (auto *UDE = dyn_cast<UnresolvedDotExpr>(anchor)) {
447482
return getConstraintLocator(
448-
expr, TC.getSelfForInitDelegationInConstructor(DC, UDE)
483+
anchor, TC.getSelfForInitDelegationInConstructor(DC, UDE)
449484
? ConstraintLocator::ConstructorMember
450485
: ConstraintLocator::Member);
451486
}
452487

453-
if (isa<UnresolvedMemberExpr>(expr))
454-
return getConstraintLocator(expr, ConstraintLocator::UnresolvedMember);
488+
if (isa<UnresolvedMemberExpr>(anchor))
489+
return getConstraintLocator(anchor, ConstraintLocator::UnresolvedMember);
455490

456-
if (isa<MemberRefExpr>(expr))
457-
return getConstraintLocator(expr, ConstraintLocator::Member);
491+
if (isa<MemberRefExpr>(anchor))
492+
return getConstraintLocator(anchor, ConstraintLocator::Member);
458493

459-
return getConstraintLocator(expr);
494+
return getConstraintLocator(anchor);
460495
}
461496

462497
Type ConstraintSystem::openUnboundGenericType(UnboundGenericType *unbound,
@@ -2462,7 +2497,7 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes(
24622497
return false;
24632498

24642499
const auto *fix = fixes.front();
2465-
auto *calleeLocator = getCalleeLocator(fix->getAnchor());
2500+
auto *calleeLocator = getAnchormostCalleeLocator(fix->getLocator());
24662501
if (commonCalleeLocator && commonCalleeLocator != calleeLocator)
24672502
return false;
24682503

@@ -2829,7 +2864,9 @@ void ConstraintSystem::generateConstraints(
28292864
}
28302865
}
28312866

2832-
ConstraintLocator *ConstraintSystem::getArgumentInfoLocator(Expr *anchor) {
2867+
ConstraintLocator *
2868+
ConstraintSystem::getArgumentInfoLocator(ConstraintLocator *locator) {
2869+
auto *anchor = locator->getAnchor();
28332870
if (!anchor)
28342871
return nullptr;
28352872

@@ -2838,12 +2875,12 @@ ConstraintLocator *ConstraintSystem::getArgumentInfoLocator(Expr *anchor) {
28382875
return getConstraintLocator(fnExpr);
28392876
}
28402877

2841-
return getCalleeLocator(anchor);
2878+
return getAnchormostCalleeLocator(locator);
28422879
}
28432880

28442881
Optional<ConstraintSystem::ArgumentInfo>
28452882
ConstraintSystem::getArgumentInfo(ConstraintLocator *locator) {
2846-
if (auto *infoLocator = getArgumentInfoLocator(locator->getAnchor())) {
2883+
if (auto *infoLocator = getArgumentInfoLocator(locator)) {
28472884
auto known = ArgumentInfos.find(infoLocator);
28482885
if (known != ArgumentInfos.end())
28492886
return known->second;

lib/Sema/ConstraintSystem.h

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1579,9 +1579,10 @@ class ConstraintSystem {
15791579
/// that locator.
15801580
llvm::DenseMap<ConstraintLocator *, ArgumentInfo> ArgumentInfos;
15811581

1582-
/// Form a locator with given anchor which then could be used
1583-
/// to retrieve argument information cached in the constraint system.
1584-
ConstraintLocator *getArgumentInfoLocator(Expr *anchor);
1582+
/// Form a locator that can be used to retrieve argument information cached in
1583+
/// the constraint system for the callee described by the anchor of the
1584+
/// passed locator.
1585+
ConstraintLocator *getArgumentInfoLocator(ConstraintLocator *locator);
15851586

15861587
/// Retrieve the argument info that is associated with a member
15871588
/// reference at the given locator.
@@ -2008,10 +2009,21 @@ class ConstraintSystem {
20082009
return e != ExprWeights.end() ? e->second.second : nullptr;
20092010
}
20102011

2011-
/// Returns a locator describing the callee for a given expression. For
2012-
/// a function application, this is a locator describing the function expr.
2013-
/// For an unresolved dot/member, this is a locator to the member.
2014-
ConstraintLocator *getCalleeLocator(Expr *expr);
2012+
/// Returns a locator describing the callee for the anchor of a given locator.
2013+
///
2014+
/// - For an unresolved dot/member anchor, this will be a locator describing
2015+
/// the member.
2016+
///
2017+
/// - For a subscript anchor, this will be a locator describing the subscript
2018+
/// member.
2019+
///
2020+
/// - For a key path anchor with a property/subscript component path element,
2021+
/// this will be a locator describing the decl referenced by the component.
2022+
///
2023+
/// - For a function application anchor, this will be a locator describing the
2024+
/// 'direct callee' of the call. For example, for the expression \c x.foo?()
2025+
/// the returned locator will describe the member \c foo.
2026+
ConstraintLocator *getAnchormostCalleeLocator(ConstraintLocator *locator);
20152027

20162028
public:
20172029

0 commit comments

Comments
 (0)