Skip to content

Commit 3b03d45

Browse files
authored
Merge pull request #3759 from DougGregor/arg-labels-in-exprs
Store argument labels + locations in directly in call and call-like expressions
2 parents a62ff70 + dad1557 commit 3b03d45

File tree

11 files changed

+883
-226
lines changed

11 files changed

+883
-226
lines changed

include/swift/AST/Expr.h

Lines changed: 342 additions & 55 deletions
Large diffs are not rendered by default.

lib/AST/ASTDumper.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2093,6 +2093,12 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
20932093
OS << " super";
20942094
if (E->isThrowsSet())
20952095
OS << (E->throws() ? " throws" : " nothrow");
2096+
if (auto call = dyn_cast<CallExpr>(E)) {
2097+
OS << " arg_labels=";
2098+
for (auto label : call->getArgumentLabels())
2099+
OS << (label.empty() ? "_" : label.str()) << ":";
2100+
}
2101+
20962102
OS << '\n';
20972103
printRec(E->getFn());
20982104
OS << '\n';

lib/AST/Expr.cpp

Lines changed: 454 additions & 97 deletions
Large diffs are not rendered by default.

lib/Parse/ParseExpr.cpp

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -845,7 +845,8 @@ ParserResult<Expr> Parser::parseExprSuper() {
845845
return makeParserCodeCompletionResult<Expr>();
846846
if (idx.isNull())
847847
return nullptr;
848-
return makeParserResult(new (Context) SubscriptExpr(superRef, idx.get()));
848+
return makeParserResult(
849+
SubscriptExpr::create(Context, superRef, idx.get()));
849850
}
850851

