Skip to content

Commit e212d45

Browse files
committed
Sema: Collect varargs into an ArrayExpr and use DefaultArgumentExpr
Instead of building ArgumentShuffleExprs, lets just build a TupleExpr, with explicit representation of collected varargs and default arguments. This isn't quite as elegant as it should be, because when re-typechecking, SanitizeExpr needs to restore the 'old' parameter list by stripping out the nodes inserted by type checking. However that hackery is all isolated in one place and will go away soon. Note that there's a minor change the generated SIL. Caller default arguments (#file, #line, etc) are no longer delayed and are instead evaluated in their usual argument position. I don't believe this actually results in an observable change in behavior, but if it turns out to be a problem, we can pretty easily change it back to the old behavior with a bit of extra work.
1 parent 27801ce commit e212d45

20 files changed

+626
-399
lines changed

include/swift/AST/Expr.h

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4021,7 +4021,7 @@ class DynamicTypeExpr : public Expr {
40214021
/// Opaque value expressions occur when a particular value within the AST
40224022
/// needs to be re-used without being re-evaluated or for a value that is
40234023
/// a placeholder. OpaqueValueExpr nodes are introduced by some other AST
4024-
/// node (say, a \c DynamicMemberRefExpr) and can only be used within the
4024+
/// node (say, an \c OpenExistentialExpr) and can only be used within the
40254025
/// subexpressions of that AST node.
40264026
class OpaqueValueExpr : public Expr {
40274027
SourceLoc Loc;
@@ -4037,6 +4037,82 @@ class OpaqueValueExpr : public Expr {
40374037
}
40384038
};
40394039

4040+
/// An expression referring to a default argument left unspecified at the
4041+
/// call site.
4042+
///
4043+
/// A DefaultArgumentExpr must only appear as a direct child of a
4044+
/// ParenExpr or a TupleExpr that is itself a call argument.
4045+
class DefaultArgumentExpr final : public Expr {
4046+
/// The owning declaration.
4047+
ConcreteDeclRef DefaultArgsOwner;
4048+
4049+
/// The caller parameter index.
4050+
unsigned ParamIndex;
4051+
4052+
/// The source location of the argument list.
4053+
SourceLoc Loc;
4054+
4055+
public:
4056+
explicit DefaultArgumentExpr(ConcreteDeclRef defaultArgsOwner, unsigned paramIndex,
4057+
SourceLoc loc, Type Ty)
4058+
: Expr(ExprKind::DefaultArgument, /*Implicit=*/true, Ty),
4059+
DefaultArgsOwner(defaultArgsOwner), ParamIndex(paramIndex), Loc(loc) { }
4060+
4061+
SourceRange getSourceRange() const {
4062+
return Loc;
4063+
}
4064+
4065+
ConcreteDeclRef getDefaultArgsOwner() const {
4066+
return DefaultArgsOwner;
4067+
}
4068+
4069+
unsigned getParamIndex() const {
4070+
return ParamIndex;
4071+
}
4072+
4073+
static bool classof(const Expr *E) {
4074+
return E->getKind() == ExprKind::DefaultArgument;
4075+
}
4076+
};
4077+
4078+
/// An expression referring to a caller-side default argument left unspecified
4079+
/// at the call site.
4080+
///
4081+
/// A CallerDefaultArgumentExpr must only appear as a direct child of a
4082+
/// ParenExpr or a TupleExpr that is itself a call argument.
4083+
///
4084+
/// FIXME: This only exists to distinguish caller default arguments from arguments
4085+
/// that were specified at the call site. Once we remove SanitizeExpr, we can remove
4086+
/// this hack too.
4087+
class CallerDefaultArgumentExpr final : public Expr {
4088+
/// The expression that is evaluated to produce the default argument value.
4089+
Expr *SubExpr;
4090+
4091+
/// The source location of the argument list.
4092+
SourceLoc Loc;
4093+
4094+
public:
4095+
explicit CallerDefaultArgumentExpr(Expr *subExpr, SourceLoc loc, Type Ty)
4096+
: Expr(ExprKind::CallerDefaultArgument, /*Implicit=*/true, Ty),
4097+
SubExpr(subExpr), Loc(loc) { }
4098+
4099+
SourceRange getSourceRange() const {
4100+
return Loc;
4101+
}
4102+
4103+
Expr *getSubExpr() const {
4104+
return SubExpr;
4105+
}
4106+
4107+
void setSubExpr(Expr *subExpr) {
4108+
SubExpr = subExpr;
4109+
}
4110+
4111+
static bool classof(const Expr *E) {
4112+
return E->getKind() == ExprKind::CallerDefaultArgument;
4113+
}
4114+
};
4115+
40404116
/// ApplyExpr - Superclass of various function calls, which apply an argument to
40414117
/// a function to get a result.
40424118
class ApplyExpr : public Expr {
@@ -4112,7 +4188,7 @@ class ApplyExpr : public Expr {
41124188
E->getKind() <= ExprKind::Last_ApplyExpr;
41134189
}
41144190
};
4115-
4191+
41164192
/// CallExpr - Application of an argument to a function, which occurs
41174193
/// syntactically through juxtaposition with a TupleExpr whose
41184194
/// leading '(' is unspaced.

include/swift/AST/ExprNodes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ EXPR(VarargExpansion, Expr)
126126
EXPR(DynamicType, Expr)
127127
EXPR(RebindSelfInConstructor, Expr)
128128
EXPR(OpaqueValue, Expr)
129+
EXPR(DefaultArgument, Expr)
130+
EXPR(CallerDefaultArgument, Expr)
129131
EXPR(BindOptional, Expr)
130132
EXPR(OptionalEvaluation, Expr)
131133
EXPR(ForceValue, Expr)

include/swift/Sema/IDETypeChecking.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,25 @@ namespace swift {
202202
/// the decl context.
203203
bool resolveProtocolNames(DeclContext *DC, ArrayRef<const char *> names,
204204
llvm::MapVector<ProtocolDecl*, StringRef> &result);
205+
206+
/// FIXME: All of the below goes away once CallExpr directly stores its
207+
/// arguments.
208+
209+
/// Return value for getOriginalArgumentList().
210+
struct OriginalArgumentList {
211+
SmallVector<Expr *, 4> args;
212+
SmallVector<Identifier, 4> labels;
213+
SmallVector<SourceLoc, 4> labelLocs;
214+
SourceLoc lParenLoc;
215+
SourceLoc rParenLoc;
216+
bool hasTrailingClosure = false;
217+
};
218+
219+
/// When applying a solution to a constraint system, the type checker rewrites
220+
/// argument lists of calls to insert default arguments and collect varargs.
221+
/// Sometimes for diagnostics we want to work on the original argument list as
222+
/// written by the user; this performs the reverse transformation.
223+
OriginalArgumentList getOriginalArgumentList(Expr *expr);
205224
}
206225

207226
#endif

lib/AST/ASTDumper.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2454,6 +2454,20 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
24542454
PrintWithColorRAII(OS, ParenthesisColor) << ')';
24552455
}
24562456

2457+
void visitDefaultArgumentExpr(DefaultArgumentExpr *E) {
2458+
printCommon(E, "default_argument_expr");
2459+
OS << " default_args_owner=";
2460+
E->getDefaultArgsOwner().dump(OS);
2461+
OS << " param=" << E->getParamIndex();
2462+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
2463+
}
2464+
2465+
void visitCallerDefaultArgumentExpr(CallerDefaultArgumentExpr *E) {
2466+
printCommon(E, "caller_default_argument_expr");
2467+
printRec(E->getSubExpr());
2468+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
2469+
}
2470+
24572471
void printArgumentLabels(ArrayRef<Identifier> argLabels) {
24582472
PrintWithColorRAII(OS, ArgumentsColor) << " arg_labels=";
24592473
for (auto label : argLabels) {

lib/AST/ASTWalker.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,17 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
443443

444444
Expr *visitOpaqueValueExpr(OpaqueValueExpr *E) { return E; }
445445

446+
Expr *visitDefaultArgumentExpr(DefaultArgumentExpr *E) { return E; }
447+
448+
Expr *visitCallerDefaultArgumentExpr(CallerDefaultArgumentExpr *E) {
449+
if (auto subExpr = doIt(E->getSubExpr())) {
450+
E->setSubExpr(subExpr);
451+
return E;
452+
}
453+
454+
return nullptr;
455+
}
456+
446457
Expr *visitInterpolatedStringLiteralExpr(InterpolatedStringLiteralExpr *E) {
447458
HANDLE_SEMANTIC_EXPR(E);
448459

lib/AST/Expr.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,9 @@ ConcreteDeclRef Expr::getReferencedDecl() const {
308308
PASS_THROUGH_REFERENCE(RebindSelfInConstructor, getSubExpr);
309309

310310
NO_REFERENCE(OpaqueValue);
311+
NO_REFERENCE(DefaultArgument);
312+
NO_REFERENCE(CallerDefaultArgument);
313+
311314
PASS_THROUGH_REFERENCE(BindOptional, getSubExpr);
312315
PASS_THROUGH_REFERENCE(OptionalEvaluation, getSubExpr);
313316
PASS_THROUGH_REFERENCE(ForceValue, getSubExpr);
@@ -612,6 +615,8 @@ bool Expr::canAppendPostfixExpression(bool appendingPostfixOperator) const {
612615

613616
case ExprKind::RebindSelfInConstructor:
614617
case ExprKind::OpaqueValue:
618+
case ExprKind::DefaultArgument:
619+
case ExprKind::CallerDefaultArgument:
615620
case ExprKind::BindOptional:
616621
case ExprKind::OptionalEvaluation:
617622
return false;

lib/IDE/Refactoring.cpp

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "swift/Frontend/Frontend.h"
2828
#include "swift/Index/Index.h"
2929
#include "swift/Parse/Lexer.h"
30+
#include "swift/Sema/IDETypeChecking.h"
3031
#include "swift/Subsystems.h"
3132
#include "clang/Rewrite/Core/RewriteBuffer.h"
3233
#include "llvm/ADT/StringSet.h"
@@ -2885,33 +2886,24 @@ bool RefactoringActionTrailingClosure::performChange() {
28852886
auto *CE = findTrailingClosureTarget(SM, CursorInfo);
28862887
if (!CE)
28872888
return true;
2888-
Expr *Args = CE->getArg();
2889-
if (auto *ASE = dyn_cast<ArgumentShuffleExpr>(Args))
2890-
Args = ASE->getSubExpr();
2889+
Expr *Arg = CE->getArg();
28912890

28922891
Expr *ClosureArg = nullptr;
28932892
Expr *PrevArg = nullptr;
2894-
SourceLoc LPLoc, RPLoc;
28952893

2896-
if (auto *PE = dyn_cast<ParenExpr>(Args)) {
2897-
ClosureArg = PE->getSubExpr();
2898-
LPLoc = PE->getLParenLoc();
2899-
RPLoc = PE->getRParenLoc();
2900-
} else {
2901-
auto *TE = cast<TupleExpr>(Args);
2902-
auto NumArgs = TE->getNumElements();
2903-
if (NumArgs == 0)
2904-
return true;
2905-
LPLoc = TE->getLParenLoc();
2906-
RPLoc = TE->getRParenLoc();
2907-
ClosureArg = TE->getElement(NumArgs - 1);
2908-
if (NumArgs > 1)
2909-
PrevArg = TE->getElement(NumArgs - 2);
2910-
}
2894+
OriginalArgumentList ArgList = getOriginalArgumentList(Arg);
2895+
2896+
auto NumArgs = ArgList.args.size();
2897+
if (NumArgs == 0)
2898+
return true;
2899+
ClosureArg = ArgList.args[NumArgs - 1];
2900+
if (NumArgs > 1)
2901+
PrevArg = ArgList.args[NumArgs - 2];
2902+
29112903
if (auto *ICE = dyn_cast<ImplicitConversionExpr>(ClosureArg))
29122904
ClosureArg = ICE->getSyntacticSubExpr();
29132905

2914-
if (LPLoc.isInvalid() || RPLoc.isInvalid())
2906+
if (ArgList.lParenLoc.isInvalid() || ArgList.rParenLoc.isInvalid())
29152907
return true;
29162908

29172909
// Replace:
@@ -2925,14 +2917,14 @@ bool RefactoringActionTrailingClosure::performChange() {
29252917
EditConsumer.accept(SM, PreRange, ") ");
29262918
} else {
29272919
CharSourceRange PreRange(
2928-
SM, LPLoc, ClosureArg->getStartLoc());
2920+
SM, ArgList.lParenLoc, ClosureArg->getStartLoc());
29292921
EditConsumer.accept(SM, PreRange, " ");
29302922
}
29312923
// Remove original closing paren.
29322924
CharSourceRange PostRange(
29332925
SM,
29342926
Lexer::getLocForEndOfToken(SM, ClosureArg->getEndLoc()),
2935-
Lexer::getLocForEndOfToken(SM, RPLoc));
2927+
Lexer::getLocForEndOfToken(SM, ArgList.rParenLoc));
29362928
EditConsumer.remove(SM, PostRange);
29372929
return false;
29382930
}

lib/SILGen/ASTVisitor.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,15 @@ class ASTVisitor : public swift::ASTVisitor<ImplClass,
5656
llvm_unreachable("expression kind should not survive to SILGen");
5757
}
5858

59+
ExprRetTy visitDefaultArgumentExpr(DefaultArgumentExpr *E, Args...AA) {
60+
llvm_unreachable("DefaultArgumentExpr should not appear in this position");
61+
}
62+
63+
ExprRetTy visitCallerDefaultArgumentExpr(CallerDefaultArgumentExpr *E, Args... AA) {
64+
return static_cast<ImplClass*>(this)->visit(E->getSubExpr(),
65+
std::forward<Args>(AA)...);
66+
}
67+
5968
ExprRetTy visitVarargExpansionExpr(VarargExpansionExpr *E, Args... AA) {
6069
return static_cast<ImplClass*>(this)->visit(E->getSubExpr(),
6170
std::forward<Args>(AA)...);

lib/SILGen/ArgumentSource.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,25 @@ class ArgumentSource {
172172
bool isRValue() const & { return StoredKind == Kind::RValue; }
173173
bool isLValue() const & { return StoredKind == Kind::LValue; }
174174

175+
bool isDefaultArg() const {
176+
switch (StoredKind) {
177+
case Kind::Invalid:
178+
llvm_unreachable("argument source is invalid");
179+
case Kind::RValue:
180+
case Kind::LValue:
181+
return false;
182+
case Kind::Expr:
183+
return isa<DefaultArgumentExpr>(asKnownExpr());
184+
}
185+
llvm_unreachable("bad kind");
186+
}
187+
188+
/// Return the default argument owner and parameter index, consuming
189+
/// the argument source. Will assert if this is not a default argument.
190+
DefaultArgumentExpr *asKnownDefaultArg() && {
191+
return cast<DefaultArgumentExpr>(std::move(*this).asKnownExpr());
192+
}
193+
175194
/// Given that this source is storing an RValue, extract and clear
176195
/// that value.
177196
RValue &&asKnownRValue(SILGenFunction &SGF) && {

lib/SILGen/SILGenApply.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2715,6 +2715,26 @@ class ArgEmitter {
27152715

27162716
// origParamType is a parameter type.
27172717
void emitSingleArg(ArgumentSource &&arg, AbstractionPattern origParamType) {
2718+
// If this is default argument, prepare to emit the default argument
2719+
// generator later.
2720+
if (arg.isDefaultArg()) {
2721+
auto substParamType = arg.getSubstRValueType();
2722+
auto defArg = std::move(arg).asKnownDefaultArg();
2723+
2724+
auto numParams = getFlattenedValueCount(origParamType,
2725+
substParamType,
2726+
ImportAsMemberStatus());
2727+
DelayedArguments.emplace_back(defArg,
2728+
defArg->getDefaultArgsOwner(),
2729+
defArg->getParamIndex(),
2730+
substParamType, origParamType,
2731+
claimNextParameters(numParams),
2732+
Rep);
2733+
Args.push_back(ManagedValue());
2734+
2735+
maybeEmitForeignErrorArgument();
2736+
return;
2737+
}
27182738
emit(std::move(arg), origParamType);
27192739
maybeEmitForeignErrorArgument();
27202740
}

0 commit comments

Comments
 (0)