Skip to content

Commit bf61952

Browse files
authored
Merge pull request #25782 from xedin/callee-locator-logic-consolidation-5.1
[5.1][ConstraintSystem] Consolidate logic forming locators to callees
2 parents c039b4a + a0a4a5b commit bf61952

File tree

12 files changed

+115
-151
lines changed

12 files changed

+115
-151
lines changed

lib/Sema/CSApply.cpp

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4591,8 +4591,7 @@ namespace {
45914591
buildKeyPathPropertyComponent(const SelectedOverload &overload,
45924592
SourceLoc componentLoc,
45934593
ConstraintLocator *locator) {
4594-
if (overload.choice.isDecl()) {
4595-
auto property = overload.choice.getDecl();
4594+
if (auto *property = overload.choice.getDeclOrNull()) {
45964595
// Key paths can only refer to properties currently.
45974596
auto varDecl = cast<VarDecl>(property);
45984597
// Key paths don't work with mutating-get properties.
@@ -4909,10 +4908,8 @@ static ConcreteDeclRef resolveLocatorToDecl(
49094908
// Overloaded and unresolved cases: find the resolved overload.
49104909
auto anchorLocator = cs.getConstraintLocator(anchor);
49114910
if (auto selected = findOvlChoice(anchorLocator)) {
4912-
if (selected->choice.isDecl())
4913-
return getConcreteDeclRef(selected->choice.getDecl(),
4914-
selected->openedType,
4915-
anchorLocator);
4911+
if (auto *decl = selected->choice.getDeclOrNull())
4912+
return getConcreteDeclRef(decl, selected->openedType, anchorLocator);
49164913
}
49174914
}
49184915

@@ -4921,10 +4918,8 @@ static ConcreteDeclRef resolveLocatorToDecl(
49214918
auto anchorLocator = cs.getConstraintLocator(anchor,
49224919
ConstraintLocator::UnresolvedMember);
49234920
if (auto selected = findOvlChoice(anchorLocator)) {
4924-
if (selected->choice.isDecl())
4925-
return getConcreteDeclRef(selected->choice.getDecl(),
4926-
selected->openedType,
4927-
anchorLocator);
4921+
if (auto *decl = selected->choice.getDeclOrNull())
4922+
return getConcreteDeclRef(decl, selected->openedType, anchorLocator);
49284923
}
49294924
}
49304925

@@ -4933,10 +4928,8 @@ static ConcreteDeclRef resolveLocatorToDecl(
49334928
auto anchorLocator = cs.getConstraintLocator(anchor,
49344929
ConstraintLocator::Member);
49354930
if (auto selected = findOvlChoice(anchorLocator)) {
4936-
if (selected->choice.isDecl())
4937-
return getConcreteDeclRef(selected->choice.getDecl(),
4938-
selected->openedType,
4939-
anchorLocator);
4931+
if (auto *decl = selected->choice.getDeclOrNull())
4932+
return getConcreteDeclRef(decl, selected->openedType, anchorLocator);
49404933
}
49414934
}
49424935

@@ -4949,10 +4942,8 @@ static ConcreteDeclRef resolveLocatorToDecl(
49494942
auto anchorLocator =
49504943
cs.getConstraintLocator(anchor, ConstraintLocator::SubscriptMember);
49514944
if (auto selected = findOvlChoice(anchorLocator)) {
4952-
if (selected->choice.isDecl())
4953-
return getConcreteDeclRef(selected->choice.getDecl(),
4954-
selected->openedType,
4955-
anchorLocator);
4945+
if (auto *decl = selected->choice.getDeclOrNull())
4946+
return getConcreteDeclRef(decl, selected->openedType, anchorLocator);
49564947
}
49574948
}
49584949

lib/Sema/CSDiag.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -940,9 +940,8 @@ bool FailureDiagnosis::diagnoseGeneralOverloadFailure(Constraint *constraint) {
940940
if (constraint->getKind() == ConstraintKind::Disjunction) {
941941
for (auto elt : constraint->getNestedConstraints()) {
942942
if (elt->getKind() != ConstraintKind::BindOverload) continue;
943-
if (!elt->getOverloadChoice().isDecl()) continue;
944-
auto candidate = elt->getOverloadChoice().getDecl();
945-
diagnose(candidate, diag::found_candidate);
943+
if (auto *candidate = elt->getOverloadChoice().getDeclOrNull())
944+
diagnose(candidate, diag::found_candidate);
946945
}
947946
}
948947

lib/Sema/CSDiagnostics.cpp

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

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

137113
Type RequirementFailure::getOwnerType() const {
@@ -191,10 +167,6 @@ ProtocolConformance *RequirementFailure::getConformanceForConditionalReq(
191167

192168
ValueDecl *RequirementFailure::getDeclRef() const {
193169
auto &cs = getConstraintSystem();
194-
auto &TC = getTypeChecker();
195-
196-
auto *anchor = getRawAnchor();
197-
auto *locator = cs.getConstraintLocator(anchor);
198170

199171
// Get a declaration associated with given type (if any).
200172
// This is used to retrieve affected declaration when
@@ -216,38 +188,7 @@ ValueDecl *RequirementFailure::getDeclRef() const {
216188
if (isFromContextualType())
217189
return getAffectedDeclFromType(cs.getContextualType());
218190

219-
if (auto *AE = dyn_cast<CallExpr>(anchor)) {
220-
// NOTE: In valid code, the function can only be a TypeExpr
221-
assert(isa<TypeExpr>(AE->getFn()) ||
222-
isa<OverloadedDeclRefExpr>(AE->getFn()));
223-
ConstraintLocatorBuilder ctor(locator);
224-
locator = cs.getConstraintLocator(
225-
ctor.withPathElement(PathEltKind::ApplyFunction)
226-
.withPathElement(PathEltKind::ConstructorMember));
227-
} else if (auto *UDE = dyn_cast<UnresolvedDotExpr>(anchor)) {
228-
ConstraintLocatorBuilder member(locator);
229-
230-
if (TC.getSelfForInitDelegationInConstructor(getDC(), UDE)) {
231-
member = member.withPathElement(PathEltKind::ConstructorMember);
232-
} else {
233-
member = member.withPathElement(PathEltKind::Member);
234-
}
235-
236-
locator = cs.getConstraintLocator(member);
237-
} else if (auto *UME = dyn_cast<UnresolvedMemberExpr>(anchor)) {
238-
locator = cs.getConstraintLocator(locator, PathEltKind::UnresolvedMember);
239-
} else if (isa<SubscriptExpr>(anchor)) {
240-
ConstraintLocatorBuilder subscript(locator);
241-
locator = cs.getConstraintLocator(
242-
subscript.withPathElement(PathEltKind::SubscriptMember));
243-
} else if (isa<MemberRefExpr>(anchor)) {
244-
ConstraintLocatorBuilder memberRef(locator);
245-
locator =
246-
cs.getConstraintLocator(memberRef.withPathElement(PathEltKind::Member));
247-
}
248-
249-
auto overload = getOverloadChoiceIfAvailable(locator);
250-
if (overload)
191+
if (auto overload = getChoiceFor(getRawAnchor()))
251192
return overload->choice.getDecl();
252193

253194
return getAffectedDeclFromType(getOwnerType());
@@ -576,32 +517,7 @@ bool NoEscapeFuncToTypeConversionFailure::diagnoseParameterUse() const {
576517

577518
Type NoEscapeFuncToTypeConversionFailure::getParameterTypeFor(
578519
Expr *expr, unsigned paramIdx) const {
579-
auto &cs = getConstraintSystem();
580-
ConstraintLocator *locator = nullptr;
581-
582-
if (auto *call = dyn_cast<CallExpr>(expr)) {
583-
auto *fnExpr = call->getFn();
584-
if (isa<UnresolvedDotExpr>(fnExpr)) {
585-
locator = cs.getConstraintLocator(fnExpr, ConstraintLocator::Member);
586-
} else if (isa<UnresolvedMemberExpr>(fnExpr)) {
587-
locator =
588-
cs.getConstraintLocator(fnExpr, ConstraintLocator::UnresolvedMember);
589-
} else if (auto *TE = dyn_cast<TypeExpr>(fnExpr)) {
590-
locator = cs.getConstraintLocator(call,
591-
{ConstraintLocator::ApplyFunction,
592-
ConstraintLocator::ConstructorMember},
593-
/*summaryFlags=*/0);
594-
} else {
595-
locator = cs.getConstraintLocator(fnExpr);
596-
}
597-
} else if (auto *SE = dyn_cast<SubscriptExpr>(expr)) {
598-
locator = cs.getConstraintLocator(SE, ConstraintLocator::SubscriptMember);
599-
}
600-
601-
if (!locator)
602-
return Type();
603-
604-
auto choice = getOverloadChoiceIfAvailable(locator);
520+
auto choice = getChoiceFor(expr);
605521
if (!choice)
606522
return Type();
607523

lib/Sema/CSDiagnostics.h

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

159-
Optional<SelectedOverload> getChoiceFor(Expr *);
159+
Optional<SelectedOverload> getChoiceFor(Expr *) const;
160160

161161
private:
162162
/// 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
@@ -602,9 +602,9 @@ namespace {
602602
unsigned numFavoredConstraints = 0;
603603
Constraint *firstFavored = nullptr;
604604
for (auto constraint : disjunction->getNestedConstraints()) {
605-
if (!constraint->getOverloadChoice().isDecl())
605+
auto *decl = constraint->getOverloadChoice().getDeclOrNull();
606+
if (!decl)
606607
continue;
607-
auto decl = constraint->getOverloadChoice().getDecl();
608608

609609
if (mustConsider && mustConsider(decl)) {
610610
// Roll back any constraints we favored.

lib/Sema/CSSimplify.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -828,8 +828,7 @@ getCalleeDeclAndArgs(ConstraintSystem &cs,
828828
hasTrailingClosure, nullptr);
829829

830830
// If there's a declaration, return it.
831-
if (choice->isDecl()) {
832-
auto decl = choice->getDecl();
831+
if (auto *decl = choice->getDeclOrNull()) {
833832
bool hasCurriedSelf = false;
834833
if (decl->getDeclContext()->isTypeContext()) {
835834
if (auto function = dyn_cast<AbstractFunctionDecl>(decl)) {
@@ -4570,9 +4569,7 @@ fixMemberRef(ConstraintSystem &cs, Type baseTy,
45704569
Optional<MemberLookupResult::UnviableReason> reason = None) {
45714570
// Not all of the choices handled here are going
45724571
// to refer to a declaration.
4573-
if (choice.isDecl()) {
4574-
auto *decl = choice.getDecl();
4575-
4572+
if (auto *decl = choice.getDeclOrNull()) {
45764573
if (auto *CD = dyn_cast<ConstructorDecl>(decl)) {
45774574
if (auto *fix = validateInitializerRef(cs, CD, locator))
45784575
return fix;

lib/Sema/CSSolver.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2104,11 +2104,9 @@ void ConstraintSystem::partitionDisjunction(
21042104
forEachChoice(Choices, [&](unsigned index, Constraint *constraint) -> bool {
21052105
if (constraint->getKind() != ConstraintKind::BindOverload)
21062106
return false;
2107-
if (!constraint->getOverloadChoice().isDecl())
2108-
return false;
21092107

2110-
auto *decl = constraint->getOverloadChoice().getDecl();
2111-
auto *funcDecl = dyn_cast<FuncDecl>(decl);
2108+
auto *decl = constraint->getOverloadChoice().getDeclOrNull();
2109+
auto *funcDecl = dyn_cast_or_null<FuncDecl>(decl);
21122110
if (!funcDecl)
21132111
return false;
21142112

lib/Sema/ConstraintSystem.cpp

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,47 @@ ConstraintLocator *ConstraintSystem::getConstraintLocator(
408408
return getConstraintLocator(anchor, path, builder.getSummaryFlags());
409409
}
410410

411+
ConstraintLocator *ConstraintSystem::getCalleeLocator(Expr *expr) {
412+
// Make sure we handle subscripts before looking at apply exprs. We don't
413+
// want to return a subscript member locator for an expression such as x[](y),
414+
// as its callee is not the subscript, but rather the function it returns.
415+
if (isa<SubscriptExpr>(expr))
416+
return getConstraintLocator(expr, ConstraintLocator::SubscriptMember);
417+
418+
if (auto *applyExpr = dyn_cast<ApplyExpr>(expr)) {
419+
auto *fnExpr = applyExpr->getFn();
420+
// For an apply of a metatype, we have a short-form constructor. Unlike
421+
// other locators to callees, these are anchored on the apply expression
422+
// rather than the function expr.
423+
if (simplifyType(getType(fnExpr))->is<AnyMetatypeType>()) {
424+
auto *fnLocator =
425+
getConstraintLocator(applyExpr, ConstraintLocator::ApplyFunction);
426+
return getConstraintLocator(fnLocator,
427+
ConstraintLocator::ConstructorMember);
428+
}
429+
// Otherwise fall through and look for locators anchored on the fn expr.
430+
expr = fnExpr;
431+
}
432+
433+
auto *locator = getConstraintLocator(expr);
434+
if (auto *ude = dyn_cast<UnresolvedDotExpr>(expr)) {
435+
if (TC.getSelfForInitDelegationInConstructor(DC, ude)) {
436+
return getConstraintLocator(locator,
437+
ConstraintLocator::ConstructorMember);
438+
} else {
439+
return getConstraintLocator(locator, ConstraintLocator::Member);
440+
}
441+
}
442+
443+
if (isa<UnresolvedMemberExpr>(expr))
444+
return getConstraintLocator(locator, ConstraintLocator::UnresolvedMember);
445+
446+
if (isa<MemberRefExpr>(expr))
447+
return getConstraintLocator(locator, ConstraintLocator::Member);
448+
449+
return locator;
450+
}
451+
411452
Type ConstraintSystem::openUnboundGenericType(UnboundGenericType *unbound,
412453
ConstraintLocatorBuilder locator,
413454
OpenedTypeMap &replacements) {
@@ -2096,8 +2137,7 @@ void ConstraintSystem::resolveOverload(ConstraintLocator *locator,
20962137
}
20972138
assert(!refType->hasTypeParameter() && "Cannot have a dependent type here");
20982139

2099-
if (choice.isDecl()) {
2100-
auto decl = choice.getDecl();
2140+
if (auto *decl = choice.getDeclOrNull()) {
21012141
// If we're binding to an init member, the 'throws' need to line up between
21022142
// the bound and reference types.
21032143
if (auto CD = dyn_cast<ConstructorDecl>(decl)) {
@@ -2419,16 +2459,11 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes(
24192459
if (solutions.empty())
24202460
return false;
24212461

2422-
auto getOverloadDecl = [&](SelectedOverload &overload) -> ValueDecl * {
2423-
auto &choice = overload.choice;
2424-
return choice.isDecl() ? choice.getDecl() : nullptr;
2425-
};
2426-
24272462
// Problems related to fixes forming ambiguous solution set
24282463
// could only be diagnosed (at the moment), if all of the fixes
2429-
// are attached to the same anchor, which means they fix
2430-
// different overloads of the same declaration.
2431-
Expr *commonAnchor = nullptr;
2464+
// have the same callee locator, which means they fix different
2465+
// overloads of the same declaration.
2466+
ConstraintLocator *commonCalleeLocator = nullptr;
24322467
SmallPtrSet<ValueDecl *, 4> distinctChoices;
24332468
SmallVector<std::pair<const Solution *, const ConstraintFix *>, 4>
24342469
viableSolutions;
@@ -2442,21 +2477,17 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes(
24422477
return false;
24432478

24442479
const auto *fix = fixes.front();
2445-
if (commonAnchor && commonAnchor != fix->getAnchor())
2480+
auto *calleeLocator = getCalleeLocator(fix->getAnchor());
2481+
if (commonCalleeLocator && commonCalleeLocator != calleeLocator)
24462482
return false;
24472483

2448-
commonAnchor = fix->getAnchor();
2484+
commonCalleeLocator = calleeLocator;
24492485

2450-
SmallVector<SelectedOverload, 2> overloads;
2451-
solution.getOverloadChoices(commonAnchor, overloads);
2452-
// There is unfortunately no way, at the moment, to figure out
2453-
// what declaration the fix is attached to, so we have to make
2454-
// sure that there is only one declaration associated with common
2455-
// anchor to be sure that the right problem is being diagnosed.
2456-
if (overloads.size() != 1)
2486+
auto overload = solution.getOverloadChoiceIfAvailable(calleeLocator);
2487+
if (!overload)
24572488
return false;
24582489

2459-
auto *decl = getOverloadDecl(overloads.front());
2490+
auto *decl = overload->choice.getDeclOrNull();
24602491
if (!decl)
24612492
return false;
24622493

@@ -2479,6 +2510,7 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes(
24792510
DiagnosticTransaction transaction(TC.Diags);
24802511

24812512
const auto *fix = viableSolutions.front().second;
2513+
auto *commonAnchor = commonCalleeLocator->getAnchor();
24822514
if (fix->getKind() == FixKind::UseSubscriptOperator) {
24832515
auto *UDE = cast<UnresolvedDotExpr>(commonAnchor);
24842516
TC.diagnose(commonAnchor->getLoc(),

lib/Sema/ConstraintSystem.h

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -716,16 +716,6 @@ class Solution {
716716
return None;
717717
}
718718

719-
/// Retrieve overload choices associated with given expression.
720-
void getOverloadChoices(Expr *anchor,
721-
SmallVectorImpl<SelectedOverload> &overloads) const {
722-
for (auto &e : overloadChoices) {
723-
auto *locator = e.first;
724-
if (locator->getAnchor() == anchor)
725-
overloads.push_back(e.second);
726-
}
727-
}
728-
729719
LLVM_ATTRIBUTE_DEPRECATED(
730720
void dump() const LLVM_ATTRIBUTE_USED,
731721
"only for use within the debugger");
@@ -1927,6 +1917,11 @@ class ConstraintSystem {
19271917
return e != ExprWeights.end() ? e->second.second : nullptr;
19281918
}
19291919

1920+
/// Returns a locator describing the callee for a given expression. For
1921+
/// a function application, this is a locator describing the function expr.
1922+
/// For an unresolved dot/member, this is a locator to the member.
1923+
ConstraintLocator *getCalleeLocator(Expr *expr);
1924+
19301925
public:
19311926

19321927
/// Whether we should attempt to fix problems.

0 commit comments

Comments
 (0)