Skip to content

Commit fd916f9

Browse files
committed
[Function builders] Add support for buildExpression().
If a function builder type has a static method buildExpression(), use it to pass through each expression whose value will become part of the final result. This is part of the function builders pitch that had not yet been implemented.
1 parent 43da5c9 commit fd916f9

File tree

3 files changed

+55
-2
lines changed

3 files changed

+55
-2
lines changed

include/swift/AST/KnownIdentifiers.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ IDENTIFIER_(bridgeToObjectiveC)
3434
IDENTIFIER(buildBlock)
3535
IDENTIFIER(buildDo)
3636
IDENTIFIER(buildEither)
37+
IDENTIFIER(buildExpression)
3738
IDENTIFIER(buildIf)
3839
IDENTIFIER(callAsFunction)
3940
IDENTIFIER(Change)

lib/Sema/BuilderTransform.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,15 @@ class BuilderClosureVisitor
169169
}
170170

171171
auto expr = node.get<Expr *>();
172-
if (wantExpr)
173-
expr = new (ctx) OneWayExpr(expr);
172+
if (wantExpr) {
173+
if (builderSupports(ctx.Id_buildExpression)) {
174+
expr = buildCallIfWanted(expr->getLoc(), ctx.Id_buildExpression,
175+
{ expr }, { Identifier() },
176+
/*allowOneWay=*/true);
177+
} else {
178+
expr = new (ctx) OneWayExpr(expr);
179+
}
180+
}
174181

175182
expressions.push_back(expr);
176183
}

test/Constraints/function_builder.swift

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,51 @@ func testAcceptColorTagged(b: Bool, i: Int, s: String, d: Double) {
316316

317317
testAcceptColorTagged(b: true, i: 17, s: "Hello", d: 3.14159)
318318

319+
// Use buildExpression() when it's available.
320+
enum Component {
321+
case string(StaticString)
322+
case floating(Double)
323+
case color(Color)
324+
indirect case array([Component])
325+
indirect case optional(Component?)
326+
}
327+
328+
@_functionBuilder
329+
struct ComponentBuilder {
330+
static func buildExpression(_ string: StaticString) -> Component {
331+
return .string(string)
332+
}
333+
334+
static func buildExpression(_ float: Double) -> Component {
335+
return .floating(float)
336+
}
337+
338+
static func buildExpression(_ color: Color) -> Component {
339+
return .color(color)
340+
}
341+
342+
static func buildBlock(_ components: Component...) -> Component {
343+
return .array(components)
344+
}
345+
346+
static func buildIf(_ value: Component?) -> Component {
347+
return .optional(value)
348+
}
349+
}
350+
351+
func acceptComponentBuilder(@ComponentBuilder _ body: () -> Component) {
352+
print(body())
353+
}
354+
355+
acceptComponentBuilder {
356+
"hello"
357+
if true {
358+
3.14159
359+
}
360+
.red
361+
}
362+
// CHECK: array([main.Component.string("hello"), main.Component.optional(Optional(main.Component.array([main.Component.floating(3.14159)]))), main.Component.color(main.Color.red)])
363+
319364
// rdar://53325810
320365

321366
// Test that we don't have problems with expression pre-checking when

0 commit comments

Comments
 (0)