Skip to content

Commit a20188b

Browse files
authored
Merge pull request #24826 from hamishknight/who-ya-gonna-callee
[CS] Consolidate logic forming locators to callees
2 parents 3b4bb19 + f4c0bc7 commit a20188b

13 files changed

+120
-152
lines changed

lib/Sema/CSApply.cpp

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4479,8 +4479,7 @@ namespace {
44794479
buildKeyPathPropertyComponent(const SelectedOverload &overload,
44804480
SourceLoc componentLoc,
44814481
ConstraintLocator *locator) {
4482-
if (overload.choice.isDecl()) {
4483-
auto property = overload.choice.getDecl();
4482+
if (auto *property = overload.choice.getDeclOrNull()) {
44844483
// Key paths can only refer to properties currently.
44854484
auto varDecl = cast<VarDecl>(property);
44864485
// Key paths don't work with mutating-get properties.
@@ -4784,10 +4783,8 @@ static ConcreteDeclRef resolveLocatorToDecl(
47844783
// Overloaded and unresolved cases: find the resolved overload.
47854784
auto anchorLocator = cs.getConstraintLocator(anchor);
47864785
if (auto selected = findOvlChoice(anchorLocator)) {
4787-
if (selected->choice.isDecl())
4788-
return getConcreteDeclRef(selected->choice.getDecl(),
4789-
selected->openedType,
4790-
anchorLocator);
4786+
if (auto *decl = selected->choice.getDeclOrNull())
4787+
return getConcreteDeclRef(decl, selected->openedType, anchorLocator);
47914788
}
47924789
}
47934790

@@ -4796,10 +4793,8 @@ static ConcreteDeclRef resolveLocatorToDecl(
47964793
auto anchorLocator = cs.getConstraintLocator(anchor,
47974794
ConstraintLocator::UnresolvedMember);
47984795
if (auto selected = findOvlChoice(anchorLocator)) {
4799-
if (selected->choice.isDecl())
4800-
return getConcreteDeclRef(selected->choice.getDecl(),
4801-
selected->openedType,
4802-
anchorLocator);
4796+
if (auto *decl = selected->choice.getDeclOrNull())
4797+
return getConcreteDeclRef(decl, selected->openedType, anchorLocator);
48034798
}
48044799
}
48054800

@@ -4808,10 +4803,8 @@ static ConcreteDeclRef resolveLocatorToDecl(
48084803
auto anchorLocator = cs.getConstraintLocator(anchor,
48094804
ConstraintLocator::Member);
48104805
if (auto selected = findOvlChoice(anchorLocator)) {
4811-
if (selected->choice.isDecl())
4812-
return getConcreteDeclRef(selected->choice.getDecl(),
4813-
selected->openedType,
4814-
anchorLocator);
4806+
if (auto *decl = selected->choice.getDeclOrNull())
4807+
return getConcreteDeclRef(decl, selected->openedType, anchorLocator);
48154808
}
48164809
}
48174810

@@ -4824,10 +4817,8 @@ static ConcreteDeclRef resolveLocatorToDecl(
48244817
auto anchorLocator =
48254818
cs.getConstraintLocator(anchor, ConstraintLocator::SubscriptMember);
48264819
if (auto selected = findOvlChoice(anchorLocator)) {
4827-
if (selected->choice.isDecl())
4828-
return getConcreteDeclRef(selected->choice.getDecl(),
4829-
selected->openedType,
4830-
anchorLocator);
4820+
if (auto *decl = selected->choice.getDeclOrNull())
4821+
return getConcreteDeclRef(decl, selected->openedType, anchorLocator);
48314822
}
48324823
}
48334824

lib/Sema/CSDiag.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -867,9 +867,8 @@ bool FailureDiagnosis::diagnoseGeneralOverloadFailure(Constraint *constraint) {
867867
if (constraint->getKind() == ConstraintKind::Disjunction) {
868868
for (auto elt : constraint->getNestedConstraints()) {
869869
if (elt->getKind() != ConstraintKind::BindOverload) continue;
870-
if (!elt->getOverloadChoice().isDecl()) continue;
871-
auto candidate = elt->getOverloadChoice().getDecl();
872-
diagnose(candidate, diag::found_candidate);
870+
if (auto *candidate = elt->getOverloadChoice().getDeclOrNull())
871+
diagnose(candidate, diag::found_candidate);
873872
}
874873
}
875874

@@ -4663,7 +4662,11 @@ static bool isViableOverloadSet(const CalleeCandidateInfo &CCI,
46634662
for (unsigned i = 0; i < CCI.size(); ++i) {
46644663
auto &&cand = CCI[i];
46654664
auto funcDecl = dyn_cast_or_null<AbstractFunctionDecl>(cand.getDecl());
4666-
if (!funcDecl)
4665+
4666+
// If we don't have a func decl or we haven't resolved its parameters,
4667+
// continue. The latter case can occur with `type(of:)`, which is introduced
4668+
// as a type variable.
4669+
if (!funcDecl || !cand.hasParameters())
46674670
continue;
46684671

46694672
auto params = cand.getParameters();

lib/Sema/CSDiagnostics.cpp

Lines changed: 4 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -101,33 +101,9 @@ Expr *FailureDiagnostic::getArgumentExprFor(Expr *anchor) const {
101101
return nullptr;
102102
}
103103

104-
// TODO: Replace duplications of this logic with calls to this.
105-
Optional<SelectedOverload> FailureDiagnostic::getChoiceFor(Expr *expr) {
104+
Optional<SelectedOverload> FailureDiagnostic::getChoiceFor(Expr *expr) const {
106105
auto &cs = getConstraintSystem();
107-
ConstraintLocator *locator = nullptr;
108-
109-
if (auto *AE = dyn_cast<ApplyExpr>(expr)) {
110-
if (auto *TE = dyn_cast<TypeExpr>(AE->getFn())) {
111-
locator = cs.getConstraintLocator(AE,
112-
{ConstraintLocator::ApplyFunction,
113-
ConstraintLocator::ConstructorMember},
114-
/*summaryFlags=*/0);
115-
}
116-
return getChoiceFor(AE->getFn());
117-
} else if (auto *UDE = dyn_cast<UnresolvedDotExpr>(expr)) {
118-
locator = cs.getConstraintLocator(UDE, ConstraintLocator::Member);
119-
} else if (auto *UME = dyn_cast<UnresolvedMemberExpr>(expr)) {
120-
locator = cs.getConstraintLocator(UME, ConstraintLocator::UnresolvedMember);
121-
} else if (auto *SE = dyn_cast<SubscriptExpr>(expr)) {
122-
locator = cs.getConstraintLocator(SE, ConstraintLocator::SubscriptMember);
123-
} else {
124-
locator = cs.getConstraintLocator(expr);
125-
}
126-
127-
if (!locator)
128-
return None;
129-
130-
return getOverloadChoiceIfAvailable(locator);
106+
return getOverloadChoiceIfAvailable(cs.getCalleeLocator(expr));
131107
}
132108

133109
Type RequirementFailure::getOwnerType() const {
@@ -179,10 +155,6 @@ ProtocolConformance *RequirementFailure::getConformanceForConditionalReq(
179155

180156
ValueDecl *RequirementFailure::getDeclRef() const {
181157
auto &cs = getConstraintSystem();
182-
auto &TC = getTypeChecker();
183-
184-
auto *anchor = getRawAnchor();
185-
auto *locator = cs.getConstraintLocator(anchor);
186158

187159
// Get a declaration associated with given type (if any).
188160
// This is used to retrieve affected declaration when
@@ -204,38 +176,7 @@ ValueDecl *RequirementFailure::getDeclRef() const {
204176
if (isFromContextualType())
205177
return getAffectedDeclFromType(cs.getContextualType());
206178

207-
if (auto *AE = dyn_cast<CallExpr>(anchor)) {
208-
// NOTE: In valid code, the function can only be a TypeExpr
209-
assert(isa<TypeExpr>(AE->getFn()) ||
210-
isa<OverloadedDeclRefExpr>(AE->getFn()));
211-
ConstraintLocatorBuilder ctor(locator);
212-
locator = cs.getConstraintLocator(
213-
ctor.withPathElement(PathEltKind::ApplyFunction)
214-
.withPathElement(PathEltKind::ConstructorMember));
215-
} else if (auto *UDE = dyn_cast<UnresolvedDotExpr>(anchor)) {
216-
ConstraintLocatorBuilder member(locator);
217-
218-
if (TC.getSelfForInitDelegationInConstructor(getDC(), UDE)) {
219-
member = member.withPathElement(PathEltKind::ConstructorMember);
220-
} else {
221-
member = member.withPathElement(PathEltKind::Member);
222-
}
223-
224-
locator = cs.getConstraintLocator(member);
225-
} else if (auto *UME = dyn_cast<UnresolvedMemberExpr>(anchor)) {
226-
locator = cs.getConstraintLocator(locator, PathEltKind::UnresolvedMember);
227-
} else if (isa<SubscriptExpr>(anchor)) {
228-
ConstraintLocatorBuilder subscript(locator);
229-
locator = cs.getConstraintLocator(
230-
subscript.withPathElement(PathEltKind::SubscriptMember));
231-
} else if (isa<MemberRefExpr>(anchor)) {
232-
ConstraintLocatorBuilder memberRef(locator);
233-
locator =
234-
cs.getConstraintLocator(memberRef.withPathElement(PathEltKind::Member));
235-
}
236-
237-
auto overload = getOverloadChoiceIfAvailable(locator);
238-
if (overload)
179+
if (auto overload = getChoiceFor(getRawAnchor()))
239180
return overload->choice.getDecl();
240181

241182
return getAffectedDeclFromType(getOwnerType());
@@ -568,32 +509,7 @@ bool NoEscapeFuncToTypeConversionFailure::diagnoseParameterUse() const {
568509

569510
Type NoEscapeFuncToTypeConversionFailure::getParameterTypeFor(
570511
Expr *expr, unsigned paramIdx) const {
571-
auto &cs = getConstraintSystem();
572-
ConstraintLocator *locator = nullptr;
573-
574-
if (auto *call = dyn_cast<CallExpr>(expr)) {
575-
auto *fnExpr = call->getFn();
576-
if (isa<UnresolvedDotExpr>(fnExpr)) {
577-
locator = cs.getConstraintLocator(fnExpr, ConstraintLocator::Member);
578-
} else if (isa<UnresolvedMemberExpr>(fnExpr)) {
579-
locator =
580-
cs.getConstraintLocator(fnExpr, ConstraintLocator::UnresolvedMember);
581-
} else if (auto *TE = dyn_cast<TypeExpr>(fnExpr)) {
582-
locator = cs.getConstraintLocator(call,
583-
{ConstraintLocator::ApplyFunction,
584-
ConstraintLocator::ConstructorMember},
585-
/*summaryFlags=*/0);
586-
} else {
587-
locator = cs.getConstraintLocator(fnExpr);
588-
}
589-
} else if (auto *SE = dyn_cast<SubscriptExpr>(expr)) {
590-
locator = cs.getConstraintLocator(SE, ConstraintLocator::SubscriptMember);
591-
}
592-
593-
if (!locator)
594-
return Type();
595-
596-
auto choice = getOverloadChoiceIfAvailable(locator);
512+
auto choice = getChoiceFor(expr);
597513
if (!choice)
598514
return Type();
599515

lib/Sema/CSDiagnostics.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ class FailureDiagnostic {
155155
/// reference or subscript, nullptr otherwise.
156156
Expr *getArgumentExprFor(Expr *anchor) const;
157157

158-
Optional<SelectedOverload> getChoiceFor(Expr *);
158+
Optional<SelectedOverload> getChoiceFor(Expr *) const;
159159

160160
private:
161161
/// Compute anchor expression associated with current diagnostic.

lib/Sema/CSGen.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -622,9 +622,9 @@ namespace {
622622
unsigned numFavoredConstraints = 0;
623623
Constraint *firstFavored = nullptr;
624624
for (auto constraint : disjunction->getNestedConstraints()) {
625-
if (!constraint->getOverloadChoice().isDecl())
625+
auto *decl = constraint->getOverloadChoice().getDeclOrNull();
626+
if (!decl)
626627
continue;
627-
auto decl = constraint->getOverloadChoice().getDecl();
628628

629629
if (mustConsider && mustConsider(decl)) {
630630
// Roll back any constraints we favored.

lib/Sema/CSSimplify.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -859,8 +859,7 @@ getCalleeDeclAndArgs(ConstraintSystem &cs,
859859
hasTrailingClosure);
860860

861861
// If there's a declaration, return it.
862-
if (choice->isDecl()) {
863-
auto decl = choice->getDecl();
862+
if (auto *decl = choice->getDeclOrNull()) {
864863
bool hasCurriedSelf = false;
865864
if (decl->getDeclContext()->isTypeContext()) {
866865
if (auto function = dyn_cast<AbstractFunctionDecl>(decl)) {
@@ -4475,9 +4474,7 @@ fixMemberRef(ConstraintSystem &cs, Type baseTy,
44754474
Optional<MemberLookupResult::UnviableReason> reason = None) {
44764475
// Not all of the choices handled here are going
44774476
// to refer to a declaration.
4478-
if (choice.isDecl()) {
4479-
auto *decl = choice.getDecl();
4480-
4477+
if (auto *decl = choice.getDeclOrNull()) {
44814478
if (auto *CD = dyn_cast<ConstructorDecl>(decl)) {
44824479
if (auto *fix = validateInitializerRef(cs, CD, locator))
44834480
return fix;

lib/Sema/CSSolver.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2092,11 +2092,9 @@ void ConstraintSystem::partitionDisjunction(
20922092
forEachChoice(Choices, [&](unsigned index, Constraint *constraint) -> bool {
20932093
if (constraint->getKind() != ConstraintKind::BindOverload)
20942094
return false;
2095-
if (!constraint->getOverloadChoice().isDecl())
2096-
return false;
20972095

2098-
auto *decl = constraint->getOverloadChoice().getDecl();
2099-
auto *funcDecl = dyn_cast<FuncDecl>(decl);
2096+
auto *decl = constraint->getOverloadChoice().getDeclOrNull();
2097+
auto *funcDecl = dyn_cast_or_null<FuncDecl>(decl);
21002098
if (!funcDecl)
21012099
return false;
21022100

lib/Sema/ConstraintSystem.cpp

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,44 @@ ConstraintLocator *ConstraintSystem::getConstraintLocator(
411411
return getConstraintLocator(anchor, path, builder.getSummaryFlags());
412412
}
413413

414+
ConstraintLocator *ConstraintSystem::getCalleeLocator(Expr *expr) {
415+
if (auto *applyExpr = dyn_cast<ApplyExpr>(expr)) {
416+
auto *fnExpr = applyExpr->getFn();
417+
// For an apply of a metatype, we have a short-form constructor. Unlike
418+
// other locators to callees, these are anchored on the apply expression
419+
// rather than the function expr.
420+
if (simplifyType(getType(fnExpr))->is<AnyMetatypeType>()) {
421+
auto *fnLocator =
422+
getConstraintLocator(applyExpr, ConstraintLocator::ApplyFunction);
423+
return getConstraintLocator(fnLocator,
424+
ConstraintLocator::ConstructorMember);
425+
}
426+
// Otherwise fall through and look for locators anchored on the fn expr.
427+
expr = fnExpr;
428+
}
429+
430+
auto *locator = getConstraintLocator(expr);
431+
if (auto *ude = dyn_cast<UnresolvedDotExpr>(expr)) {
432+
if (TC.getSelfForInitDelegationInConstructor(DC, ude)) {
433+
return getConstraintLocator(locator,
434+
ConstraintLocator::ConstructorMember);
435+
} else {
436+
return getConstraintLocator(locator, ConstraintLocator::Member);
437+
}
438+
}
439+
440+
if (isa<UnresolvedMemberExpr>(expr))
441+
return getConstraintLocator(locator, ConstraintLocator::UnresolvedMember);
442+
443+
if (isa<SubscriptExpr>(expr))
444+
return getConstraintLocator(locator, ConstraintLocator::SubscriptMember);
445+
446+
if (isa<MemberRefExpr>(expr))
447+
return getConstraintLocator(locator, ConstraintLocator::Member);
448+
449+
return locator;
450+
}
451+
414452
Type ConstraintSystem::openUnboundGenericType(UnboundGenericType *unbound,
415453
ConstraintLocatorBuilder locator,
416454
OpenedTypeMap &replacements) {
@@ -2075,8 +2113,7 @@ void ConstraintSystem::resolveOverload(ConstraintLocator *locator,
20752113
}
20762114
assert(!refType->hasTypeParameter() && "Cannot have a dependent type here");
20772115

2078-
if (choice.isDecl()) {
2079-
auto decl = choice.getDecl();
2116+
if (auto *decl = choice.getDeclOrNull()) {
20802117
// If we're binding to an init member, the 'throws' need to line up between
20812118
// the bound and reference types.
20822119
if (auto CD = dyn_cast<ConstructorDecl>(decl)) {
@@ -2398,16 +2435,11 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes(
23982435
if (solutions.empty())
23992436
return false;
24002437

2401-
auto getOverloadDecl = [&](SelectedOverload &overload) -> ValueDecl * {
2402-
auto &choice = overload.choice;
2403-
return choice.isDecl() ? choice.getDecl() : nullptr;
2404-
};
2405-
24062438
// Problems related to fixes forming ambiguous solution set
24072439
// could only be diagnosed (at the moment), if all of the fixes
2408-
// are attached to the same anchor, which means they fix
2409-
// different overloads of the same declaration.
2410-
Expr *commonAnchor = nullptr;
2440+
// have the same callee locator, which means they fix different
2441+
// overloads of the same declaration.
2442+
ConstraintLocator *commonCalleeLocator = nullptr;
24112443
SmallPtrSet<ValueDecl *, 4> distinctChoices;
24122444
SmallVector<std::pair<const Solution *, const ConstraintFix *>, 4>
24132445
viableSolutions;
@@ -2421,21 +2453,17 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes(
24212453
return false;
24222454

24232455
const auto *fix = fixes.front();
2424-
if (commonAnchor && commonAnchor != fix->getAnchor())
2456+
auto *calleeLocator = getCalleeLocator(fix->getAnchor());
2457+
if (commonCalleeLocator && commonCalleeLocator != calleeLocator)
24252458
return false;
24262459

2427-
commonAnchor = fix->getAnchor();
2460+
commonCalleeLocator = calleeLocator;
24282461

2429-
SmallVector<SelectedOverload, 2> overloads;
2430-
solution.getOverloadChoices(commonAnchor, overloads);
2431-
// There is unfortunately no way, at the moment, to figure out
2432-
// what declaration the fix is attached to, so we have to make
2433-
// sure that there is only one declaration associated with common
2434-
// anchor to be sure that the right problem is being diagnosed.
2435-
if (overloads.size() != 1)
2462+
auto overload = solution.getOverloadChoiceIfAvailable(calleeLocator);
2463+
if (!overload)
24362464
return false;
24372465

2438-
auto *decl = getOverloadDecl(overloads.front());
2466+
auto *decl = overload->choice.getDeclOrNull();
24392467
if (!decl)
24402468
return false;
24412469

@@ -2458,6 +2486,7 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes(
24582486
DiagnosticTransaction transaction(TC.Diags);
24592487

24602488
const auto *fix = viableSolutions.front().second;
2489+
auto *commonAnchor = commonCalleeLocator->getAnchor();
24612490
if (fix->getKind() == FixKind::UseSubscriptOperator) {
24622491
auto *UDE = cast<UnresolvedDotExpr>(commonAnchor);
24632492
TC.diagnose(commonAnchor->getLoc(),

0 commit comments

Comments
 (0)