I have a struct using variadic generics and I'm getting this error:
error: cannot use a value of protocol type in embedded Swift
30 |
31 | target.draw(
32 | VStack {
| `- error: cannot use a value of protocol type in embedded Swift
33 | TileText("Hello, world!", color: .Pico.white)
34 | TileText("Hello, world?", color: .Pico.white)
:
38 | )
39 | }
40 | }
But there are no protocol types used anywhere, VStack is generic and uses the for in repeat each loop to draw the nested types. There's no values of protocol types anywhere, not in the result builder, not in the implementation, and definitely not in TileText. Are variadic generics broken in embedded Swift?
Variadic generics are not yet supported in Embedded Swift. Behind the scenes they currently rely on similar (if not the same) metadata as existentials, and require compiler changes before they can be used in the Embedded mode.
@resultBuilder
public struct FlatteningDrawableBuilder {
public static func buildBlock(_ d0: some Drawable) -> [Image] {
[d0.flatten()]
}
public static func buildBlock(_ d0: some Drawable, _ d1: some Drawable) -> [Image] {
[
d0.flatten(),
d1.flatten()
]
}
...
}
But this allocates and evaluates all the pixels instead of being lazy, losing any additional information the type had, which is important for later figuring out which ones have click events and such. Is there a workaround for this, like creating vtables manually? I don't know what that would look like in Swift.
I don’t know a lot about your use case, but this looks like exactly the kind of thing that buildPartialBlock is for (avoiding tons of overloads on buildBlock).
There’s no inherent reason variadic generics can’t be supported in embedded Swift in the same manner as ordinary generics, via specialization. The problem here is that the SIL optimizer isn’t very good at specializing away variadic generics. So runtime metadata calls remain in the code, and it gets diagnosed.