Skip to content

Commit 2b42671

Browse files
authored
[CS] Use custom locator element for callAsFunction (swiftlang#28854)
[CS] Use custom locator element for callAsFunction
2 parents ddcb1d5 + 40d1171 commit 2b42671

File tree

5 files changed

+61
-56
lines changed

5 files changed

+61
-56
lines changed

lib/Sema/CSApply.cpp

Lines changed: 43 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,7 +1057,7 @@ namespace {
10571057
}
10581058
}
10591059

1060-
return finishApply(apply, memberRef, openedType, locator);
1060+
return finishApply(apply, openedType, locator, memberLocator);
10611061
}
10621062

10631063
/// Convert the given literal expression via a protocol pair.
@@ -1113,15 +1113,16 @@ namespace {
11131113
/// \param apply The function application to finish type-checking, which
11141114
/// may be a newly-built expression.
11151115
///
1116-
/// \param callee The callee for the function being applied.
1117-
///
11181116
/// \param openedType The "opened" type this expression had during
11191117
/// type checking, which will be used to specialize the resulting,
11201118
/// type-checked expression appropriately.
11211119
///
11221120
/// \param locator The locator for the original expression.
1123-
Expr *finishApply(ApplyExpr *apply, ConcreteDeclRef callee, Type openedType,
1124-
ConstraintLocatorBuilder locator);
1121+
///
1122+
/// \param calleeLocator The locator that identifies the apply's callee.
1123+
Expr *finishApply(ApplyExpr *apply, Type openedType,
1124+
ConstraintLocatorBuilder locator,
1125+
ConstraintLocatorBuilder calleeLocator);
11251126

11261127
// Resolve `@dynamicCallable` applications.
11271128
Expr *finishApplyDynamicCallable(ApplyExpr *apply,
@@ -2390,17 +2391,16 @@ namespace {
23902391

23912392
// If there was an argument, apply it.
23922393
if (auto arg = expr->getArgument()) {
2393-
// Find the callee. Note this may be different to the member being
2394-
// referenced for things like callAsFunction.
2394+
// Get the callee locator. Note this may be different to the locator for
2395+
// the member being referenced for things like callAsFunction.
23952396
auto *calleeLoc = cs.getCalleeLocator(exprLoc);
2396-
auto calleeOverload = solution.getOverloadChoice(calleeLoc);
2397-
auto callee = resolveConcreteDeclRef(calleeOverload.choice.getDecl(),
2398-
calleeLoc);
2397+
2398+
// Build and finish the apply.
23992399
ApplyExpr *apply = CallExpr::create(
24002400
ctx, result, arg, expr->getArgumentLabels(),
24012401
expr->getArgumentLabelLocs(), expr->hasTrailingClosure(),
24022402
/*implicit=*/expr->isImplicit(), Type(), getType);
2403-
result = finishApply(apply, callee, Type(), exprLoc);
2403+
result = finishApply(apply, Type(), exprLoc, calleeLoc);
24042404

24052405
// FIXME: Application could fail, because some of the solutions
24062406
// are not expressible in AST (yet?), like certain tuple-to-tuple
@@ -2579,9 +2579,8 @@ namespace {
25792579
auto *call = new (cs.getASTContext()) DotSyntaxCallExpr(ctorRef, dotLoc,
25802580
base);
25812581

2582-
return finishApply(call, callee, cs.getType(expr),
2583-
ConstraintLocatorBuilder(
2584-
cs.getConstraintLocator(expr)));
2582+
return finishApply(call, cs.getType(expr), cs.getConstraintLocator(expr),
2583+
ctorLocator);
25852584
}
25862585

25872586
Expr *applyMemberRefExpr(Expr *expr, Expr *base, SourceLoc dotLoc,
@@ -3027,17 +3026,8 @@ namespace {
30273026
Expr *visitApplyExpr(ApplyExpr *expr) {
30283027
auto *calleeLoc = CalleeLocators[expr];
30293028
assert(calleeLoc);
3030-
3031-
// Resolve the callee for the application if we have one. Note that we're
3032-
// using `resolveConcreteDeclRef` instead `solution.resolveLocatorToDecl`
3033-
// here to benefit from ExprRewriter's cache of concrete refs.
3034-
ConcreteDeclRef callee;
3035-
if (auto overload = solution.getOverloadChoiceIfAvailable(calleeLoc)) {
3036-
auto *decl = overload->choice.getDeclOrNull();
3037-
callee = resolveConcreteDeclRef(decl, calleeLoc);
3038-
}
3039-
return finishApply(expr, callee, cs.getType(expr),
3040-
cs.getConstraintLocator(expr));
3029+
return finishApply(expr, cs.getType(expr), cs.getConstraintLocator(expr),
3030+
calleeLoc);
30413031
}
30423032

30433033
Expr *visitRebindSelfInConstructorExpr(RebindSelfInConstructorExpr *expr) {
@@ -6465,13 +6455,15 @@ static bool isValidDynamicCallableMethod(FuncDecl *method,
64656455
// Build a reference to a `callAsFunction` method.
64666456
static Expr *buildCallAsFunctionMethodRef(
64676457
ExprRewriter &rewriter, ApplyExpr *apply, SelectedOverload selected,
6468-
ConstraintLocatorBuilder applyFunctionLoc) {
6469-
auto *fn = apply->getFn();
6458+
ConstraintLocator *calleeLoc) {
6459+
assert(calleeLoc->isLastElement<LocatorPathElt::ImplicitCallAsFunction>());
6460+
assert(cast<FuncDecl>(selected.choice.getDecl())->isCallAsFunctionMethod());
6461+
64706462
// Create direct reference to `callAsFunction` method.
6463+
auto *fn = apply->getFn();
64716464
auto *declRef = rewriter.buildMemberRef(
64726465
fn, /*dotLoc*/ SourceLoc(), selected, DeclNameLoc(fn->getEndLoc()),
6473-
applyFunctionLoc, applyFunctionLoc, /*implicit*/ true,
6474-
AccessSemantics::Ordinary);
6466+
calleeLoc, calleeLoc, /*implicit*/ true, AccessSemantics::Ordinary);
64756467
if (!declRef)
64766468
return nullptr;
64776469
declRef->setImplicit(apply->isImplicit());
@@ -6559,9 +6551,9 @@ ExprRewriter::finishApplyDynamicCallable(ApplyExpr *apply,
65596551
return result;
65606552
}
65616553

6562-
Expr *ExprRewriter::finishApply(ApplyExpr *apply, ConcreteDeclRef callee,
6563-
Type openedType,
6564-
ConstraintLocatorBuilder locator) {
6554+
Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
6555+
ConstraintLocatorBuilder locator,
6556+
ConstraintLocatorBuilder calleeLocator) {
65656557
auto &ctx = cs.getASTContext();
65666558

65676559
auto fn = apply->getFn();
@@ -6705,7 +6697,24 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, ConcreteDeclRef callee,
67056697
llvm_unreachable("Unhandled DeclTypeCheckingSemantics in switch.");
67066698
};
67076699

6708-
// Resolve `callAsFunction` and `@dynamicCallable` applications.
6700+
// Resolve the callee for the application if we have one.
6701+
ConcreteDeclRef callee;
6702+
auto *calleeLoc = cs.getConstraintLocator(calleeLocator);
6703+
auto overload = solution.getOverloadChoiceIfAvailable(calleeLoc);
6704+
if (overload) {
6705+
auto *decl = overload->choice.getDeclOrNull();
6706+
callee = resolveConcreteDeclRef(decl, calleeLoc);
6707+
}
6708+
6709+
// If this is an implicit call to a `callAsFunction` method, build the
6710+
// appropriate member reference.
6711+
if (cs.getType(fn)->getRValueType()->isCallableNominalType(dc)) {
6712+
fn = buildCallAsFunctionMethodRef(*this, apply, *overload, calleeLoc);
6713+
if (!fn)
6714+
return nullptr;
6715+
}
6716+
6717+
// Resolve a `@dynamicCallable` application.
67096718
auto applyFunctionLoc =
67106719
locator.withPathElement(ConstraintLocator::ApplyFunction);
67116720
if (auto selected = solution.getOverloadChoiceIfAvailable(
@@ -6718,15 +6727,6 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, ConcreteDeclRef callee,
67186727
if (isValidDynamicCallableMethod(method, methodType))
67196728
return finishApplyDynamicCallable(
67206729
apply, *selected, method, methodType, applyFunctionLoc);
6721-
6722-
// If this is an implicit call to a callAsFunction method, build the
6723-
// appropriate member reference.
6724-
if (method->isCallAsFunctionMethod()) {
6725-
fn = buildCallAsFunctionMethodRef(*this, apply, *selected,
6726-
applyFunctionLoc);
6727-
if (!fn)
6728-
return nullptr;
6729-
}
67306730
}
67316731
}
67326732

@@ -6854,12 +6854,8 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, ConcreteDeclRef callee,
68546854
assert(ty->getNominalOrBoundGenericNominal() || ty->is<DynamicSelfType>() ||
68556855
ty->isExistentialType() || ty->is<ArchetypeType>());
68566856

6857-
// We have the constructor.
6858-
auto choice = selected->choice;
6859-
68606857
// Consider the constructor decl reference expr 'implicit', but the
68616858
// constructor call expr itself has the apply's 'implicitness'.
6862-
auto ctorRef = resolveConcreteDeclRef(choice.getDecl(), ctorLocator);
68636859
Expr *declRef = buildMemberRef(fn, /*dotLoc=*/SourceLoc(), *selected,
68646860
DeclNameLoc(fn->getEndLoc()), locator,
68656861
ctorLocator, /*Implicit=*/true,
@@ -6870,7 +6866,7 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, ConcreteDeclRef callee,
68706866
apply->setFn(declRef);
68716867

68726868
// Tail-recur to actually call the constructor.
6873-
return finishApply(apply, ctorRef, openedType, locator);
6869+
return finishApply(apply, openedType, locator, ctorLocator);
68746870
}
68756871

68766872
// Return the precedence-yielding parent of 'expr', along with the index of

lib/Sema/CSSimplify.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7391,18 +7391,16 @@ ConstraintSystem::simplifyApplicableFnConstraint(
73917391
// is true.
73927392
if (desugar2->isCallableNominalType(DC)) {
73937393
auto memberLoc = getConstraintLocator(
7394-
outerLocator.withPathElement(ConstraintLocator::Member));
7394+
locator.withPathElement(ConstraintLocator::ImplicitCallAsFunction));
73957395
// Add a `callAsFunction` member constraint, binding the member type to a
73967396
// type variable.
73977397
auto memberTy = createTypeVariable(memberLoc, /*options=*/0);
73987398
// TODO: Revisit this if `static func callAsFunction` is to be supported.
73997399
// Static member constraint requires `FunctionRefKind::DoubleApply`.
7400-
// TODO: Use a custom locator element to identify this member constraint
7401-
// instead of just pointing to the function expr.
74027400
addValueMemberConstraint(origLValueType2,
74037401
DeclNameRef(ctx.Id_callAsFunction),
74047402
memberTy, DC, FunctionRefKind::SingleApply,
7405-
/*outerAlternatives*/ {}, locator);
7403+
/*outerAlternatives*/ {}, memberLoc);
74067404
// Add new applicable function constraint based on the member type
74077405
// variable.
74087406
addConstraint(ConstraintKind::ApplicableFunction, func1, memberTy,

lib/Sema/ConstraintLocator.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ unsigned LocatorPathElt::getNewSummaryFlags() const {
114114
case ConstraintLocator::KeyPathComponentResult:
115115
case ConstraintLocator::Condition:
116116
case ConstraintLocator::DynamicCallable:
117+
case ConstraintLocator::ImplicitCallAsFunction:
117118
return 0;
118119

119120
case ConstraintLocator::FunctionArgument:
@@ -458,6 +459,10 @@ void ConstraintLocator::dump(SourceManager *sm, raw_ostream &out) const {
458459
case DynamicCallable:
459460
out << "implicit call to @dynamicCallable method";
460461
break;
462+
463+
case ImplicitCallAsFunction:
464+
out << "implicit reference to callAsFunction";
465+
break;
461466
}
462467
}
463468
out << ']';

lib/Sema/ConstraintLocatorPathElts.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ SIMPLE_LOCATOR_PATH_ELT(FunctionResult)
7676
/// FIXME: Add support for named generic arguments?
7777
CUSTOM_LOCATOR_PATH_ELT(GenericArgument)
7878

79+
/// An implicit reference to a 'callAsFunction' method of a nominal type.
80+
SIMPLE_LOCATOR_PATH_ELT(ImplicitCallAsFunction)
81+
7982
/// Locator for a binding from an IUO disjunction choice.
8083
SIMPLE_LOCATOR_PATH_ELT(ImplicitlyUnwrappedDisjunctionChoice)
8184

lib/Sema/ConstraintSystem.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -506,9 +506,11 @@ ConstraintSystem::getCalleeLocator(ConstraintLocator *locator,
506506
}
507507

508508
// Handle an apply of a nominal type which supports callAsFunction.
509-
if (fnTy->isCallableNominalType(DC))
510-
return getConstraintLocator(anchor, ConstraintLocator::ApplyFunction);
511-
509+
if (fnTy->isCallableNominalType(DC)) {
510+
return getConstraintLocator(anchor,
511+
{LocatorPathElt::ApplyFunction(),
512+
LocatorPathElt::ImplicitCallAsFunction()});
513+
}
512514
return nullptr;
513515
};
514516

@@ -3145,8 +3147,9 @@ void constraints::simplifyLocator(Expr *&anchor,
31453147
case ConstraintLocator::LValueConversion:
31463148
case ConstraintLocator::RValueAdjustment:
31473149
case ConstraintLocator::UnresolvedMember:
3148-
// Arguments in autoclosure positions, lvalue and rvalue adjustments, and
3149-
// scalar-to-tuple conversions, and unresolved members are
3150+
case ConstraintLocator::ImplicitCallAsFunction:
3151+
// Arguments in autoclosure positions, lvalue and rvalue adjustments,
3152+
// unresolved members, and implicit callAsFunction references are
31503153
// implicit.
31513154
path = path.slice(1);
31523155
continue;

0 commit comments

Comments
 (0)