Skip to content

Commit bcceea2

Browse files
committed
[AST] Introduce a syntactic distinction betweek vararg type reprs and
pack expansion type reprs. Classic variadic parameters still use the postfix ellipsis syntax, and pack expansion types now use a prefix 'repeat' keyword.
1 parent ed5d2ed commit bcceea2

17 files changed

+158
-76
lines changed

include/swift/AST/CASTBridging.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ void *ImplicitlyUnwrappedOptionalTypeRepr_create(void *ctx, void *base,
239239
void *exclamationLoc);
240240
void *MetatypeTypeRepr_create(void *ctx, void *baseType, void *typeLoc);
241241
void *ProtocolTypeRepr_create(void *ctx, void *baseType, void *protoLoc);
242-
void *PackExpansionTypeRepr_create(void *ctx, void *base, void *ellipsisLoc);
242+
void *PackExpansionTypeRepr_create(void *ctx, void *base, void *repeatLoc);
243243
void *TupleTypeRepr_create(void *ctx, BridgedArrayRef elements, void *lParenLoc,
244244
void *rParenLoc);
245245
void *IdentTypeRepr_create(void *ctx, BridgedArrayRef components);

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5155,6 +5155,9 @@ ERROR(dot_protocol_on_non_existential,none,
51555155
"cannot use 'Protocol' with non-protocol type %0", (Type))
51565156
ERROR(tuple_single_element,none,
51575157
"cannot create a single-element tuple with an element label", ())
5158+
ERROR(vararg_not_allowed,none,
5159+
"variadic parameter cannot appear outside of a function parameter list",
5160+
())
51585161
ERROR(expansion_not_allowed,none,
51595162
"variadic expansion %0 cannot appear outside of a function parameter list, "
51605163
"function result, tuple element or generic argument list", (Type))

include/swift/AST/TypeRepr.h

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,32 @@ struct TupleTypeReprElement {
704704
TupleTypeReprElement(TypeRepr *Type): Type(Type) {}
705705
};
706706

