Generics and Function Builders

Hi there,
I have a question about Function Builders and Generics:

The TL;DR is:
I have a function builder that is generic with type constraints. The builder simply collects a variadic number of elements of a related generic type into an array.
When I use the function builder, the generic type cannot be inferred even though I would assume that this was possible.

The smallest example I could find that demonstrates the issue is:

public protocol FieldProvider {
    associatedtype Field
    func value(for field: Field) -> String?

public enum TemplateItem<F: FieldProvider> {
    case staticText(String)
    case field(F.Field)

public class GenericFunctionBuilder<F: FieldProvider> {
    static func buildBlock(_ children: TemplateItem<F>...) -> [TemplateItem<F>] {

struct Generic<F: FieldProvider> {
    let items: [TemplateItem<F>]
    public init(items: [TemplateItem<F>]) {
        self.items = items
    public init(@GenericFunctionBuilder<F> content: () -> [TemplateItem<F>]) {
        self.items = content()

// Usage

struct Business {
    enum Fields {
        case name
    var name: String

extension Business: FieldProvider {
    typealias Field = Fields

    func value(for field: Business.Fields) -> String? {
        switch field {
        case .name:
            return name

func createUsingEnum() -> Generic<Business> {
    Generic(items: [

func create() -> Generic<Business> {
    Generic {

As can be seen in createUsingEnum() the generic type Business can be inferred.
But in the function builder version create(), the type cannot be inferred and I need to spell out the full generic type.

As far as I can tell, the compiler should have enough information to infer the type.
I have tried building with Swift 5.1, the latest 5.2 snapshot and latest master branch snapshot. All with similar results.

I am curious to hear whether it ought to be possible for the compiler to infer the type - full well knowing that function builders have not yet been officially accepted and added to the language.

Or might there be some logical fallacy in what I am attempting to do?

Note that the example above is abbreviated a bit - with my small proof-of-concept I would be able to use the small DSL like this:

let t: Template<Business> =
    Template {
        SubField(employees) {

while with my troubles with automatic inference I have to write:

let t: Template<Business> =
    Template {
        Text("Business") as Template<Business>.Item
        Field(.name) as Template<Business>.Item
        SubField(employees) {
            Text("Name") as Template<Employee>.Item
            Field(.employeeName) as Template<Employee>.Item
        } as Template<Business>.Item
1 Like

I found the discussion about this and it appears that this will be possible in the future! :heart:

Were you able to get this working in Swift 5.3?

Terms of Service

Privacy Policy

Cookie Policy