Skip to content

Commit c32e31c

Browse files
authored
[CS] Use a MapVector to cache resolved overloads (#28593)
[CS] Use a MapVector to cache resolved overloads
2 parents 31d567e + 40750c0 commit c32e31c

File tree

10 files changed

+110
-212
lines changed

10 files changed

+110
-212
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3414,15 +3414,13 @@ void FailureDiagnosis::diagnoseAmbiguity(Expr *E) {
34143414
/// If an UnresolvedDotExpr, SubscriptMember, etc has been resolved by the
34153415
/// constraint system, return the decl that it references.
34163416
ValueDecl *ConstraintSystem::findResolvedMemberRef(ConstraintLocator *locator) {
3417-
// Search through the resolvedOverloadSets to see if we have a resolution for
3418-
// this member. This is an O(n) search, but only happens when producing an
3419-
// error diagnostic.
3420-
auto *overload = findSelectedOverloadFor(locator);
3417+
// See if we have a resolution for this member.
3418+
auto overload = findSelectedOverloadFor(locator);
34213419
if (!overload)
34223420
return nullptr;
34233421

34243422
// We only want to handle the simplest decl binding.
3425-
auto choice = overload->Choice;
3423+
auto choice = overload->choice;
34263424
if (choice.getKind() != OverloadChoiceKind::Decl)
34273425
return nullptr;
34283426

lib/Sema/CSDiagnostics.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,8 +1099,8 @@ bool MemberAccessOnOptionalBaseFailure::diagnoseAsError() {
10991099
// type, then the result of the expression is optional (and we want to offer
11001100
// only a '?' fixit) even though the constraint system didn't need to add any
11011101
// additional optionality.
1102-
auto overload = getResolvedOverload(getLocator());
1103-
if (overload && overload->ImpliedType->getOptionalObjectType())
1102+
auto overload = getOverloadChoiceIfAvailable(getLocator());
1103+
if (overload && overload->openedType->getOptionalObjectType())
11041104
resultIsOptional = true;
11051105

11061106
auto unwrappedBaseType = baseType->getOptionalObjectType();
@@ -1417,12 +1417,12 @@ bool RValueTreatedAsLValueFailure::diagnoseAsError() {
14171417
}
14181418
}
14191419

1420-
if (auto resolvedOverload = getResolvedOverload(getLocator())) {
1421-
if (resolvedOverload->Choice.getKind() ==
1420+
if (auto resolvedOverload = getOverloadChoiceIfAvailable(getLocator())) {
1421+
if (resolvedOverload->choice.getKind() ==
14221422
OverloadChoiceKind::DynamicMemberLookup)
14231423
subElementDiagID = diag::assignment_dynamic_property_has_immutable_base;
14241424

1425-
if (resolvedOverload->Choice.getKind() ==
1425+
if (resolvedOverload->choice.getKind() ==
14261426
OverloadChoiceKind::KeyPathDynamicMemberLookup) {
14271427
if (!getType(member->getBase(), /*wantRValue=*/false)->hasLValueType())
14281428
subElementDiagID =
@@ -4163,7 +4163,7 @@ bool MissingArgumentsFailure::isMisplacedMissingArgument(
41634163
return false;
41644164

41654165
auto *fnType =
4166-
cs.simplifyType(overloadChoice->ImpliedType)->getAs<FunctionType>();
4166+
cs.simplifyType(overloadChoice->openedType)->getAs<FunctionType>();
41674167
if (!(fnType && fnType->getNumParams() == 2))
41684168
return false;
41694169

lib/Sema/CSDiagnostics.h

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -140,18 +140,10 @@ class FailureDiagnostic {
140140
return CS.findResolvedMemberRef(locator);
141141
}
142142

143+
/// Retrieve overload choice resolved for a given locator
144+
/// by the constraint solver.
143145
Optional<SelectedOverload>
144146
getOverloadChoiceIfAvailable(ConstraintLocator *locator) const {
145-
if (auto *overload = getResolvedOverload(locator))
146-
return Optional<SelectedOverload>(
147-
{overload->Choice, overload->OpenedFullType, overload->ImpliedType});
148-
return None;
149-
}
150-
151-
/// Retrieve overload choice resolved for given locator
152-
/// by the constraint solver.
153-
ResolvedOverloadSetListItem *
154-
getResolvedOverload(ConstraintLocator *locator) const {
155147
return CS.findSelectedOverloadFor(locator);
156148
}
157149

lib/Sema/CSSimplify.cpp

Lines changed: 27 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -803,8 +803,6 @@ getCalleeDeclAndArgs(ConstraintSystem &cs,
803803
auto calleeLocator = cs.getCalleeLocator(callLocator);
804804

805805
// Find the overload choice corresponding to the callee locator.
806-
// FIXME: This linearly walks the list of resolved overloads, which is
807-
// potentially very expensive.
808806
auto selectedOverload = cs.findSelectedOverloadFor(calleeLocator);
809807

810808
// If we didn't find any matching overloads, we're done. Just return the
@@ -815,7 +813,7 @@ getCalleeDeclAndArgs(ConstraintSystem &cs,
815813
/*calleeLocator*/ nullptr);
816814

817815
// Return the found declaration, assuming there is one.
818-
auto choice = selectedOverload->Choice;
816+
auto choice = selectedOverload->choice;
819817
return std::make_tuple(choice.getDeclOrNull(), hasAppliedSelf(cs, choice),
820818
argLabels, hasTrailingClosure, calleeLocator);
821819
}
@@ -1385,9 +1383,9 @@ assessRequirementFailureImpact(ConstraintSystem &cs, Type requirementType,
13851383
return 1;
13861384

13871385
unsigned choiceImpact = 0;
1388-
if (auto *choice = cs.findSelectedOverloadFor(ODRE)) {
1386+
if (auto choice = cs.findSelectedOverloadFor(ODRE)) {
13891387
auto *typeVar = requirementType->castTo<TypeVariableType>();
1390-
choice->ImpliedType.visit([&](Type type) {
1388+
choice->openedType.visit([&](Type type) {
13911389
if (type->isEqual(typeVar))
13921390
++choiceImpact;
13931391
});
@@ -2450,8 +2448,7 @@ static ConstraintFix *fixRequirementFailure(ConstraintSystem &cs, Type type1,
24502448

24512449
static ConstraintFix *fixPropertyWrapperFailure(
24522450
ConstraintSystem &cs, Type baseTy, ConstraintLocator *locator,
2453-
llvm::function_ref<bool(ResolvedOverloadSetListItem *, VarDecl *, Type)>
2454-
attemptFix,
2451+
llvm::function_ref<bool(SelectedOverload, VarDecl *, Type)> attemptFix,
24552452
Optional<Type> toType = None) {
24562453

24572454
Expr *baseExpr = nullptr;
@@ -2486,7 +2483,7 @@ static ConstraintFix *fixPropertyWrapperFailure(
24862483
if (baseTy->isEqual(type))
24872484
return nullptr;
24882485

2489-
if (!attemptFix(resolvedOverload, decl, type))
2486+
if (!attemptFix(*resolvedOverload, decl, type))
24902487
return nullptr;
24912488

24922489
switch (fix) {
@@ -2503,20 +2500,21 @@ static ConstraintFix *fixPropertyWrapperFailure(
25032500
llvm_unreachable("Unhandled Fix type in switch");
25042501
};
25052502

2506-
if (auto storageWrapper = cs.getStorageWrapperInformation(resolvedOverload)) {
2503+
if (auto storageWrapper =
2504+
cs.getStorageWrapperInformation(*resolvedOverload)) {
25072505
if (auto *fix = applyFix(Fix::StorageWrapper, storageWrapper->first,
25082506
storageWrapper->second))
25092507
return fix;
25102508
}
25112509

2512-
if (auto wrapper = cs.getPropertyWrapperInformation(resolvedOverload)) {
2510+
if (auto wrapper = cs.getPropertyWrapperInformation(*resolvedOverload)) {
25132511
if (auto *fix =
25142512
applyFix(Fix::PropertyWrapper, wrapper->first, wrapper->second))
25152513
return fix;
25162514
}
25172515

25182516
if (auto wrappedProperty =
2519-
cs.getWrappedPropertyInformation(resolvedOverload)) {
2517+
cs.getWrappedPropertyInformation(*resolvedOverload)) {
25202518
if (auto *fix = applyFix(Fix::WrappedValue, wrappedProperty->first,
25212519
wrappedProperty->second))
25222520
return fix;
@@ -2561,8 +2559,8 @@ repairViaBridgingCast(ConstraintSystem &cs, Type fromType, Type toType,
25612559
if (!anchor)
25622560
return false;
25632561

2564-
if (auto *overload = cs.findSelectedOverloadFor(anchor)) {
2565-
auto *decl = overload->Choice.getDeclOrNull();
2562+
if (auto overload = cs.findSelectedOverloadFor(anchor)) {
2563+
auto *decl = overload->choice.getDeclOrNull();
25662564
if (decl && decl->isImplicitlyUnwrappedOptional())
25672565
fromType = objectType1;
25682566
}
@@ -2703,11 +2701,11 @@ bool ConstraintSystem::repairFailures(
27032701
if (!anchor)
27042702
return false;
27052703

2706-
auto *overload = findSelectedOverloadFor(anchor);
2707-
if (!(overload && overload->Choice.isDecl()))
2704+
auto overload = findSelectedOverloadFor(anchor);
2705+
if (!(overload && overload->choice.isDecl()))
27082706
return false;
27092707

2710-
const auto &choice = overload->Choice;
2708+
const auto &choice = overload->choice;
27112709
ParameterListInfo info(fnType->getParams(), choice.getDecl(),
27122710
hasAppliedSelf(*this, choice));
27132711

@@ -3093,8 +3091,7 @@ bool ConstraintSystem::repairFailures(
30933091

30943092
if (auto *fix = fixPropertyWrapperFailure(
30953093
*this, lhs, loc,
3096-
[&](ResolvedOverloadSetListItem *overload, VarDecl *decl,
3097-
Type newBase) {
3094+
[&](SelectedOverload overload, VarDecl *decl, Type newBase) {
30983095
// FIXME: There is currently no easy way to avoid attempting
30993096
// fixes, matchTypes do not propagate `TMF_ApplyingFix` flag.
31003097
llvm::SaveAndRestore<ConstraintSystemOptions> options(
@@ -5317,8 +5314,8 @@ static bool isSelfRecursiveKeyPathDynamicMemberLookup(
53175314
auto *choiceLoc =
53185315
cs.getConstraintLocator(locator->getAnchor(), path.drop_back());
53195316

5320-
if (auto *overload = cs.findSelectedOverloadFor(choiceLoc)) {
5321-
auto baseTy = overload->Choice.getBaseType();
5317+
if (auto overload = cs.findSelectedOverloadFor(choiceLoc)) {
5318+
auto baseTy = overload->choice.getBaseType();
53225319

53235320
// If it's `Foo<Int>` vs. `Foo<String>` it doesn't really matter
53245321
// for dynamic lookup because it's going to be performed on `Foo`.
@@ -6268,16 +6265,9 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
62686265
if (auto dotExpr =
62696266
dyn_cast_or_null<UnresolvedDotExpr>(locator->getAnchor())) {
62706267
auto baseExpr = dotExpr->getBase();
6271-
auto resolvedOverload = getResolvedOverloadSets();
6272-
while (resolvedOverload) {
6273-
if (resolvedOverload->Locator->getAnchor() == baseExpr) {
6274-
if (resolvedOverload->Choice
6275-
.isImplicitlyUnwrappedValueOrReturnValue())
6276-
return SolutionKind::Error;
6277-
break;
6278-
}
6279-
resolvedOverload = resolvedOverload->Previous;
6280-
}
6268+
if (auto overload = findSelectedOverloadFor(baseExpr))
6269+
if (overload->choice.isImplicitlyUnwrappedValueOrReturnValue())
6270+
return SolutionKind::Error;
62816271
}
62826272

62836273
// Let's check whether the problem is related to optionality of base
@@ -6337,8 +6327,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
63376327
// properties that have matching members.
63386328
if (auto *fix = fixPropertyWrapperFailure(
63396329
*this, baseTy, locator,
6340-
[&](ResolvedOverloadSetListItem *overload, VarDecl *decl,
6341-
Type newBase) {
6330+
[&](SelectedOverload overload, VarDecl *decl, Type newBase) {
63426331
return solveWithNewBaseOrName(newBase, member) ==
63436332
SolutionKind::Solved;
63446333
})) {
@@ -6915,30 +6904,6 @@ ConstraintSystem::simplifyKeyPathConstraint(
69156904
return SolutionKind::Error;
69166905
}
69176906

6918-
// First gather the callee locators for the individual components.
6919-
SmallVector<std::pair<ConstraintLocator *, OverloadChoice>, 4> choices;
6920-
for (unsigned i : indices(keyPath->getComponents())) {
6921-
auto *componentLoc = getConstraintLocator(
6922-
locator.withPathElement(LocatorPathElt::KeyPathComponent(i)));
6923-
auto *calleeLoc = getCalleeLocator(componentLoc);
6924-
choices.push_back({calleeLoc, OverloadChoice()});
6925-
}
6926-
6927-
// Then search for the resolved overloads.
6928-
for (auto resolvedItem = resolvedOverloadSets; resolvedItem;
6929-
resolvedItem = resolvedItem->Previous) {
6930-
auto locator = resolvedItem->Locator;
6931-
auto kpElt = locator->getFirstElementAs<LocatorPathElt::KeyPathComponent>();
6932-
if (!kpElt || locator->getAnchor() != keyPath)
6933-
continue;
6934-
6935-
auto &choice = choices[kpElt->getIndex()];
6936-
if (choice.first == locator) {
6937-
assert(choice.second.isInvalid() && "Resolved same component twice?");
6938-
choice.second = resolvedItem->Choice;
6939-
}
6940-
}
6941-
69426907
// See if we resolved overloads for all the components involved.
69436908
enum {
69446909
ReadOnly,
@@ -6960,15 +6925,17 @@ ConstraintSystem::simplifyKeyPathConstraint(
69606925
case KeyPathExpr::Component::Kind::Subscript:
69616926
case KeyPathExpr::Component::Kind::UnresolvedProperty:
69626927
case KeyPathExpr::Component::Kind::UnresolvedSubscript: {
6963-
auto *calleeLoc = choices[i].first;
6964-
auto choice = choices[i].second;
6928+
auto *componentLoc = getConstraintLocator(
6929+
locator.withPathElement(LocatorPathElt::KeyPathComponent(i)));
6930+
auto *calleeLoc = getCalleeLocator(componentLoc);
6931+
auto overload = findSelectedOverloadFor(calleeLoc);
69656932

69666933
// If no choice was made, leave the constraint unsolved. But when
69676934
// generating constraints, we may already have enough information
69686935
// to determine whether the result will be a function type vs BGT KeyPath
69696936
// type, so continue through components to create new constraint at the
69706937
// end.
6971-
if (choice.isInvalid() || anyComponentsUnresolved) {
6938+
if (!overload || anyComponentsUnresolved) {
69726939
if (flags.contains(TMF_GenerateConstraints)) {
69736940
anyComponentsUnresolved = true;
69746941
continue;
@@ -7000,6 +6967,7 @@ ConstraintSystem::simplifyKeyPathConstraint(
70006967
}
70016968

70026969
// tuple elements do not change the capability of the key path
6970+
auto choice = overload->choice;
70036971
if (choice.getKind() == OverloadChoiceKind::TupleIndex) {
70046972
continue;
70056973
}

lib/Sema/CSSolver.cpp

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,9 @@ Solution ConstraintSystem::finalize() {
101101
solution.typeBindings[tv] = simplifyType(tv)->reconstituteSugar(false);
102102
}
103103

104-
// For each of the overload sets, get its overload choice.
105-
for (auto resolved = resolvedOverloadSets;
106-
resolved; resolved = resolved->Previous) {
107-
solution.overloadChoices[resolved->Locator]
108-
= { resolved->Choice, resolved->OpenedFullType, resolved->ImpliedType };
109-
}
104+
// Copy over the resolved overloads.
105+
solution.overloadChoices.insert(ResolvedOverloads.begin(),
106+
ResolvedOverloads.end());
110107

111108
// For each of the constraint restrictions, record it with simplified,
112109
// canonical types.
@@ -203,15 +200,8 @@ void ConstraintSystem::applySolution(const Solution &solution) {
203200

204201
// Register overload choices.
205202
// FIXME: Copy these directly into some kind of partial solution?
206-
for (auto overload : solution.overloadChoices) {
207-
resolvedOverloadSets
208-
= new (*this) ResolvedOverloadSetListItem{resolvedOverloadSets,
209-
Type(),
210-
overload.second.choice,
211-
overload.first,
212-
overload.second.openedFullType,
213-
overload.second.openedType};
214-
}
203+
for (auto overload : solution.overloadChoices)
204+
ResolvedOverloads.insert(overload);
215205

216206
// Register constraint restrictions.
217207
// FIXME: Copy these directly into some kind of partial solution?
@@ -433,7 +423,6 @@ ConstraintSystem::SolverState::~SolverState() {
433423
ConstraintSystem::SolverScope::SolverScope(ConstraintSystem &cs)
434424
: cs(cs), CGScope(cs.CG)
435425
{
436-
resolvedOverloadSets = cs.resolvedOverloadSets;
437426
numTypeVariables = cs.TypeVariables.size();
438427
numSavedBindings = cs.solverState->savedBindings.size();
439428
numConstraintRestrictions = cs.ConstraintRestrictions.size();
@@ -448,6 +437,7 @@ ConstraintSystem::SolverScope::SolverScope(ConstraintSystem &cs)
448437
numDisabledConstraints = cs.solverState->getNumDisabledConstraints();
449438
numFavoredConstraints = cs.solverState->getNumFavoredConstraints();
450439
numBuilderTransformedClosures = cs.builderTransformedClosures.size();
440+
numResolvedOverloads = cs.ResolvedOverloads.size();
451441

452442
PreviousScore = cs.CurrentScore;
453443

@@ -457,10 +447,12 @@ ConstraintSystem::SolverScope::SolverScope(ConstraintSystem &cs)
457447

458448
ConstraintSystem::SolverScope::~SolverScope() {
459449
// Erase the end of various lists.
460-
cs.resolvedOverloadSets = resolvedOverloadSets;
461450
while (cs.TypeVariables.size() > numTypeVariables)
462451
cs.TypeVariables.pop_back();
463452

453+
while (cs.ResolvedOverloads.size() > numResolvedOverloads)
454+
cs.ResolvedOverloads.pop_back();
455+
464456
// Restore bindings.
465457
cs.restoreTypeVariableBindings(cs.solverState->savedBindings.size() -
466458
numSavedBindings);

lib/Sema/CSStep.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,9 @@ class SolverStep {
213213
CS.CG.addConstraint(constraint);
214214
}
215215

216-
ResolvedOverloadSetListItem *getResolvedOverloads() const {
217-
return CS.resolvedOverloadSets;
216+
const llvm::MapVector<ConstraintLocator *, SelectedOverload> &
217+
getResolvedOverloads() const {
218+
return CS.ResolvedOverloads;
218219
}
219220

220221
void recordDisjunctionChoice(ConstraintLocator *disjunctionLocator,
@@ -710,12 +711,12 @@ class DisjunctionStep final : public BindingStep<DisjunctionChoiceProducer> {
710711
if (!repr || repr == typeVar)
711712
return;
712713

713-
for (auto *resolved = getResolvedOverloads(); resolved;
714-
resolved = resolved->Previous) {
715-
if (!resolved->BoundType->isEqual(repr))
714+
for (auto elt : getResolvedOverloads()) {
715+
auto resolved = elt.second;
716+
if (!resolved.boundType->isEqual(repr))
716717
continue;
717718

718-
auto &representative = resolved->Choice;
719+
auto &representative = resolved.choice;
719720
if (!representative.isDecl())
720721
return;
721722

0 commit comments

Comments
 (0)