707+
/// A vararg type 'T...' with element type 'T'.
708+
class VarargTypeRepr final : public TypeRepr {
709+
TypeRepr *Element;
710+
SourceLoc EllipsisLoc;
711+
712+
public:
713+
VarargTypeRepr(TypeRepr *Element, SourceLoc EllipsisLoc)
714+
: TypeRepr(TypeReprKind::Vararg), Element(Element),
715+
EllipsisLoc(EllipsisLoc) {}
716+
717+
TypeRepr *getElementType() const { return Element; }
718+
SourceLoc getEllipsisLoc() const { return EllipsisLoc; }
719+
720+
static bool classof(const TypeRepr *T) {
721+
return T->getKind() == TypeReprKind::Vararg;
722+
}
723+
static bool classof(const VarargTypeRepr *T) { return true; }
724+
725+
private:
726+
SourceLoc getStartLocImpl() const { return Element->getEndLoc(); }
727+
SourceLoc getEndLocImpl() const { return EllipsisLoc; }
728+
SourceLoc getLocImpl() const { return EllipsisLoc; }
729+
void printImpl(ASTPrinter &Printer, const PrintOptions &Opts) const;
730+
friend class TypeRepr;
731+
};
732+
707733
/// A pack expansion 'T...' with a pattern 'T'.
708734
///
709735
/// Can appear in the following positions:
@@ -719,26 +745,26 @@ struct TupleTypeReprElement {
719745
/// In the third case, tuples cannot contain an old-style variadic element,
720746
/// so the pack expansion must be a real variadic pack expansion.
721747
class PackExpansionTypeRepr final : public TypeRepr {
748+
SourceLoc RepeatLoc;
722749
TypeRepr *Pattern;
723-
SourceLoc EllipsisLoc;
724750

725751
public:
726-
PackExpansionTypeRepr(TypeRepr *Pattern, SourceLoc EllipsisLoc)
727-
: TypeRepr(TypeReprKind::PackExpansion), Pattern(Pattern),
728-
EllipsisLoc(EllipsisLoc) {}
752+
PackExpansionTypeRepr(SourceLoc RepeatLoc, TypeRepr *Pattern)
753+
: TypeRepr(TypeReprKind::PackExpansion), RepeatLoc(RepeatLoc),
754+
Pattern(Pattern) {}
729755

756+
SourceLoc getRepeatLoc() const { return RepeatLoc; }
730757
TypeRepr *getPatternType() const { return Pattern; }
731-
SourceLoc getEllipsisLoc() const { return EllipsisLoc; }
732758

733759
static bool classof(const TypeRepr *T) {
734760
return T->getKind() == TypeReprKind::PackExpansion;
735761
}
736762
static bool classof(const PackExpansionTypeRepr *T) { return true; }
737763

738764
private:
739-
SourceLoc getStartLocImpl() const { return Pattern->getStartLoc(); }
740-
SourceLoc getEndLocImpl() const { return EllipsisLoc; }
741-
SourceLoc getLocImpl() const { return EllipsisLoc; }
765+
SourceLoc getStartLocImpl() const { return RepeatLoc; }
766+
SourceLoc getEndLocImpl() const { return Pattern->getEndLoc(); }
767+
SourceLoc getLocImpl() const { return RepeatLoc; }
742768
void printImpl(ASTPrinter &Printer, const PrintOptions &Opts) const;
743769
friend class TypeRepr;
744770
};
@@ -1381,6 +1407,7 @@ inline bool TypeRepr::isSimple() const {
13811407
case TypeReprKind::Dictionary:
13821408
case TypeReprKind::Optional:
13831409
case TypeReprKind::ImplicitlyUnwrappedOptional:
1410+
case TypeReprKind::Vararg:
13841411
case TypeReprKind::PackExpansion:
13851412
case TypeReprKind::Tuple:
13861413
case TypeReprKind::Fixed:

include/swift/AST/TypeReprNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ TYPEREPR(ImplicitlyUnwrappedOptional, TypeRepr)
5959
TYPEREPR(Tuple, TypeRepr)
6060
TYPEREPR(Composition, TypeRepr)
6161
TYPEREPR(Metatype, TypeRepr)
62+
TYPEREPR(Vararg, TypeRepr)
6263
TYPEREPR(PackExpansion, TypeRepr)
6364
TYPEREPR(Protocol, TypeRepr)
6465
TYPEREPR(OpaqueReturn, TypeRepr)

lib/AST/ASTDumper.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3161,6 +3161,12 @@ class PrintTypeRepr : public TypeReprVisitor<PrintTypeRepr> {
31613161
PrintWithColorRAII(OS, ParenthesisColor) << ')';
31623162
}
31633163

3164+
void visitVarargTypeRepr(VarargTypeRepr *T) {
3165+
printCommon("vararg") << '\n';
3166+
printRec(T->getElementType());
3167+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
3168+
}
3169+
31643170
void visitPackExpansionTypeRepr(PackExpansionTypeRepr *T) {
31653171
printCommon("pack_expansion") << '\n';
31663172
printRec(T->getPatternType());

lib/AST/ASTWalker.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1999,6 +1999,11 @@ bool Traversal::visitOptionalTypeRepr(OptionalTypeRepr *T) {
19991999
bool Traversal::visitImplicitlyUnwrappedOptionalTypeRepr(ImplicitlyUnwrappedOptionalTypeRepr *T) {
20002000
return doIt(T->getBase());
20012001
}
2002+
2003+
bool Traversal::visitVarargTypeRepr(VarargTypeRepr *T) {
2004+
return doIt(T->getElementType());
2005+
}
2006+
20022007
bool Traversal::visitPackExpansionTypeRepr(PackExpansionTypeRepr *T) {
20032008
return doIt(T->getPatternType());
20042009
}

lib/AST/CASTBridging.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -466,10 +466,10 @@ void *ProtocolTypeRepr_create(void *ctx, void *baseType, void *protoLoc) {
466466
return new (Context) ProtocolTypeRepr((TypeRepr *)baseType, protocolLoc);
467467
}
468468

469-
void *PackExpansionTypeRepr_create(void *ctx, void *base, void *ellipsisLoc) {
469+
void *PackExpansionTypeRepr_create(void *ctx, void *base, void *repeatLoc) {
470470
ASTContext &Context = *static_cast<ASTContext *>(ctx);
471471
return new (Context) PackExpansionTypeRepr(
472-
(TypeRepr *)base, getSourceLocFromPointer(ellipsisLoc));
472+
getSourceLocFromPointer(repeatLoc), (TypeRepr *)base);
473473
}
474474

475475
void *TupleTypeRepr_create(void *ctx, BridgedArrayRef elements, void *lParenLoc,

lib/AST/NameLookup.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2509,6 +2509,13 @@ directReferencesForTypeRepr(Evaluator &evaluator,
25092509
return { };
25102510
}
25112511

2512+
case TypeReprKind::Vararg: {
2513+
auto packExpansionRepr = cast<VarargTypeRepr>(typeRepr);
2514+
return directReferencesForTypeRepr(evaluator, ctx,
2515+
packExpansionRepr->getElementType(), dc,
2516+
allowUsableFromInline);
2517+
}
2518+
25122519
case TypeReprKind::PackExpansion: {
25132520
auto packExpansionRepr = cast<PackExpansionTypeRepr>(typeRepr);
25142521
return directReferencesForTypeRepr(evaluator, ctx,
@@ -2813,7 +2820,7 @@ CollectedOpaqueReprs swift::collectOpaqueReturnTypeReprs(TypeRepr *r, ASTContext
28132820
PreWalkAction walkToTypeReprPre(TypeRepr *repr) override {
28142821

28152822
// Don't allow variadic opaque parameter or return types.
2816-
if (isa<PackExpansionTypeRepr>(repr))
2823+
if (isa<PackExpansionTypeRepr>(repr) || isa<VarargTypeRepr>(repr))
28172824
return Action::SkipChildren();
28182825

28192826
if (auto opaqueRepr = dyn_cast<OpaqueReturnTypeRepr>(repr)) {

lib/AST/TypeRepr.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,10 +407,16 @@ SourceLoc SILBoxTypeRepr::getLocImpl() const {
407407
return LBraceLoc;
408408
}
409409

410+
void VarargTypeRepr::printImpl(ASTPrinter &Printer,
411+
const PrintOptions &Opts) const {
412+
printTypeRepr(Element, Printer, Opts);
413+
Printer << "...";
414+
}
415+
410416
void PackExpansionTypeRepr::printImpl(ASTPrinter &Printer,
411417
const PrintOptions &Opts) const {
418+
Printer.printKeyword("repeat", Opts, /*Suffix=*/" ");
412419
printTypeRepr(Pattern, Printer, Opts);
413-
Printer << "...";
414420
}
415421

416422
void PackReferenceTypeRepr::printImpl(ASTPrinter &Printer,

lib/ASTGen/Sources/ASTGen/Types.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,8 @@ extension ASTGenVisitor {
118118

119119
public func visit(_ node: PackExpansionTypeSyntax) -> ASTNode {
120120
let base = visit(node.patternType).rawValue
121-
let ellipsisLoc = self.base.advanced(by: node.ellipsis.position.utf8Offset).raw
122-
return .type(PackExpansionTypeRepr_create(self.ctx, base, ellipsisLoc))
121+
let repeatLoc = self.base.advanced(by: node.repeatKeyword.position.utf8Offset).raw
122+
return .type(PackExpansionTypeRepr_create(self.ctx, base, repeatLoc))
123123
}
124124

125125
public func visit(_ node: TupleTypeSyntax) -> ASTNode {

lib/Parse/ParseExpr.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2972,7 +2972,8 @@ ParserResult<Expr> Parser::parseTupleOrParenExpr(tok leftTok, tok rightTok) {
29722972

29732973
// A tuple with a single, unlabeled element is just parentheses.
29742974
if (Context.LangOpts.hasFeature(Feature::VariadicGenerics)) {
2975-
if (elts.size() == 1 && elts[0].LabelLoc.isInvalid()) {
2975+
if (elts.size() == 1 && !isa<PackExpansionExpr>(elts[0].E) &&
2976+
elts[0].LabelLoc.isInvalid()) {
29762977
return makeParserResult(
29772978
status, new (Context) ParenExpr(leftLoc, elts[0].E, rightLoc));
29782979
}

lib/Parse/ParseType.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -535,16 +535,28 @@ ParserResult<TypeRepr> Parser::parseTypeScalar(
535535
///
536536
ParserResult<TypeRepr> Parser::parseType(
537537
Diag<> MessageID, ParseTypeReason reason) {
538+
// Parse pack expansion 'repeat T'
539+
if (Tok.is(tok::kw_repeat)) {
540+
SourceLoc repeatLoc = consumeToken(tok::kw_repeat);
541+
542+
auto ty = parseTypeScalar(MessageID, reason);
543+
if (ty.isNull())
544+
return ty;
545+
546+
return makeParserResult(ty,
547+
new (Context) PackExpansionTypeRepr(repeatLoc, ty.get()));
548+
}
549+
538550
auto ty = parseTypeScalar(MessageID, reason);
539551
if (ty.isNull())
540552
return ty;
541553

542-
// Parse pack expansion 'T...'.
554+
// Parse vararg type 'T...'.
543555
if (Tok.isEllipsis()) {
544556
Tok.setKind(tok::ellipsis);
545557
SourceLoc ellipsisLoc = consumeToken();
546558
ty = makeParserResult(ty,
547-
new (Context) PackExpansionTypeRepr(ty.get(), ellipsisLoc));
559+
new (Context) VarargTypeRepr(ty.get(), ellipsisLoc));
548560
}
549561

550562
return ty;
@@ -1396,6 +1408,9 @@ bool Parser::canParseGenericArguments() {
13961408
}
13971409

13981410
bool Parser::canParseType() {
1411+
// 'repeat' starts a pack expansion type.
1412+
consumeIf(tok::kw_repeat);
1413+
13991414
// Accept 'inout' at for better recovery.
14001415
consumeIf(tok::kw_inout);
14011416

lib/Sema/CSGen.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3053,6 +3053,9 @@ namespace {
30533053
Type visitPackElementExpr(PackElementExpr *expr) {
30543054
auto packType = CS.getType(expr->getPackRefExpr());
30553055

3056+
if (PackElementEnvironments.empty())
3057+
return Type();
3058+
30563059
// The type of a PackElementExpr is the opened pack element archetype
30573060
// of the pack reference.
30583061
OpenPackElementType openPackElement(CS, CS.getConstraintLocator(expr),

lib/Sema/PreCheckExpr.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1775,6 +1775,11 @@ TypeExpr *PreCheckExpression::simplifyTypeExpr(Expr *E) {
17751775
SmallVector<TupleTypeReprElement, 4> Elts;
17761776
unsigned EltNo = 0;
17771777
for (auto Elt : TE->getElements()) {
1778+
// Try to simplify the element, e.g. to fold PackExpansionExprs
1779+
// into TypeExprs.
1780+
if (auto simplified = simplifyTypeExpr(Elt))
1781+
Elt = simplified;
1782+
17781783
auto *eltTE = dyn_cast<TypeExpr>(Elt);
17791784
if (!eltTE) return nullptr;
17801785
TupleTypeReprElement elt;
@@ -1975,11 +1980,11 @@ TypeExpr *PreCheckExpression::simplifyTypeExpr(Expr *E) {
19751980
return new (Ctx) TypeExpr(CompRepr);
19761981
}
19771982

1978-
// Fold 'T...' into a pack expansion type when 'T' is a TypeExpr.
1979-
if (auto *operand = isPostfixEllipsisOperator(E)) {
1980-
if (auto *pattern = dyn_cast<TypeExpr>(operand)) {
1981-
auto *repr = new (Ctx) PackExpansionTypeRepr(pattern->getTypeRepr(),
1982-
E->getLoc());
1983+
// Fold a pack expansion expr into a TypeExpr when the pattern is a TypeExpr.
1984+
if (auto *expansion = dyn_cast<PackExpansionExpr>(E)) {
1985+
if (auto *pattern = dyn_cast<TypeExpr>(expansion->getPatternExpr())) {
1986+
auto *repr = new (Ctx) PackExpansionTypeRepr(expansion->getStartLoc(),
1987+
pattern->getTypeRepr());
19831988
return new (Ctx) TypeExpr(repr);
19841989
}
19851990
}

lib/Sema/TypeCheckDecl.cpp

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2258,42 +2258,28 @@ static Type validateParameterType(ParamDecl *decl) {
22582258
break;
22592259
}
22602260

2261-
if (auto *packExpansionRepr = dyn_cast<PackExpansionTypeRepr>(nestedRepr)) {
2261+
if (auto *varargTypeRepr = dyn_cast<VarargTypeRepr>(nestedRepr)) {
22622262
// If the element is a variadic parameter, resolve the parameter type as if
22632263
// it were in non-parameter position, since we want functions to be
22642264
// @escaping in this case.
22652265
options.setContext(TypeResolverContext::VariadicFunctionInput);
22662266
options |= TypeResolutionFlags::Direct;
2267-
options |= TypeResolutionFlags::AllowPackReferences;
2268-
2269-
// FIXME: This duplicates code found elsewhere
2270-
auto *patternRepr = packExpansionRepr->getPatternType();
22712267

22722268
const auto resolution =
22732269
TypeResolution::forInterface(dc, options, unboundTyOpener,
22742270
PlaceholderType::get,
22752271
/*packElementOpener*/ nullptr);
2276-
Ty = resolution.resolveType(patternRepr);
2272+
Ty = resolution.resolveType(nestedRepr);
22772273

2278-
// Find the first type parameter pack and use that as the count type.
2279-
SmallVector<Type, 2> rootParameterPacks;
2280-
Ty->getTypeParameterPacks(rootParameterPacks);
2274+
// Monovariadic types (T...) for <T> resolve to [T].
2275+
Ty = VariadicSequenceType::get(Ty);
22812276

2282-
// Handle the monovariadic/polyvariadic interface type split.
2283-
if (!rootParameterPacks.empty()) {
2284-
// Polyvariadic types (T...) for <T...> resolve to pack expansions.
2285-
Ty = PackExpansionType::get(Ty, rootParameterPacks[0]);
2286-
} else {
2287-
// Monovariadic types (T...) for <T> resolve to [T].
2288-
Ty = VariadicSequenceType::get(Ty);
2289-
2290-
// Set the old-style variadic bit.
2291-
decl->setVariadic();
2292-
if (!ctx.getArrayDecl()) {
2293-
ctx.Diags.diagnose(decl->getTypeRepr()->getLoc(),
2294-
diag::sugar_type_not_found, 0);
2295-
return ErrorType::get(ctx);
2296-
}
2277+
// Set the old-style variadic bit.
2278+
decl->setVariadic();
2279+
if (!ctx.getArrayDecl()) {
2280+
ctx.Diags.diagnose(decl->getTypeRepr()->getLoc(),
2281+
diag::sugar_type_not_found, 0);
2282+
return ErrorType::get(ctx);
22972283
}
22982284
} else {
22992285
options.setContext(TypeResolverContext::FunctionInput);

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -644,7 +644,7 @@ GenericSignatureRequest::evaluate(Evaluator &evaluator,
644644
if (auto *specifier = dyn_cast<SpecifierTypeRepr>(typeRepr))
645645
typeRepr = specifier->getBase();
646646

647-
if (auto *packExpansion = dyn_cast<PackExpansionTypeRepr>(typeRepr)) {
647+
if (auto *packExpansion = dyn_cast<VarargTypeRepr>(typeRepr)) {
648648
paramOptions.setContext(TypeResolverContext::VariadicFunctionInput);
649649
} else {
650650
paramOptions.setContext(TypeResolverContext::FunctionInput);

0 commit comments

Comments
 (0)