Skip to content

[6.2] Add trailing comma support in cases missing from Swift 6.1 #81653

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2137,7 +2137,7 @@ Parser::parseAttributeArguments(SourceLoc attrLoc, StringRef attrName,
}

return parseList(tok::r_paren, parensRange.Start, parensRange.End,
/*allow sep after last*/ true,
/*AllowSepAfterLast=*/true,
{diag::attr_expected_rparen, {attrName, isModifier}},
parseArg);
}
Expand Down Expand Up @@ -3243,7 +3243,8 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
StringRef AttrName = "@_originallyDefinedIn";
bool SuppressLaterDiags = false;
bool ParsedUnrecognizedPlatformName = false;
if (parseList(tok::r_paren, LeftLoc, RightLoc, false,
if (parseList(tok::r_paren, LeftLoc, RightLoc,
/*AllowSepAfterLast=*/false,
diag::originally_defined_in_missing_rparen,
[&]() -> ParserStatus {
SWIFT_DEFER {
Expand Down Expand Up @@ -4976,7 +4977,7 @@ ParserResult<LifetimeEntry> Parser::parseLifetimeEntry(SourceLoc loc) {
SourceLoc rParenLoc;
bool foundParamId = false;
status = parseList(
tok::r_paren, lParenLoc, rParenLoc, /*AllowSepAfterLast*/ false,
tok::r_paren, lParenLoc, rParenLoc, /*AllowSepAfterLast=*/false,
diag::expected_rparen_after_lifetime_dependence, [&]() -> ParserStatus {
ParserStatus listStatus;
foundParamId = true;
Expand Down Expand Up @@ -9525,6 +9526,11 @@ ParserStatus Parser::parsePrimaryAssociatedTypeList(

// Parse the comma, if the list continues.
HasNextParam = consumeIf(tok::comma);

// The list ends if we find a trailing comma
if (startsWithGreater(Tok)) {
break;
}
} while (HasNextParam);

return Result;
Expand Down
9 changes: 7 additions & 2 deletions lib/Parse/ParseType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,10 @@ ParserStatus Parser::parseGenericArguments(SmallVectorImpl<TypeRepr *> &Args,
// Parse the comma, if the list continues.
if (!consumeIf(tok::comma))
break;

// If the comma was a trailing comma, finish parsing the list of types
if (startsWithGreater(Tok))
break;
}
}

Expand Down Expand Up @@ -1161,7 +1165,7 @@ ParserResult<TypeRepr> Parser::parseTypeTupleBody() {
SmallVector<TupleTypeReprElement, 8> ElementsR;

ParserStatus Status = parseList(tok::r_paren, LPLoc, RPLoc,
/*AllowSepAfterLast=*/false,
/*AllowSepAfterLast=*/true,
diag::expected_rparen_tuple_type_list,
[&] () -> ParserStatus {
TupleTypeReprElement element;
Expand Down Expand Up @@ -1605,7 +1609,8 @@ bool Parser::canParseGenericArguments() {
if (!canParseType())
return false;
// Parse the comma, if the list continues.
} while (consumeIf(tok::comma));
// This could be the trailing comma.
} while (consumeIf(tok::comma) && !startsWithGreater(Tok));

if (!startsWithGreater(Tok)) {
return false;
Expand Down
5 changes: 4 additions & 1 deletion test/Casting/ParameterizedExistentials.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ struct GenericHolder<T>: Holder {
init(value: T) { self.value = value}
}

protocol PairType<T, U> {
protocol PairType<
T,
U,
> {
associatedtype T
associatedtype U

Expand Down
18 changes: 15 additions & 3 deletions test/Parse/trailing-comma.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ let values: [Int,] = [] // expected-note {{to match this opening '['}} expected-
// Tuple and Tuple Pattern

let _ = (a: 1, b: 2, c: 3,)
let _: (a: Int, b: Int, c: Int,) = (a: 1, b: 2, c: 3,)

// Closures
let _: (String, Int, Float,) -> Void

let (_, _,) = (0,1,)

Expand All @@ -34,7 +38,7 @@ struct S<T1, T2,> { }

func foo<T1, T2,>() { }

protocol P<T1, T2> {
protocol P<T1, T2,> {
associatedtype T1
associatedtype T2
}
Expand Down Expand Up @@ -98,7 +102,7 @@ struct Foo {

}

func f(in: @differentiable(reverse,) (Int) -> Int) { } // expected-warning {{@differentiable' has been renamed to '@differentiable(reverse)' and will be removed in the next release}} expected-error {{unexpected ',' separator}} expected-error {{expected ',' separator}} expected-error {{unnamed parameters must be written with the empty name '_'}}
func f(in: @differentiable(reverse,) (Int) -> Int) { } // expected-warning {{@differentiable' has been renamed to '@differentiable(reverse)' and will be removed in the next release}} expected-error {{expected ',' separator}} expected-error {{unnamed parameters must be written with the empty name '_'}}

@derivative(of: Self.other,) // expected-error {{unexpected ',' separator}}
func foo() {}
Expand Down Expand Up @@ -135,4 +139,12 @@ if true, { } // expected-error {{expected '{' after 'if' condition}}

guard true, else { } // expected-error {{expected expression in conditional}}

while true, { } // expected-error {{expected '{' after 'while' condition}}
while true, { } // expected-error {{expected '{' after 'while' condition}}

if #available(OSX 51,) { // expected-error {{expected platform name}}
}

@available(OSX 10.7, iOS 7.0, *,) // expected-error {{expected platform name}} expected-error {{expected declaration}}
@_originallyDefinedIn(module: "HighLevel", OSX 10.9, iOS 13.0,) // expected-error {{unexpected ',' separator}}
@backDeployed(before: OSX 10.9,) // expected-error {{unexpected ',' separator}}
public struct StructWithAvailability {}
13 changes: 13 additions & 0 deletions test/decl/ext/typealias.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,16 @@ extension FooIntBarFloatDoubleInner {
}
}

struct Foo2<T1, T2, T3,> {}

typealias Bar2<
T1,
T2,
> = Foo2<
T1,
T2,
Bool,
>

let _ = Foo2<Int, Bool, String,>.self
let _ = Bar2<Int, Bool,>()
15 changes: 15 additions & 0 deletions test/type/types.swift
Original file line number Diff line number Diff line change
Expand Up @@ -219,3 +219,18 @@ do {
subscript(_: inout Double...) -> Bool { true } // expected-error {{'inout' may only be used on function or initializer parameters}}
}
}

let tupleTypeWithTrailingComma: (
bar: String,
quux: String,
)

let _ = (bar: String, quux: String,).self

let closureTypeWithTrailingCommas: (
String,
String,
) -> (
bar: String,
quux: String,
)