diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 006c0477215eb..c6e1776656047 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -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); } @@ -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 { @@ -4976,7 +4977,7 @@ ParserResult 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; @@ -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; diff --git a/lib/Parse/ParseType.cpp b/lib/Parse/ParseType.cpp index 18cfad4d45e5e..a66aed29cc3cd 100644 --- a/lib/Parse/ParseType.cpp +++ b/lib/Parse/ParseType.cpp @@ -742,6 +742,10 @@ ParserStatus Parser::parseGenericArguments(SmallVectorImpl &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; } } @@ -1161,7 +1165,7 @@ ParserResult Parser::parseTypeTupleBody() { SmallVector ElementsR; ParserStatus Status = parseList(tok::r_paren, LPLoc, RPLoc, - /*AllowSepAfterLast=*/false, + /*AllowSepAfterLast=*/true, diag::expected_rparen_tuple_type_list, [&] () -> ParserStatus { TupleTypeReprElement element; @@ -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; diff --git a/test/Casting/ParameterizedExistentials.swift b/test/Casting/ParameterizedExistentials.swift index ea893d7c02912..c6fd92d30c49f 100644 --- a/test/Casting/ParameterizedExistentials.swift +++ b/test/Casting/ParameterizedExistentials.swift @@ -46,7 +46,10 @@ struct GenericHolder: Holder { init(value: T) { self.value = value} } -protocol PairType { +protocol PairType< + T, + U, +> { associatedtype T associatedtype U diff --git a/test/Parse/trailing-comma.swift b/test/Parse/trailing-comma.swift index 200733e8885e1..453c3388f9eaa 100644 --- a/test/Parse/trailing-comma.swift +++ b/test/Parse/trailing-comma.swift @@ -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,) @@ -34,7 +38,7 @@ struct S { } func foo() { } -protocol P { +protocol P { associatedtype T1 associatedtype T2 } @@ -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() {} @@ -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}} \ No newline at end of file +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 {} diff --git a/test/decl/ext/typealias.swift b/test/decl/ext/typealias.swift index c5917a0a0d565..3d33655f7a80b 100644 --- a/test/decl/ext/typealias.swift +++ b/test/decl/ext/typealias.swift @@ -78,3 +78,16 @@ extension FooIntBarFloatDoubleInner { } } +struct Foo2 {} + +typealias Bar2< + T1, + T2, +> = Foo2< + T1, + T2, + Bool, +> + +let _ = Foo2.self +let _ = Bar2() diff --git a/test/type/types.swift b/test/type/types.swift index 09b217c147875..7176d1298c0f5 100644 --- a/test/type/types.swift +++ b/test/type/types.swift @@ -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, +)