diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 84063848ec4db..afa7e45114033 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -1387,11 +1387,17 @@ Parser::parseExprPostfixSuffix(ParserResult Result, bool isExprBasic, if (Tok.is(tok::l_brace) && isValidTrailingClosure(isExprBasic, *this)) { // FIXME: if Result has a trailing closure, break out. - // Stop after literal expressions, which may never have trailing closures. const auto *callee = Result.get(); if (isa(callee) || isa(callee) || - isa(callee)) - break; + isa(callee)) { + // Trailing closures are allowed after array and dictionary types, + // since this can mean `[Element].init { }` or `[Key: Value].init { }`. + bool allowTrailingClosureAfterCollectionLiteral = + (isa(callee) || isa(callee)); + + if (!allowTrailingClosureAfterCollectionLiteral) + break; + } SmallVector trailingClosures; auto trailingResult = diff --git a/test/expr/closure/trailing.swift b/test/expr/closure/trailing.swift index 4f8591acd2c2c..d970e9e142bd5 100644 --- a/test/expr/closure/trailing.swift +++ b/test/expr/closure/trailing.swift @@ -56,8 +56,7 @@ func notLiterals() { // expected-error@-1 {{consecutive statements on a line must be separated by ';'}} // expected-error@-2 {{closure expression is unused}} expected-note@-2 {{did you mean to use a 'do' statement?}} {{15-15=do }} _ = [42] {} - // expected-error@-1 {{consecutive statements on a line must be separated by ';'}} - // expected-error@-2 {{closure expression is unused}} expected-note@-2 {{did you mean to use a 'do' statement?}} {{12-12=do }} + // expected-error@-1 {{cannot call value of non-function type '[Int]'}} _ = (6765, 10946, 17711) {} // expected-error@-1 {{consecutive statements on a line must be separated by ';'}} // expected-error@-2 {{closure expression is unused}} expected-note@-2 {{did you mean to use a 'do' statement?}} {{28-28=do }} @@ -524,3 +523,58 @@ do { // expected-error@-1:23 {{contextual type for closure argument list expects 1 argument, which cannot be implicitly ignored}}{{24-24= _ in}} } } + +extension Array { + init(_ makeElement: () -> Element) { + self = [makeElement()] + } +} + +extension Dictionary { + init?(_ makeElement: () -> (key: Key, value: Value)?) { + guard let (key, value) = makeElement() else { return nil } + self = [key: value] + } +} + +func testTrailingClosureCollectionInits() { + _ = [String] { "foo" } + _ = [String].init { "foo" } + + _ = [String: Int] { (key: "foo", value: 42) } + _ = [String: Int].init { (key: "foo", value: 42) } + + _ = [String] + { "foo" } + + var foo = "foo" + _ = [foo] // expected-error {{cannot call value of non-function type '[String]'}} + { "bar" } + + if let bar = [String: Int] { (key: "foo", value: 42) } { // expected-warning {{trailing closure in this context is confusable with the body of the statement; pass as a parenthesized argument to silence this warning}} + print(bar) + } + + if let bar = [String: Int]({ (key: "foo", value: 42) }) { + print(bar) + } + + var myArray: Array? = [100] + _ = if let myArray: [Int] { "foo" } else { "var" } + + let myDict = ["foo": 42] + _ = if myDict == ["foo": 42] { + (key: "foo", value: 42) + } else { + (key: "bar", value: 43) + } + + _ = [1] { return [1] } // expected-error {{cannot call value of non-function type '[Int]'}} + _ = [1: 1] { return [1: 1] } // expected-error {{cannot call value of non-function type '[Int : Int]'}} + + _ = [1] // expected-error {{cannot call value of non-function type '[Int]'}} + { return [1] } + + _ = [1: 1] // expected-error {{cannot call value of non-function type '[Int : Int]'}} + { return [1: 1] } +}