Skip to content

Commit 0ed4b33

Browse files
committed
[SE-0393] Enable parameter packs for generic functions.
The VariadicGenerics flag still exists and is required for generic types with parameter packs
1 parent c602ae9 commit 0ed4b33

File tree

10 files changed

+45
-43
lines changed

10 files changed

+45
-43
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5375,6 +5375,10 @@ ERROR(tuple_pack_element_label,none,
53755375
ERROR(vararg_not_allowed,none,
53765376
"variadic parameter cannot appear outside of a function parameter list",
53775377
())
5378+
5379+
ERROR(experimental_type_with_parameter_pack,none,
5380+
"generic types with parameter packs are experimental",
5381+
())
53785382
ERROR(expansion_not_allowed,none,
53795383
"pack expansion %0 can only appear in a function parameter list, "
53805384
"tuple element, or generic argument list", (Type))

lib/Parse/ParseDecl.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6459,8 +6459,7 @@ ParserResult<TypeDecl> Parser::parseDeclAssociatedType(Parser::ParseDeclOptions
64596459
}
64606460

64616461
// Reject variadic associated types with a specific error.
6462-
if (Context.LangOpts.hasFeature(Feature::VariadicGenerics) &&
6463-
Tok.isContextualKeyword("each")) {
6462+
if (Tok.isContextualKeyword("each")) {
64646463
const auto EachLoc = consumeToken();
64656464
diagnose(EachLoc, diag::associatedtype_cannot_be_variadic)
64666465
.fixItRemoveChars(EachLoc, Tok.getLoc());
@@ -6484,8 +6483,7 @@ ParserResult<TypeDecl> Parser::parseDeclAssociatedType(Parser::ParseDeclOptions
64846483
}
64856484

64866485
// Reject (early syntax) variadic associated types with a specific error.
6487-
if (Context.LangOpts.hasFeature(Feature::VariadicGenerics) &&
6488-
startsWithEllipsis(Tok)) {
6486+
if (startsWithEllipsis(Tok)) {
64896487
const auto EllipsisLoc = consumeStartingEllipsis();
64906488
const auto EllipsisEnd = Lexer::getLocForEndOfToken(SourceMgr, EllipsisLoc);
64916489
diagnose(EllipsisLoc, diag::associatedtype_cannot_be_variadic)

lib/Parse/ParseExpr.cpp

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -531,8 +531,7 @@ ParserResult<Expr> Parser::parseExprUnary(Diag<> Message, bool isExprBasic) {
531531
tryLexRegexLiteral(/*forUnappliedOperator*/ false);
532532

533533
// 'repeat' as an expression prefix is a pack expansion expression.
534-
if (Context.LangOpts.hasFeature(Feature::VariadicGenerics) &&
535-
Tok.is(tok::kw_repeat)) {
534+
if (Tok.is(tok::kw_repeat)) {
536535
SourceLoc repeatLoc = consumeToken();
537536
auto patternExpr = parseExpr(Message);
538537
if (patternExpr.isNull())
@@ -3024,17 +3023,10 @@ ParserResult<Expr> Parser::parseTupleOrParenExpr(tok leftTok, tok rightTok) {
30243023
rightLoc);
30253024

30263025
// A tuple with a single, unlabeled element is just parentheses.
3027-
if (Context.LangOpts.hasFeature(Feature::VariadicGenerics)) {
3028-
if (elts.size() == 1 && !isa<PackExpansionExpr>(elts[0].E) &&
3029-
elts[0].LabelLoc.isInvalid()) {
3030-
return makeParserResult(
3031-
status, new (Context) ParenExpr(leftLoc, elts[0].E, rightLoc));
3032-
}
3033-
} else {
3034-
if (elts.size() == 1 && elts[0].Label.empty()) {
3035-
return makeParserResult(
3036-
status, new (Context) ParenExpr(leftLoc, elts[0].E, rightLoc));
3037-
}
3026+
if (elts.size() == 1 && !isa<PackExpansionExpr>(elts[0].E) &&
3027+
elts[0].Label.empty()) {
3028+
return makeParserResult(
3029+
status, new (Context) ParenExpr(leftLoc, elts[0].E, rightLoc));
30383030
}
30393031

30403032
SmallVector<Expr *, 8> exprs;

lib/Parse/ParseGeneric.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,7 @@ Parser::parseGenericParametersBeforeWhere(SourceLoc LAngleLoc,
6060

6161
// Parse the 'each' keyword for a type parameter pack 'each T'.
6262
SourceLoc EachLoc;
63-
if (Context.LangOpts.hasFeature(Feature::VariadicGenerics) &&
64-
Tok.isContextualKeyword("each")) {
63+
if (Tok.isContextualKeyword("each")) {
6564
TokReceiver->registerTokenKindChange(Tok.getLoc(),
6665
tok::contextual_keyword);
6766
EachLoc = consumeToken();
@@ -78,8 +77,7 @@ Parser::parseGenericParametersBeforeWhere(SourceLoc LAngleLoc,
7877

7978
// Parse and diagnose the unsupported ellipsis for a type parameter pack
8079
// 'T...'.
81-
if (Context.LangOpts.hasFeature(Feature::VariadicGenerics) &&
82-
startsWithEllipsis(Tok)) {
80+
if (startsWithEllipsis(Tok)) {
8381
const auto EllipsisLoc = consumeStartingEllipsis();
8482
// TODO: token length hardcoded because calculation for ellipsis
8583
// incorrectly includes '>' if one follows (as can occur in this parse).

lib/Parse/ParseStmt.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,7 @@ bool Parser::isStartOfStmt() {
6868
// is a pack expansion expression.
6969
// FIXME: 'repeat' followed by '{' could be a pack expansion
7070
// with a closure pattern.
71-
return !Context.LangOpts.hasFeature(Feature::VariadicGenerics) ||
72-
peekToken().is(tok::l_brace);
71+
return peekToken().is(tok::l_brace);
7372

7473
case tok::pound_line:
7574
// #line at the start of a line is a directive, when within, it is an expr.

lib/Sema/CSSimplify.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1755,8 +1755,7 @@ static ConstraintSystem::TypeMatchResult matchCallArguments(
17551755
// We pull these out special because variadic parameters ban lots of
17561756
// the more interesting typing constructs called out below like
17571757
// inout and @autoclosure.
1758-
if (cs.getASTContext().LangOpts.hasFeature(Feature::VariadicGenerics) &&
1759-
paramInfo.isVariadicGenericParameter(paramIdx)) {
1758+
if (paramInfo.isVariadicGenericParameter(paramIdx)) {
17601759
// If generic parameter comes from a variadic type declaration it's
17611760
// possible that it got specialized early and is no longer represented
17621761
// by a pack expansion type. For example, consider expression -

lib/Sema/MiscDiagnostics.cpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -293,15 +293,14 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
293293
}
294294
}
295295

296-
if (!Ctx.LangOpts.hasFeature(Feature::VariadicGenerics)) {
297-
// Diagnose single-element tuple expressions.
298-
if (auto *tupleExpr = dyn_cast<TupleExpr>(E)) {
299-
if (tupleExpr->getNumElements() == 1) {
300-
Ctx.Diags.diagnose(tupleExpr->getElementNameLoc(0),
301-
diag::tuple_single_element)
302-
.fixItRemoveChars(tupleExpr->getElementNameLoc(0),
303-
tupleExpr->getElement(0)->getStartLoc());
304-
}
296+
// Diagnose single-element tuple expressions.
297+
if (auto *tupleExpr = dyn_cast<TupleExpr>(E)) {
298+
if (tupleExpr->getNumElements() == 1 &&
299+
!isa<PackExpansionExpr>(tupleExpr->getElement(0))) {
300+
Ctx.Diags.diagnose(tupleExpr->getElementNameLoc(0),
301+
diag::tuple_single_element)
302+
.fixItRemoveChars(tupleExpr->getElementNameLoc(0),
303+
tupleExpr->getElement(0)->getStartLoc());
305304
}
306305
}
307306

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,15 @@ static void checkGenericParams(GenericContext *ownerCtx) {
473473
return;
474474

475475
for (auto gp : *genericParams) {
476+
// Diagnose generic types with a parameter packs if VariadicGenerics
477+
// is not enabled.
478+
auto *decl = ownerCtx->getAsDecl();
479+
auto &ctx = decl->getASTContext();
480+
if (gp->isParameterPack() && isa<GenericTypeDecl>(decl) &&
481+
!ctx.LangOpts.hasFeature(Feature::VariadicGenerics)) {
482+
decl->diagnose(diag::experimental_type_with_parameter_pack);
483+
}
484+
476485
TypeChecker::checkDeclAttributes(gp);
477486
checkInheritanceClause(gp);
478487
}

test/IDE/complete_repeat.swift

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,19 +52,23 @@ func enclosingFunc1() {
5252
// REPEAT_4: Decl[LocalVar]/Local: local0[#Int#];
5353
// REPEAT_4-NOT: LocalVar
5454

55-
repeat {
56-
let local1 = 1
57-
#^REPEAT_5^#
58-
} while
55+
do {
56+
repeat {
57+
let local1 = 1
58+
#^REPEAT_5^#
59+
} while
60+
}
5961
// REPEAT_5-NOT: LocalVar
6062
// REPEAT_5: Decl[LocalVar]/Local: local1[#Int#];
6163
// REPEAT_5-NOT: LocalVar
6264

63-
repeat {
64-
let local1 = 1
65+
do {
6566
repeat {
66-
let local2 = 1
67-
} while #^REPEAT_COND_1^#
67+
let local1 = 1
68+
repeat {
69+
let local2 = 1
70+
} while #^REPEAT_COND_1^#
71+
}
6872
}
6973
// REPEAT_COND_1-NOT: LocalVar
7074
// REPEAT_COND_1: Decl[LocalVar]/Local: local1[#Int#];

test/stmt/statements.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ func RepeatWhileStmt1() {
271271
}
272272

273273
func RepeatWhileStmt2() {
274-
repeat // expected-error {{expected '{' after 'repeat'}} expected-error {{expected 'while' after body of 'repeat' statement}}
274+
repeat // expected-error@+1 {{expected expression}}
275275
}
276276

277277
func RepeatWhileStmt4() {

0 commit comments

Comments
 (0)