851852
if (Tok.is(tok::code_complete)) {
@@ -1231,10 +1232,9 @@ ParserResult<Expr> Parser::parseExprPostfix(Diag<> ID, bool isExprBasic) {
12311232
DeclNameLoc NameLoc;
12321233

12331234
if (Tok.is(tok::code_complete)) {
1234-
auto Expr = new (Context) UnresolvedMemberExpr(
1235-
DotLoc,
1236-
DeclNameLoc(DotLoc.getAdvancedLoc(1)),
1237-
Context.getIdentifier("_"), nullptr);
1235+
auto Expr = UnresolvedMemberExpr::create(
1236+
Context, DotLoc, DeclNameLoc(DotLoc.getAdvancedLoc(1)),
1237+
Context.getIdentifier("_"), /*implicit=*/false);
12381238
Result = makeParserResult(Expr);
12391239
if (CodeCompletion) {
12401240
std::vector<StringRef> Identifiers;
@@ -1279,8 +1279,9 @@ ParserResult<Expr> Parser::parseExprPostfix(Diag<> ID, bool isExprBasic) {
12791279

12801280
// Handle .foo by just making an AST node.
12811281
Result = makeParserResult(
1282-
new (Context) UnresolvedMemberExpr(DotLoc, NameLoc, Name,
1283-
Arg.getPtrOrNull()));
1282+
UnresolvedMemberExpr::create(Context, DotLoc, NameLoc, Name,
1283+
Arg.getPtrOrNull(),
1284+
/*implicit=*/false));
12841285
break;
12851286
}
12861287

@@ -1529,7 +1530,7 @@ ParserResult<Expr> Parser::parseExprPostfix(Diag<> ID, bool isExprBasic) {
15291530
if (Idx.isNull() || Result.isNull())
15301531
return nullptr;
15311532
Result = makeParserResult(
1532-
new (Context) SubscriptExpr(Result.get(), Idx.get()));
1533+
SubscriptExpr::create(Context, Result.get(), Idx.get()));
15331534
continue;
15341535
}
15351536

@@ -1557,12 +1558,14 @@ ParserResult<Expr> Parser::parseExprPostfix(Diag<> ID, bool isExprBasic) {
15571558
if (auto call = dyn_cast<CallExpr>(Result.get())) {
15581559
// When a closure follows a call, it becomes the last argument of
15591560
// that call.
1561+
// FIXME: Wasteful to allocate another CallExpr here. Delay the
1562+
// allocation.
15601563
Expr *arg = addTrailingClosureToArgument(Context, call->getArg(),
15611564
closure.get());
1562-
call->setArg(arg);
1563-
1564-
if (closure.hasCodeCompletion())
1565-
Result.setHasCodeCompletion();
1565+
Result = makeParserResult(
1566+
ParserStatus(closure),
1567+
CallExpr::create(Context, call->getFn(), arg,
1568+
call->isImplicit()));
15661569
} else {
15671570
// Otherwise, the closure implicitly forms a call.
15681571
Expr *arg = createArgWithTrailingClosure(Context, SourceLoc(), { },
@@ -2643,8 +2646,8 @@ Parser::parseExprObjectLiteral(ObjectLiteralExpr::LiteralKind LitKind,
26432646
}
26442647

26452648
return makeParserResult(
2646-
new (Context) ObjectLiteralExpr(PoundLoc, LitKind, Arg.get(),
2647-
/*implicit=*/false));
2649+
ObjectLiteralExpr::create(Context, PoundLoc, LitKind, Arg.get(),
2650+
/*implicit=*/false));
26482651
}
26492652

26502653
/// \brief Parse an expression call suffix.

lib/Sema/CSApply.cpp

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,13 +1180,16 @@ namespace {
11801180
/// the call. Otherwise, a specific level describing which parameter level
11811181
/// we're applying.
11821182
/// \param argLabels The argument labels provided for the call.
1183+
/// \param hasTrailingClosure Whether the last argument is a trailing
1184+
/// closure.
11831185
/// \param locator Locator used to describe where in this expression we are.
11841186
///
11851187
/// \returns the coerced expression, which will have type \c ToType.
11861188
Expr *
11871189
coerceCallArguments(Expr *arg, Type paramType,
11881190
llvm::PointerUnion<ApplyExpr *, LevelTy> applyOrLevel,
11891191
ArrayRef<Identifier> argLabels,
1192+
bool hasTrailingClosure,
11901193
ConstraintLocatorBuilder locator);
11911194

11921195
/// \brief Coerce the given object argument (e.g., for the base of a
@@ -1215,6 +1218,7 @@ namespace {
12151218
/// \param isImplicit Whether this is an implicit subscript.
12161219
Expr *buildSubscript(Expr *base, Expr *index,
12171220
ArrayRef<Identifier> argLabels,
1221+
bool hasTrailingClosure,
12181222
ConstraintLocatorBuilder locator,
12191223
bool isImplicit, AccessSemantics semantics) {
12201224
// Determine the declaration selected for this subscript operation.
@@ -1259,6 +1263,7 @@ namespace {
12591263
// Coerce the index argument.
12601264
index = coerceCallArguments(
12611265
index, indexTy, LevelTy(1), argLabels,
1266+
hasTrailingClosure,
12621267
locator.withPathElement(ConstraintLocator::SubscriptIndex));
12631268
if (!index)
12641269
return nullptr;
@@ -1274,11 +1279,10 @@ namespace {
12741279
return nullptr;
12751280

12761281
// TODO: diagnose if semantics != AccessSemantics::Ordinary?
1277-
auto subscriptExpr = new (tc.Context) DynamicSubscriptExpr(base,
1278-
index,
1279-
subscript);
1282+
auto subscriptExpr = DynamicSubscriptExpr::create(tc.Context, base,
1283+
index, subscript,
1284+
isImplicit);
12801285
subscriptExpr->setType(resultTy);
1281-
subscriptExpr->setImplicit(isImplicit);
12821286
Expr *result = subscriptExpr;
12831287
closeExistential(result);
12841288
return result;
@@ -1310,12 +1314,11 @@ namespace {
13101314

13111315
// Form the generic subscript expression.
13121316
auto subscriptExpr
1313-
= new (tc.Context) SubscriptExpr(base, index,
1314-
ConcreteDeclRef(tc.Context,
1315-
subscript,
1316-
substitutions),
1317-
isImplicit,
1318-
semantics);
1317+
= SubscriptExpr::create(tc.Context, base, index,
1318+
ConcreteDeclRef(tc.Context, subscript,
1319+
substitutions),
1320+
isImplicit,
1321+
semantics);
13191322
subscriptExpr->setType(resultTy);
13201323
subscriptExpr->setIsSuper(isSuper);
13211324

@@ -1337,8 +1340,8 @@ namespace {
13371340

13381341
// Form a normal subscript.
13391342
auto *subscriptExpr
1340-
= new (tc.Context) SubscriptExpr(base, index, subscript,
1341-
isImplicit, semantics);
1343+
= SubscriptExpr::create(tc.Context, base, index, subscript,
1344+
isImplicit, semantics);
13421345
subscriptExpr->setType(resultTy);
13431346
subscriptExpr->setIsSuper(isSuper);
13441347
Expr *result = subscriptExpr;
@@ -2603,9 +2606,9 @@ namespace {
26032606
}
26042607

26052608
Expr *visitSubscriptExpr(SubscriptExpr *expr) {
2606-
SmallVector<Identifier, 2> argLabelsScratch;
26072609
return buildSubscript(expr->getBase(), expr->getIndex(),
2608-
expr->getArgumentLabels(argLabelsScratch),
2610+
expr->getArgumentLabels(),
2611+
expr->hasTrailingClosure(),
26092612
cs.getConstraintLocator(expr),
26102613
expr->isImplicit(),
26112614
expr->getAccessSemantics());
@@ -2747,9 +2750,9 @@ namespace {
27472750
}
27482751

27492752
Expr *visitDynamicSubscriptExpr(DynamicSubscriptExpr *expr) {
2750-
SmallVector<Identifier, 2> argLabelsScratch;
27512753
return buildSubscript(expr->getBase(), expr->getIndex(),
2752-
expr->getArgumentLabels(argLabelsScratch),
2754+
expr->getArgumentLabels(),
2755+
expr->hasTrailingClosure(),
27532756
cs.getConstraintLocator(expr),
27542757
expr->isImplicit(), AccessSemantics::Ordinary);
27552758
}
@@ -4638,6 +4641,7 @@ Expr *ExprRewriter::coerceCallArguments(
46384641
Expr *arg, Type paramType,
46394642
llvm::PointerUnion<ApplyExpr *, LevelTy> applyOrLevel,
46404643
ArrayRef<Identifier> argLabels,
4644+
bool hasTrailingClosure,
46414645
ConstraintLocatorBuilder locator) {
46424646

46434647
bool allParamsMatch = arg->getType()->isEqual(paramType);
@@ -4704,7 +4708,7 @@ Expr *ExprRewriter::coerceCallArguments(
47044708

47054709
SmallVector<ParamBinding, 4> parameterBindings;
47064710
bool failed = constraints::matchCallArguments(args, params,
4707-
hasTrailingClosure(locator),
4711+
hasTrailingClosure,
47084712
/*allowFixes=*/false, listener,
47094713
parameterBindings);
47104714
assert(!failed && "Call arguments did not match up?");
@@ -5922,9 +5926,12 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
59225926
SmallVector<Identifier, 2> argLabelsScratch;
59235927
if (auto fnType = fn->getType()->getAs<FunctionType>()) {
59245928
auto origArg = apply->getArg();
5929+
bool hasTrailingClosure =
5930+
isa<CallExpr>(apply) && cast<CallExpr>(apply)->hasTrailingClosure();
59255931
Expr *arg = coerceCallArguments(origArg, fnType->getInput(),
59265932
apply,
59275933
apply->getArgumentLabels(argLabelsScratch),
5934+
hasTrailingClosure,
59285935
locator.withPathElement(
59295936
ConstraintLocator::ApplyArgument));
59305937
if (!arg) {

lib/Sema/CSDiag.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4577,8 +4577,7 @@ bool FailureDiagnosis::visitSubscriptExpr(SubscriptExpr *SE) {
45774577
for (unsigned i = 0, e = calleeInfo.size(); i != e; ++i)
45784578
--calleeInfo.candidates[i].level;
45794579

4580-
SmallVector<Identifier, 2> argLabelsScratch;
4581-
ArrayRef<Identifier> argLabels = SE->getArgumentLabels(argLabelsScratch);
4580+
ArrayRef<Identifier> argLabels = SE->getArgumentLabels();
45824581
if (diagnoseParameterErrors(calleeInfo, SE, indexExpr, argLabels))
45834582
return true;
45844583

lib/Sema/CSSimplify.cpp

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -469,45 +469,53 @@ matchCallArguments(ArrayRef<CallArgParam> args,
469469

470470
/// Find the callee declaration and uncurry level for a given call
471471
/// locator.
472-
static std::tuple<ValueDecl *, unsigned, ArrayRef<Identifier>>
472+
static std::tuple<ValueDecl *, unsigned, ArrayRef<Identifier>, bool>
473473
getCalleeDeclAndArgs(ConstraintSystem &cs,
474474
ConstraintLocatorBuilder callLocator,
475475
SmallVectorImpl<Identifier> &argLabelsScratch) {
476476
ArrayRef<Identifier> argLabels;
477+
bool hasTrailingClosure = false;
477478

478-
// If the call locator is not just a call expression, there's
479-
// nothing to do.
479+
// Break down the call.
480480
SmallVector<LocatorPathElt, 2> path;
481481
auto callExpr = callLocator.getLocatorParts(path);
482-
if (!callExpr) return std::make_tuple(nullptr, 0, argLabels);
482+
if (!callExpr)
483+
return std::make_tuple(nullptr, 0, argLabels, hasTrailingClosure);
483484

484485
// Our remaining path can only be 'ApplyArgument' or 'SubscriptIndex'.
485486
if (!path.empty() &&
486487
!(path.size() == 1 &&
487488
(path.back().getKind() == ConstraintLocator::ApplyArgument ||
488489
path.back().getKind() == ConstraintLocator::SubscriptIndex)))
489-
return std::make_tuple(nullptr, 0, argLabels);
490+
return std::make_tuple(nullptr, 0, argLabels, hasTrailingClosure);
490491

491492
// Dig out the callee.
492493
Expr *calleeExpr;
493494
if (auto call = dyn_cast<CallExpr>(callExpr)) {
494495
calleeExpr = call->getDirectCallee();
495-
argLabels = call->getArgumentLabels(argLabelsScratch);
496+
argLabels = call->getArgumentLabels();
497+
hasTrailingClosure = call->hasTrailingClosure();
496498
} else if (auto unresolved = dyn_cast<UnresolvedMemberExpr>(callExpr)) {
497499
calleeExpr = callExpr;
498-
argLabels = unresolved->getArgumentLabels(argLabelsScratch);
500+
argLabels = unresolved->getArgumentLabels();
501+
hasTrailingClosure = unresolved->hasTrailingClosure();
499502
} else if (auto subscript = dyn_cast<SubscriptExpr>(callExpr)) {
500503
calleeExpr = callExpr;
501-
argLabels = subscript->getArgumentLabels(argLabelsScratch);
504+
argLabels = subscript->getArgumentLabels();
505+
hasTrailingClosure = subscript->hasTrailingClosure();
502506
} else if (auto dynSubscript = dyn_cast<DynamicSubscriptExpr>(callExpr)) {
503507
calleeExpr = callExpr;
504-
argLabels = dynSubscript->getArgumentLabels(argLabelsScratch);
508+
argLabels = dynSubscript->getArgumentLabels();
509+
hasTrailingClosure = dynSubscript->hasTrailingClosure();
505510
} else {
506-
if (auto apply = dyn_cast<ApplyExpr>(callExpr))
511+
if (auto apply = dyn_cast<ApplyExpr>(callExpr)) {
507512
argLabels = apply->getArgumentLabels(argLabelsScratch);
508-
else if (auto objectLiteral = dyn_cast<ObjectLiteralExpr>(callExpr))
509-
argLabels = objectLiteral->getArgumentLabels(argLabelsScratch);
510-
return std::make_tuple(nullptr, 0, argLabels);
513+
assert(!apply->hasTrailingClosure());
514+
} else if (auto objectLiteral = dyn_cast<ObjectLiteralExpr>(callExpr)) {
515+
argLabels = objectLiteral->getArgumentLabels();
516+
hasTrailingClosure = objectLiteral->hasTrailingClosure();
517+
}
518+
return std::make_tuple(nullptr, 0, argLabels, hasTrailingClosure);
511519
}
512520

513521
// Determine the target locator.
@@ -551,7 +559,8 @@ getCalleeDeclAndArgs(ConstraintSystem &cs,
551559
}
552560

553561
// If we didn't find any matching overloads, we're done.
554-
if (!choice) return std::make_tuple(nullptr, 0, argLabels);
562+
if (!choice)
563+
return std::make_tuple(nullptr, 0, argLabels, hasTrailingClosure);
555564

556565
// If there's a declaration, return it.
557566
if (choice->isDecl()) {
@@ -570,10 +579,10 @@ getCalleeDeclAndArgs(ConstraintSystem &cs,
570579
}
571580
}
572581

573-
return std::make_tuple(decl, level, argLabels);
582+
return std::make_tuple(decl, level, argLabels, hasTrailingClosure);
574583
}
575584

576-
return std::make_tuple(nullptr, 0, argLabels);
585+
return std::make_tuple(nullptr, 0, argLabels, hasTrailingClosure);
577586
}
578587

579588
// Match the argument of a call to the parameter.
@@ -604,7 +613,8 @@ matchCallArguments(ConstraintSystem &cs, TypeMatchKind kind,
604613
unsigned calleeLevel;
605614
ArrayRef<Identifier> argLabels;
606615
SmallVector<Identifier, 2> argLabelsScratch;
607-
std::tie(callee, calleeLevel, argLabels) =
616+
bool hasTrailingClosure = false;
617+
std::tie(callee, calleeLevel, argLabels, hasTrailingClosure) =
608618
getCalleeDeclAndArgs(cs, locator, argLabelsScratch);
609619
auto params = decomposeParamType(paramType, callee, calleeLevel);
610620

@@ -614,8 +624,7 @@ matchCallArguments(ConstraintSystem &cs, TypeMatchKind kind,
614624
// Match up the call arguments to the parameters.
615625
MatchCallArgumentListener listener;
616626
SmallVector<ParamBinding, 4> parameterBindings;
617-
if (constraints::matchCallArguments(args, params,
618-
hasTrailingClosure(locator),
627+
if (constraints::matchCallArguments(args, params, hasTrailingClosure,
619628
cs.shouldAttemptFixes(), listener,
620629
parameterBindings))
621630
return ConstraintSystem::SolutionKind::Error;

lib/Sema/CodeSynthesis.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -354,9 +354,11 @@ static Expr *buildArgumentForwardingExpr(ArrayRef<ParamDecl*> params,
354354
labelLocs.push_back(SourceLoc());
355355
}
356356

357-
// A single unlabelled value is not a tuple.
358-
if (args.size() == 1 && labels[0].empty())
359-
return args[0];
357+
// A single unlabeled value is not a tuple.
358+
if (args.size() == 1 && labels[0].empty()) {
359+
return new (ctx) ParenExpr(SourceLoc(), args[0], SourceLoc(),
360+
/*hasTrailingClosure=*/false);
361+
}
360362

361363
return TupleExpr::create(ctx, SourceLoc(), args, labels, labelLocs,
362364
SourceLoc(), false, IsImplicit);
@@ -477,8 +479,8 @@ static Expr *buildStorageReference(
477479

478480
if (auto subscript = dyn_cast<SubscriptDecl>(storage)) {
479481
Expr *indices = referenceContext.getIndexRefExpr(ctx, subscript);
480-
return new (ctx) SubscriptExpr(selfDRE, indices, storage,
481-
IsImplicit, semantics);
482+
return SubscriptExpr::create(ctx, selfDRE, indices, storage,
483+
IsImplicit, semantics);
482484
}
483485

484486
// This is a potentially polymorphic access, which is unnecessary;

lib/Sema/ConstraintSystem.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2129,11 +2129,6 @@ static inline bool computeTupleShuffle(TupleType *fromTuple,
21292129
sources, variadicArgs);
21302130
}
21312131

2132-
2133-
/// \brief Return whether the function argument indicated by `locator` has a
2134-
/// trailing closure.
2135-
bool hasTrailingClosure(const ConstraintLocatorBuilder &locator);
2136-
21372132
/// Describes the arguments to which a parameter binds.
21382133
/// FIXME: This is an awful data structure. We want the equivalent of a
21392134
/// TinyPtrVector for unsigned values.

lib/Sema/PlaygroundTransform.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1009,8 +1009,11 @@ class Instrumenter {
10091009

10101010
LoggerRef->setImplicit(true);
10111011

1012+
SmallVector<Identifier, 4> ArgLabels(ArgsWithSourceRange.size(),
1013+
Identifier());
10121014
ApplyExpr *LoggerCall = CallExpr::createImplicit(Context, LoggerRef,
1013-
ArgsWithSourceRange, { });
1015+
ArgsWithSourceRange,
1016+
ArgLabels);
10141017
Added<ApplyExpr*> AddedLogger(LoggerCall);
10151018

10161019
if (!doTypeCheck(Context, TypeCheckDC, AddedLogger)) {

0 commit comments

Comments
 (0)