Sema: Simplify representation of vararg forwarding

VarargExpansionExpr shows up in call argument lists in synthesized
initializers and modify accessors when we need to forward arguments
to a call taking varargs.

Previously we would say that the type of VarargExpansionExpr is
$T when its subexpression type is [$T]. matchCallArguments() would
then 'collect' the single VarargExpansionExpr into a variadic
argument list with a single element, and build an ArgumentShuffleExpr
for the argument list.

In turn, SILGen would peephole vararg emission of a variadic
argument list with a single entry that happens to be a
VarargExpansionExpr, by returning the subexpression's value,
which happened to be an array of the right element type,
instead of building a new array containing the elements of the
variadic argument list.

This was all too complicated. Instead, let's say that the type of
a VarargExpansionExpr is [$T], except that when it appears in a
TupleExpr, the variadic bit of the corresponding element is set.

Then, matchCallArguments() needs to support a case where both
the parameter and argument list have a matching vararg element.
In this case, instead of collecting multiple arguments into a
single variadic argument list, we treat the variadic argument like
an ordinary parameter, bypassing construction of the
ArgumentShuffleExpr altogether.

Finally, SILGen now needs to be able to emit a VarargExpansionExpr
in ordinary rvalue position, since it now appears as a child of a
TupleExpr; it can do this by simply emitting the sub-expression
to produce an array value.
This commit is contained in:
Slava Pestov
2019-03-28 00:33:31 -04:00
parent 8e773ab412
commit b9ef5708e2
8 changed files with 29 additions and 95 deletions

View File

@@ -457,7 +457,8 @@ static Expr *buildArgumentForwardingExpr(ArrayRef<ParamDecl*> params,
}
// A single unlabeled value is not a tuple.
if (args.size() == 1 && labels[0].empty()) {
if (args.size() == 1 && labels[0].empty() &&
!isa<VarargExpansionExpr>(args[0])) {
return new (ctx) ParenExpr(SourceLoc(), args[0], SourceLoc(),
/*hasTrailingClosure=*/false);
}