Skip to content

Commit a5e375a

Browse files
committed
Cache resolved concrete decl refs in ExprRewriter
This ensures we don't have to compute the substitutions multiple times when, for example, rewriting an apply of generic function.
1 parent 9d80a82 commit a5e375a

File tree

2 files changed

+40
-20
lines changed

2 files changed

+40
-20
lines changed

lib/Sema/CSApply.cpp

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,13 @@ static bool isOpenedAnyObject(Type type) {
5858
return archetype->getOpenedExistentialType()->isAnyObject();
5959
}
6060

61-
SubstitutionMap Solution::computeSubstitutions(
62-
GenericSignature sig,
63-
ConstraintLocatorBuilder locatorBuilder) const {
61+
SubstitutionMap
62+
Solution::computeSubstitutions(GenericSignature sig,
63+
ConstraintLocator *locator) const {
6464
if (sig.isNull())
6565
return SubstitutionMap();
6666

6767
// Gather the substitutions from dependent types to concrete types.
68-
auto locator = getConstraintSystem().getConstraintLocator(locatorBuilder);
6968
auto openedTypes = OpenedTypes.find(locator);
7069

7170
// If we have a member reference on an existential, there are no
@@ -98,7 +97,7 @@ SubstitutionMap Solution::computeSubstitutions(
9897

9998
ConcreteDeclRef
10099
Solution::resolveConcreteDeclRef(ValueDecl *decl,
101-
ConstraintLocatorBuilder locator) const {
100+
ConstraintLocator *locator) const {
102101
if (!decl)
103102
return ConcreteDeclRef();
104103

@@ -501,7 +500,7 @@ namespace {
501500
return typeExpr;
502501
}
503502

504-
auto ref = solution.resolveConcreteDeclRef(decl, locator);
503+
auto ref = resolveConcreteDeclRef(decl, locator);
505504
auto declRefExpr =
506505
new (ctx) DeclRefExpr(ref, loc, implicit, semantics, type);
507506
cs.cacheType(declRefExpr);
@@ -539,6 +538,24 @@ namespace {
539538
/// will no longer be equivalent to the one stored in the solution.
540539
llvm::DenseMap<ApplyExpr *, ConstraintLocator *> CalleeLocators;
541540

541+
/// A cache of decl references with their contextual substitutions for a
542+
/// given callee locator.
543+
llvm::DenseMap<ConstraintLocator *, ConcreteDeclRef> CachedConcreteRefs;
544+
545+
ConcreteDeclRef
546+
resolveConcreteDeclRef(ValueDecl *decl, ConstraintLocatorBuilder locator) {
547+
if (!decl)
548+
return ConcreteDeclRef();
549+
550+
auto *loc = getConstraintSystem().getConstraintLocator(locator);
551+
auto &ref = CachedConcreteRefs[loc];
552+
if (!ref)
553+
ref = solution.resolveConcreteDeclRef(decl, loc);
554+
555+
assert(ref.getDecl() == decl);
556+
return ref;
557+
}
558+
542559
/// Members which are AbstractFunctionDecls but not FuncDecls cannot
543560
/// mutate self.
544561
bool isNonMutatingMember(ValueDecl *member) {
@@ -763,7 +780,7 @@ namespace {
763780
}
764781

765782
// Build a member reference.
766-
auto memberRef = solution.resolveConcreteDeclRef(member, memberLocator);
783+
auto memberRef = resolveConcreteDeclRef(member, memberLocator);
767784
auto refTy = solution.simplifyType(openedFullType);
768785

769786
// If we're referring to the member of a module, it's just a simple
@@ -1381,7 +1398,7 @@ namespace {
13811398
}
13821399

13831400
// Compute the concrete reference to the subscript.
1384-
auto subscriptRef = solution.resolveConcreteDeclRef(subscript, memberLoc);
1401+
auto subscriptRef = resolveConcreteDeclRef(subscript, memberLoc);
13851402

13861403
// Figure out the index and result types.
13871404
Type resultTy;
@@ -2412,8 +2429,8 @@ namespace {
24122429

24132430
// If there was an argument, apply it.
24142431
if (auto arg = expr->getArgument()) {
2415-
auto callee = solution.resolveConcreteDeclRef(selected.choice.getDecl(),
2416-
memberLocator);
2432+
auto callee = resolveConcreteDeclRef(selected.choice.getDecl(),
2433+
memberLocator);
24172434
ApplyExpr *apply = CallExpr::create(
24182435
tc.Context, result, arg, expr->getArgumentLabels(),
24192436
expr->getArgumentLabelLocs(), expr->hasTrailingClosure(),
@@ -2593,7 +2610,7 @@ namespace {
25932610
}
25942611

25952612
// Build a partial application of the delegated initializer.
2596-
auto callee = solution.resolveConcreteDeclRef(ctor, ctorLocator);
2613+
auto callee = resolveConcreteDeclRef(ctor, ctorLocator);
25972614
Expr *ctorRef = buildOtherConstructorRef(openedType, callee, base,
25982615
nameLoc, ctorLocator, implicit);
25992616
auto *call = new (cs.getASTContext()) DotSyntaxCallExpr(ctorRef, dotLoc,
@@ -3028,7 +3045,11 @@ namespace {
30283045
assert(calleeLoc);
30293046

30303047
// Resolve the callee for the application if we have one.
3031-
auto callee = solution.resolveLocatorToDecl(calleeLoc);
3048+
ConcreteDeclRef callee;
3049+
if (auto overload = solution.getOverloadChoiceIfAvailable(calleeLoc)) {
3050+
auto *decl = overload->choice.getDeclOrNull();
3051+
callee = resolveConcreteDeclRef(decl, calleeLoc);
3052+
}
30323053
return finishApply(expr, callee, cs.getType(expr),
30333054
cs.getConstraintLocator(expr));
30343055
}
@@ -4535,7 +4556,7 @@ namespace {
45354556
resolvedTy = simplifyType(resolvedTy);
45364557

45374558
// Compute the concrete reference to the member.
4538-
auto ref = solution.resolveConcreteDeclRef(property, locator);
4559+
auto ref = resolveConcreteDeclRef(property, locator);
45394560
return KeyPathExpr::Component::forProperty(ref, resolvedTy,
45404561
componentLoc);
45414562
}
@@ -4562,7 +4583,7 @@ namespace {
45624583
/*canonicalVararg=*/false);
45634584

45644585
// Compute substitutions to refer to the member.
4565-
auto ref = solution.resolveConcreteDeclRef(subscript, locator);
4586+
auto ref = resolveConcreteDeclRef(subscript, locator);
45664587
indexType = indexType.subst(ref.getSubstitutions());
45674588

45684589
// If this is a @dynamicMemberLookup reference to resolve a property
@@ -6686,8 +6707,8 @@ static Expr *finishApplyCallAsFunctionMethod(
66866707
declRef->setImplicit(apply->isImplicit());
66876708
apply->setFn(declRef);
66886709
// Coerce argument to input type of the `callAsFunction` method.
6689-
auto callee = rewriter.solution.resolveConcreteDeclRef(choice.getDecl(),
6690-
applyFunctionLoc);
6710+
auto callee = rewriter.resolveConcreteDeclRef(choice.getDecl(),
6711+
applyFunctionLoc);
66916712
SmallVector<Identifier, 2> argLabelsScratch;
66926713
auto *arg = rewriter.coerceCallArguments(
66936714
apply->getArg(), openedMethodType, callee, apply,
@@ -7081,7 +7102,7 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, ConcreteDeclRef callee,
70817102
// Consider the constructor decl reference expr 'implicit', but the
70827103
// constructor call expr itself has the apply's 'implicitness'.
70837104
bool isDynamic = choice.getKind() == OverloadChoiceKind::DeclViaDynamic;
7084-
auto ctorRef = solution.resolveConcreteDeclRef(choice.getDecl(), ctorLocator);
7105+
auto ctorRef = resolveConcreteDeclRef(choice.getDecl(), ctorLocator);
70857106
Expr *declRef = buildMemberRef(fn, selected->openedFullType,
70867107
/*dotLoc=*/SourceLoc(), choice,
70877108
DeclNameLoc(fn->getEndLoc()),

lib/Sema/ConstraintSystem.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -697,13 +697,12 @@ class Solution {
697697
/// \param locator The locator that describes where the substitutions came
698698
/// from.
699699
SubstitutionMap computeSubstitutions(GenericSignature sig,
700-
ConstraintLocatorBuilder locator) const;
700+
ConstraintLocator *locator) const;
701701

702702
/// Resolves the contextual substitutions for a reference to a declaration
703703
/// at a given locator.
704704
ConcreteDeclRef
705-
resolveConcreteDeclRef(ValueDecl *decl,
706-
ConstraintLocatorBuilder locator) const;
705+
resolveConcreteDeclRef(ValueDecl *decl, ConstraintLocator *locator) const;
707706

708707
/// Return the disjunction choice for the given constraint location.
709708
unsigned getDisjunctionChoice(ConstraintLocator *locator) const {

0 commit comments

Comments
 (0)