// RUN: %target-run-simple-swift | %FileCheck %s // REQUIRES: executable_test enum Either { case first(T) case second(U) } @resultBuilder struct TupleBuilder { static func buildBlock(_ t1: T1) -> (T1) { return (t1) } static func buildBlock(_ t1: T1, _ t2: T2) -> (T1, T2) { return (t1, t2) } static func buildBlock(_ t1: T1, _ t2: T2, _ t3: T3) -> (T1, T2, T3) { return (t1, t2, t3) } static func buildBlock(_ t1: T1, _ t2: T2, _ t3: T3, _ t4: T4) -> (T1, T2, T3, T4) { return (t1, t2, t3, t4) } static func buildBlock( _ t1: T1, _ t2: T2, _ t3: T3, _ t4: T4, _ t5: T5 ) -> (T1, T2, T3, T4, T5) { return (t1, t2, t3, t4, t5) } static func buildIf(_ value: T?) -> T? { return value } static func buildEither(first value: T) -> Either { return .first(value) } static func buildEither(second value: U) -> Either { return .second(value) } static func buildArray(_ array: [T]) -> [T] { return array } } func tuplify(_ cond: Bool, @TupleBuilder body: (Bool) throws -> T) rethrows { print(try body(cond)) } // CHECK: (17, 3.14159, "Hello, DSL", (["nested", "do"], 6), Optional((2.71828, ["if", "stmt"]))) let name = "dsl" tuplify(true) { 17 3.14159 "Hello, \(name.map { $0.uppercased() }.joined())" do { ["nested", "do"] 1 + 2 + 3 } if $0 { 2.71828 ["if", "stmt"] } } // CHECK: ("Empty optional", nil) tuplify(false) { "Empty optional" if $0 { 2.71828 ["if", "stmt"] } } // CHECK: ("chain0", main.Either<(Swift.String, Swift.Double), (Swift.Double, Swift.String)>.second(2.8, "capable")) tuplify(false) { "chain0" if $0 { "marginal" 2.9 } else { 2.8 "capable" } } // CHECK: ("chain1", nil) tuplify(false) { "chain1" if $0 { "marginal" 2.9 } else if $0 { 2.8 "capable" } } // CHECK: ("chain2", Optional(main.Either<(Swift.String, Swift.Double), (Swift.Double, Swift.String)>.first("marginal", 2.9))) tuplify(true) { "chain2" if $0 { "marginal" 2.9 } else if $0 { 2.8 "capable" } } // CHECK: ("chain3", main.Either, main.Either<(Swift.Double, Swift.Double), (Swift.String, Swift.String)>>.first(main.Either<(Swift.String, Swift.Double), (Swift.Double, Swift.String)>.first("marginal", 2.9))) tuplify(true) { "chain3" if $0 { "marginal" 2.9 } else if $0 { 2.8 "capable" } else if $0 { 2.8 1.0 } else { "wild" "broken" } } // CHECK: ("chain4", main.Either, main.Either<(Swift.String, Swift.Int), (Swift.String, Swift.Int)>>, main.Either, (Swift.String, Swift.Int)>>.first tuplify(true) { "chain4" if $0 { "0" 0 } else if $0 { "1" 1 } else if $0 { "2" 2 } else if $0 { "3" 3 } else if $0 { "4" 4 } else if $0 { "5" 5 } else { "6" 6 } } // rdar://50710698 // CHECK: ("chain5", 8, 9) tuplify(true) { "chain5" #if false 6 $0 #else 8 9 #endif } // CHECK: ("getterBuilder", 0, 4, 12) @TupleBuilder var globalBuilder: (String, Int, Int, Int) { "getterBuilder" 0 4 12 } print(globalBuilder) // CHECK: ("funcBuilder", 13, 45.0) @TupleBuilder func funcBuilder(d: Double) -> (String, Int, Double) { "funcBuilder" 13 d } print(funcBuilder(d: 45)) struct MemberBuilders { @TupleBuilder func methodBuilder(_ i: Int) -> (String, Int) { "methodBuilder" i } @TupleBuilder static func staticMethodBuilder(_ i: Int) -> (String, Int) { "staticMethodBuilder" i + 14 } @TupleBuilder var propertyBuilder: (String, Int) { "propertyBuilder" 12 } } // CHECK: ("staticMethodBuilder", 27) print(MemberBuilders.staticMethodBuilder(13)) let mbuilders = MemberBuilders() // CHECK: ("methodBuilder", 13) print(mbuilders.methodBuilder(13)) // CHECK: ("propertyBuilder", 12) print(mbuilders.propertyBuilder) // https://github.com/apple/swift/issues/53840 // Operator builders infix operator ^^^ func ^^^ (lhs: Int, @TupleBuilder rhs: (Int) -> (String, Int)) -> (String, Int) { return rhs(lhs) } // CHECK: ("hello", 6) print(5 ^^^ { "hello" $0 + 1 }) struct Tagged { let tag: Tag let entity: Entity } protocol Taggable { } extension Taggable { func tag(_ tag: Tag) -> Tagged { return Tagged(tag: tag, entity: self) } } extension Int: Taggable { } extension String: Taggable { } extension Double: Taggable { } @resultBuilder struct TaggedBuilder { static func buildBlock() -> () { } static func buildBlock(_ t1: Tagged) -> Tagged { return t1 } static func buildBlock(_ t1: Tagged, _ t2: Tagged) -> (Tagged, Tagged) { return (t1, t2) } static func buildBlock(_ t1: Tagged, _ t2: Tagged, _ t3: Tagged) -> (Tagged, Tagged, Tagged) { return (t1, t2, t3) } static func buildBlock(_ t1: Tagged, _ t2: Tagged, _ t3: Tagged, _ t4: Tagged) -> (Tagged, Tagged, Tagged, Tagged) { return (t1, t2, t3, t4) } static func buildBlock( _ t1: Tagged, _ t2: Tagged, _ t3: Tagged, _ t4: Tagged, _ t5: Tagged ) -> (Tagged, Tagged, Tagged, Tagged, Tagged) { return (t1, t2, t3, t4, t5) } static func buildIf(_ value: Tagged?) -> Tagged? { return value } } enum Color { case red, green, blue } func acceptColorTagged(@TaggedBuilder body: () -> Result) { print(body()) } struct TagAccepter { static func acceptTagged(@TaggedBuilder body: () -> Result) { print(body()) } } func testAcceptColorTagged(b: Bool, i: Int, s: String, d: Double) { // FIXME: When we support buildExpression, drop the "Color" prefix // CHECK: Tagged< acceptColorTagged { i.tag(Color.red) s.tag(Color.green) d.tag(Color.blue) } // FIXME: When we support buildExpression, drop the "Color" prefix // CHECK: Tagged< TagAccepter.acceptTagged { i.tag(Color.red) s.tag(Color.green) d.tag(Color.blue) } // CHECK: Tagged< TagAccepter.acceptTagged { () -> Tagged in if b { return i.tag(Color.green) } else { return i.tag(Color.blue) } } } testAcceptColorTagged(b: true, i: 17, s: "Hello", d: 3.14159) // Use buildExpression() when it's available. enum Component { case string(StaticString) case floating(Double) case color(Color) indirect case array([Component]) indirect case optional(Component?) } @resultBuilder struct ComponentBuilder { static func buildExpression(_ string: StaticString) -> Component { return .string(string) } static func buildExpression(_ float: Double) -> Component { return .floating(float) } static func buildExpression(_ color: Color) -> Component { return .color(color) } static func buildBlock(_ components: Component...) -> Component { return .array(components) } static func buildIf(_ value: Component?) -> Component { return .optional(value) } } func acceptComponentBuilder(@ComponentBuilder _ body: () -> Component) { print(body()) } func colorWithAutoClosure(_ color: @autoclosure () -> Color) -> Color { return color() } var trueValue = true acceptComponentBuilder { "hello" if trueValue { 3.14159 colorWithAutoClosure(.red) } .red } // CHECK: array([main.Component.string("hello"), main.Component.optional(Optional(main.Component.array([main.Component.floating(3.14159), main.Component.color(main.Color.red)]))), main.Component.color(main.Color.red)]) // rdar://53325810 // Test that we don't have problems with expression pre-checking when // type-checking an overloaded result-builder call. In particular, // we need to make sure that expressions in the closure are pre-checked // before we build constraints for them. Note that top-level expressions // that need to be rewritten by expression prechecking (such as the operator // sequences in the boolean conditions and statements below) won't be // rewritten in the original closure body if we just precheck the // expressions produced by the result-builder transformation. struct ForEach1 { var data: Data var content: (Data.Element) -> Content func show() { print(content(data.first!)) print(content(data.last!)) } } extension ForEach1 where Data.Element: StringProtocol { // Checking this overload shouldn't trigger inappropriate caching that // affects checking the next overload. init(_ data: Data, @TupleBuilder content: @escaping (Data.Element) -> Content) { self.init(data: data, content: content) } } extension ForEach1 where Data == Range { // This is the overload we actually want. init(_ data: Data, @TupleBuilder content: @escaping (Int) -> Content) { self.init(data: data, content: content) } } let testForEach1 = ForEach1(-10 ..< 10) { i in "testForEach1" if i < 0 { "begin" i < -5 } else { i > 5 "end" } } testForEach1.show() // CHECK: ("testForEach1", main.Either<(Swift.String, Swift.Bool), (Swift.Bool, Swift.String)>.first("begin", true)) // CHECK: ("testForEach1", main.Either<(Swift.String, Swift.Bool), (Swift.Bool, Swift.String)>.second(true, "end")) func test_single_stmt_closure_support() { @resultBuilder struct MyBuilder { static func buildBlock(_ numbers: Int...) -> Int { return 42 } } func test(@MyBuilder builder: () -> Int) -> Int { builder() } let _ = test { 0 } // ok } // Check a case involving nested closures that refer to parameters of their // enclosing closures. struct X { init(_ c: C, @TupleBuilder body: (C.Element) -> T) { } } struct Y { init(@TupleBuilder body: () -> T) { } } struct Z { init(@TupleBuilder body: () -> T) { } } func testNestedClosuresWithDependencies(cond: Bool) { tuplify(cond) { _ in X([1, 2, 3]) { x in Y { Z { x 1 } } } } } // Check that we can handle multiple conditions in an 'if' statement. func testIfConditions(cond: Bool, c1: Bool, i1: Int, i2: Int) { tuplify(cond) { x in "testIfConditions" if i1 == i2, c1, x { 1 "hello" } 3.14159 } } testIfConditions(cond: true, c1: true, i1: 1, i2: 1) // CHECK: testIfConditions // CHECK-SAME: hello // Use a "let" declaration within a result builder. tuplify(true) { c in "testLetDeclarations" let (a, b) = (c, c && true) if a == b { "hello" b } a } // CHECK: testLetDeclarations" // CHECK-SAME: hello // CHECK-SAME: true // Use if let / if case with various forms of decomposition. func getOptionalInt(_: Bool) -> Int? { return 25 } enum E { case a case b(Int, String?) } func getE(_ i: Int) -> E { switch i { case 0: return .a case 1: return .b(17, "hello") case 2: return .b(42, nil) default: fatalError("Unhandled case") } } func test_labeled_splats() { enum E { case multi(a: String, b: String) case tuple((a: Int, b: Int)) case single(result: Int) case single_multi(result: (a: Int, q: String)) } func test_answer(_: String) -> Int { 42 } func test_question(_: Int) -> String { "ultimate question" } let e: E = E.single(result: 42) tuplify(true) { _ in switch e { case .single(let result): test_question(result) case let .single_multi(result): test_answer(result.q) test_question(result.a) case let .multi(value): // tuple splat preserves labels test_answer(value.a) test_answer(value.b) case let .tuple(a: a, b: b): // un-splat preserves labels too test_question(a) test_question(b) } // compound names still work with and without splat switch e { case .single(_): 42 case .single_multi(result: (let a, let q)): test_answer(q) test_question(a) case let .multi(a: a, b: b): test_answer(a) test_answer(b) case let .tuple((a: a, b: b)): test_question(a) test_question(b) } // no labels, no problem regardless of splatting switch e { case .single(_): 42 case let .single_multi(result: (a, q)): test_question(a) test_answer(q) case let .multi(a, b): test_answer(a) test_answer(b) case let .tuple((a, b)): test_question(a) test_question(b) } } } tuplify(true) { c in "testIfLetMatching" if let theValue = getOptionalInt(c) { theValue + 17 } if case let .a = getE(0) { "matched without payload" } if case let .b(i, s?) = getE(1) { "matched with payload" s + "!" i + 17 } if case let .b(i, s?) = getE(2) { fatalError("cannot match this") } else { "intentional mismatch" } } // CHECK: testIfLetMatching // CHECK-SAME: Optional(42) // CHECK-SAME: Optional("matched without payload") // CHECK-SAME: "matched with payload", "hello!", 34 // CHECK-SAME: "intentional mismatch" class Super { } class Sub : Super { func subMethod() -> String { return "subMethod" } } func getSuper(wantSubclass: Bool) -> Super { return wantSubclass ? Sub() : Super() } tuplify(true) { c in "testIfLetAsMatching" if case let sub as Sub = getSuper(wantSubclass: true) { sub.subMethod() } if case let sub as Sub = getSuper(wantSubclass: false) { fatalError("cannot match this") } else { "Superclass instance" } } // CHECK: testIfLetAsMatching // CHECK-SAME: "subMethod" // CHECK-SAME: "Superclass instance" // switch statements func testSwitch(_ e: E) { tuplify(true) { c in "testSwitch" switch e { case .a: "a" case .b(let i, let s?): i * 2 s + "!" case .b(let i, nil): "just \(i)" } } } func testExistingPatternsInCaseStatements() { tuplify(true) { c in switch false { case (c): 1 // Ok default: 0 } } var arr: [Int] = [] tuplify(true) { c in let n = arr.endIndex switch arr.startIndex { case (n): 1 // Ok default: 0 } } } // CHECK: testSwitch // CHECK-SAME: first(main.Either.first("a")) testSwitch(getE(0)) // CHECK: testSwitch // CHECK-SAME: first(main.Either.second(34, "hello!")) testSwitch(getE(1)) // CHECK: testSwitch // CHECK-SAME: second("just 42") testSwitch(getE(2)) func testSwitchCombined(_ eIn: E) { var e = eIn tuplify(true) { c in "testSwitchCombined" switch e { case .a: "a" case .b(let i, _?), .b(let i, nil): "just \(i)" } } } // CHECK: testSwitchCombined // CHECK-SAME: main.Either.first("a") testSwitchCombined(getE(0)) // CHECK: testSwitchCombined // CHECK-SAME: second("just 17") testSwitchCombined(getE(1)) // CHECK: testSwitchCombined // CHECK-SAME: second("just 42") testSwitchCombined(getE(2)) // Test buildOptional(_:) as an alternative to buildIf(_:). @resultBuilder struct TupleBuilderWithOpt { static func buildBlock(_ t1: T1) -> (T1) { return (t1) } static func buildBlock(_ t1: T1, _ t2: T2) -> (T1, T2) { return (t1, t2) } static func buildBlock(_ t1: T1, _ t2: T2, _ t3: T3) -> (T1, T2, T3) { return (t1, t2, t3) } static func buildBlock(_ t1: T1, _ t2: T2, _ t3: T3, _ t4: T4) -> (T1, T2, T3, T4) { return (t1, t2, t3, t4) } static func buildBlock( _ t1: T1, _ t2: T2, _ t3: T3, _ t4: T4, _ t5: T5 ) -> (T1, T2, T3, T4, T5) { return (t1, t2, t3, t4, t5) } static func buildOptional(_ value: T?) -> T? { return value } static func buildEither(first value: T) -> Either { return .first(value) } static func buildEither(second value: U) -> Either { return .second(value) } } func tuplifyWithOpt(_ cond: Bool, @TupleBuilderWithOpt body: (Bool) -> T) { print(body(cond)) } tuplifyWithOpt(true) { c in "1" 3.14159 } // Test for-each loops with buildArray. // CHECK: testForEach // CHECK-SAME: (1, "separator") // CHECK-SAME: (2, "separator") // CHECK-SAME: (3, "separator") // CHECK-SAME: (4, "separator") // CHECK-SAME: (5, "separator") // CHECK-SAME: (6, "separator") // CHECK-SAME: (7, "separator") // CHECK-SAME: (8, "separator") // CHECK-SAME: (9, "separator") // CHECK-SAME: (10, "separator") tuplify(true) { c in "testForEach" for i in 0 ..< (c ? 10 : 5) { i + 1 "separator" } } // Test the use of result builders partly implemented through a protocol. indirect enum FunctionBuilder { case expression(Expression) case block([FunctionBuilder]) case either(Either) case optional(FunctionBuilder?) } protocol FunctionBuilderProtocol { associatedtype Expression typealias Component = FunctionBuilder associatedtype Return static func buildExpression(_ expression: Expression) -> Component static func buildBlock(_ components: Component...) -> Component static func buildOptional(_ optional: Component?) -> Component static func buildArray(_ components: [Component]) -> Component static func buildLimitedAvailability(_ component: Component) -> Component static func buildFinalResult(_ components: Component) -> Return } extension FunctionBuilderProtocol { static func buildExpression(_ expression: Expression) -> Component { .expression(expression) } static func buildBlock(_ components: Component...) -> Component { .block(components) } static func buildOptional(_ optional: Component?) -> Component { .optional(optional) } static func buildArray(_ components: [Component]) -> Component { .block(components) } static func buildLimitedAvailability(_ component: Component) -> Component { component } } @resultBuilder enum ArrayBuilder: FunctionBuilderProtocol { typealias Expression = E typealias Component = FunctionBuilder typealias Return = [E] static func buildFinalResult(_ components: Component) -> Return { switch components { case .expression(let e): return [e] case .block(let children): return children.flatMap(buildFinalResult) case .either(.first(let child)): return buildFinalResult(child) case .either(.second(let child)): return buildFinalResult(child) case .optional(let child?): return buildFinalResult(child) case .optional(nil): return [] } } } func buildArray(@ArrayBuilder build: () -> [String]) -> [String] { return build() } let a = buildArray { "1" "2" if Bool.random() { "maybe 3" } } // CHECK: ["1", "2" print(a) // Throwing in result builders. enum MyError: Error { case boom } // CHECK: testThrow do { print("testThrow") try tuplify(true) { c in "ready to throw" throw MyError.boom } } catch MyError.boom { // CHECK: caught it! print("caught it!") } catch { fatalError("Threw something else?") } // CHECK: testStoredProperties struct MyTupleStruct { @TupleBuilder let first: () -> T @TupleBuilder let second: U } print("testStoredProperties") let ts1 = MyTupleStruct { 1 "hello" if true { "conditional" } } second: { 3.14159 "blah" } // CHECK: MyTupleStruct<(Int, String, Optional), (Double, String)>(first: (Function), second: (3.14159, "blah")) print(ts1) // Make sure that `weakV` is `Test?` and not `Test??` func test_weak_optionality_stays_the_same() { class Test { func fn() -> Int { 42 } } tuplify(true) { c in weak var weakV: Test? = Test() 0 if let v = weakV { v.fn() } } } enum WrapperEnum where Wrapped: RawRepresentable { case known(Wrapped) static func ~= (lhs: Wrapped, rhs: WrapperEnum) -> Bool where Wrapped: Equatable { switch rhs { case .known(let wrapped): return wrapped == lhs } } } func test_custom_tilde_equals_operator_matching() { @resultBuilder struct Builder { static func buildBlock(_ t: T) -> T { t } static func buildEither(first: T) -> T { first } static func buildEither(second: T) -> T { second } } enum TildeTest : String { case test = "test" } struct S {} struct MyView { var entry: WrapperEnum @Builder var body: S { switch entry { case .test: S() // Ok although `.test` comes from `TildeTest` instead of `WrapperEnum` case .known(_): S() // Ok - `.known` comes directly from `WrapperEnum` } } } } struct Values { var values: T init(values: T) { self.values = values } func map(_ f: (T) -> R) -> Values { .init(values: f(values)) } } @resultBuilder enum NestedTupleBuilder { static func buildPartialBlock(first x: T) -> Values { .init(values: x) } static func buildPartialBlock( accumulated: Values, next: U ) -> Values<(T, U)> { .init(values: (accumulated.values, next)) } } extension Values { init(@NestedTupleBuilder nested values: () -> Self) { self = values() } } let nestedValues = Values(nested: { 1 "2" 3.0 "yes" }) print(nestedValues) @resultBuilder enum NestedTupleBuilder_Not { @available(*, unavailable) static func buildPartialBlock(first x: T) -> Values { .init(values: x) } @available(*, unavailable) static func buildPartialBlock( accumulated: Values, next: U ) -> Values<(T, U)> { .init(values: (accumulated.values, next)) } #if os(macOS) @available(macOS 9999, *) static func buildPartialBlock(first x: Never) -> Values { fatalError() } @available(macOS 9999, *) static func buildPartialBlock( accumulated: Values, next: Never ) -> Values { fatalError() } #endif // This one will be called because no `buildPartialBlock` is available. static func buildBlock(_ x: Any...) -> Values<[Any]> { .init(values: x) } } extension Values { init(@NestedTupleBuilder_Not nested_not values: () -> Self) { self = values() } } let nestedValues_not = Values(nested_not: { 1 "2" 3.0 "yes" }) print(nestedValues_not) // CHECK: Values>(values: [1, "2", 3.0, "yes"]) @resultBuilder enum FlatTupleBuilder { static func buildExpression(_ x: T) -> Values { .init(values: x) } static func buildPartialBlock(first x: Values) -> Values { .init(values: x.values) } static func buildPartialBlock( accumulated: Values, next: Values ) -> Values<(T, N)> { .init(values: (accumulated.values, next.values)) } static func buildPartialBlock( accumulated: Values<(T0, T1)>, next: Values ) -> Values<(T0, T1, N)> { .init(values: (accumulated.values.0, accumulated.values.1, next.values)) } static func buildPartialBlock( accumulated: Values<(T0, T1, T2)>, next: Values ) -> Values<(T0, T1, T2, N)> { .init(values: (accumulated.values.0, accumulated.values.1, accumulated.values.2, next.values)) } static func buildPartialBlock( accumulated: Values<(T0, T1, T2, T3)>, next: Values ) -> Values<(T0, T1, T2, T3, N)> { .init(values: (accumulated.values.0, accumulated.values.1, accumulated.values.2, accumulated.values.3, next.values)) } static func buildBlock(_ x: Never...) -> Values<()> { assert(x.isEmpty, "I should never be called unless it's nullary") return .init(values: ()) } static func buildEither(first: T) -> T { first } static func buildEither(second: T) -> T { second } static func buildOptional(_ x: Values?) -> Values { x?.map { $0 } ?? .init(values: nil) } static func buildLimitedAvailability(_ x: Values) -> Values { x } } extension Values { init(@FlatTupleBuilder flat values: () -> Self) { self = values() } } let flatValues0 = Values(flat: {}) print(flatValues0) // CHECK: Values<()>(values: ()) let flatValues1 = Values(flat: { 1 "2" 3.0 }) print(flatValues1) // CHECK: Values<(Int, String, Double)>(values: (1, "2", 3.0)) let flatValues2 = Values(flat: { 1 "2" let y = 3.0 + 4.0 #if false "not gonna happen" #endif if true { "yes" } else { "no" } #warning("Beware of pairwise block building") #if true if false { "nah" } if #available(*) { 5.0 } #endif }) print(flatValues2) // CHECK: Values<(Int, String, String, Optional, Optional)>(values: (1, "2", "yes", nil, Optional(5.0))) struct Nil: CustomStringConvertible { var description: String { "nil" } } struct Cons: CustomStringConvertible { var head: Head var tail: Tail var description: String { "(cons \(String(reflecting: head)) \(tail))" } } @resultBuilder enum ListBuilder { static func buildBlock() -> Nil { Nil() } static func buildPartialBlock(first x: T) -> Cons { .init(head: x, tail: Nil()) } static func buildPartialBlock(accumulated: T, next: New) -> Cons { .init(head: next, tail: accumulated) } static func buildBlock(_ x: T...) -> [T] { fatalError("I should never be called!") } } func list(@ListBuilder f: () -> T) -> T { f() } let list0 = list {} print(list0) // CHECK: nil let list1 = list { "1" } print(list1) // Check: (cons 1 nil) let list2 = list { 1 2 } print(list2) // CHECK: (cons 2 (cons 1 nil)) let list3 = list { 1 list { 2.0 "3" } "4" } print(list3) // CHECK: (cons "4" (cons (cons "3" (cons 2.0 nil)) (cons 1 nil))) func test_callAsFunction_with_resultBuilder() { struct CallableTest { func callAsFunction(@TupleBuilder _ body: (Bool) -> T) { print(body(true)) } } CallableTest() { 0 "with parens" $0 } CallableTest { 1 "without parens" $0 } } test_callAsFunction_with_resultBuilder() // CHECK: (0, "with parens", true) // CHECK: (1, "without parens", true) do { struct S { static func test(@TupleBuilder _ body: (Bool) -> T) -> S { print(body(true)) return .init() } } let _: S? = .test { 42 "" [$0] } // CHECK: (42, "", [true]) } do { @resultBuilder struct MyBuilder { static func buildBlock(_ t1: T1) -> (T1) { return (t1) } static func buildBlock(_ t1: T1, _ t2: T2) -> (T1, T2) { return (t1, t2) } static func buildOptional(_ value: T?) -> T { return value! } static func buildEither(first value: T) -> T { return value } static func buildEither(second value: U) -> U { return value } } func test(@MyBuilder _ builder: (Int) -> T) { print(builder(42)) } test { if $0 < 0 { "\($0)" } else if $0 == 42 { "the answer" } } // CHECK: the answer } protocol TestIfSequences { } struct A: TestIfSequences {} struct B: TestIfSequences {} struct C: TestIfSequences {} struct D: TestIfSequences {} func testOptionalIfElseSequences() { func check(_ v: TestIfSequences, @TupleBuilder body: (TestIfSequences) throws -> T) rethrows { print(try body(v)) } check(A()) { v in if let a = v as? A { a } else if let b = v as? B { b } else if let c = v as? C { c } } check(B()) { v in if let a = v as? A { a } else if let b = v as? B { b } else if let c = v as? C { c } } check(C()) { v in if let a = v as? A { a } else if let b = v as? B { b } else if let c = v as? C { c } } check(D()) { v in if let a = v as? A { a } else if let b = v as? B { b } else if let c = v as? C { c } else { D() } } check(A()) { v in if let a = v as? A { a } else { if let b = v as? B { b } if let c = v as? C { c } else if let d = v as? D { d } } } check(B()) { v in if let a = v as? A { a } else { if let b = v as? B { b } if let c = v as? C { c } else if let d = v as? D { d } } } check(C()) { v in if let a = v as? A { a } else { if let b = v as? B { b } if let c = v as? C { c } else if let d = v as? D { d } } } check(D()) { v in if let a = v as? A { a } else { if let b = v as? B { b } if let c = v as? C { c } else if let d = v as? D { d } } } } testOptionalIfElseSequences() // CHECK: Optional(main.Either, main.C>.first(main.Either.first(main.A()))) // CHECK-NEXT: Optional(main.Either, main.C>.first(main.Either.second(main.B()))) // CHECK-NEXT: Optional(main.Either, main.C>.second(main.C())) // CHECK-NEXT: second(main.Either.second(main.D())) // CHECK-NEXT: first(main.A()) // CHECK-NEXT: second(Optional(main.B()), nil) // CHECK-NEXT: second(nil, Optional(main.Either.first(main.C()))) // CHECK-NEXT: second(nil, Optional(main.Either.second(main.D()))) // rdar://106364495 - ambiguous use of `buildFinalResult` func testBuildFinalResultDependentOnContextualType() { @resultBuilder struct MyBuilder { static func buildBlock(_ v: Int) -> Int { v } static func buildFinalResult(_ v: Int) -> Int { v } static func buildFinalResult(_ v: Int) -> String { "" } } func test(@MyBuilder _ fn: () -> Int?) { print(fn()) } test { 42 } } testBuildFinalResultDependentOnContextualType() // CHECK: Optional(42) protocol TestLeadingDot { } @resultBuilder struct IntBuilder { static func buildBlock(_ v: Int) -> Int { print("buildBlock: \(v)") return v } } extension TestLeadingDot where Self == NoopImpl { static func test(@IntBuilder builder: () -> Int) -> NoopImpl { builder() return NoopImpl() } } struct NoopImpl : TestLeadingDot { } @available(SwiftStdlib 5.1, *) func testLeadingDotSyntax(v: Int) { let x: some TestLeadingDot = .test { v } } if #available(SwiftStdlib 5.1, *) { testLeadingDotSyntax(v: -42) } else { print("buildBlock: -42") // Fallback for the back deployment bots } // CHECK: buildBlock: -42