George
1
Swift has a really powerful feature where the generic type of a value can be inferred from a function with an opaque return value.
For example:
func buildSequence() -> some Sequence<Int> {
return [0, 1, 2]
}
struct Foo<S: Sequence<Int>> {
init(_ builder: () -> S) { }
}
func bar() {
/// `foo` is inferred to have type `Foo<some Sequence<Int>>`
let foo = Foo(buildSequence)
}
Unfortunately, I can't figure out a way to have this functionality compose.
Consider the following code:
extension Foo {
init<IntermediateS: Sequence<Int>>(wrap: Bool, builder: () -> IntermediateS) {
assert(wrap)
self.init({
// The following doesn't work because `S` is fixed and we are returning `some Sequence<Int>`
builder().wrap()
})
}
}
If this wasn't an initializer, but a simple function, everything would work as expected, because the generic argument isn't fixed:
func baz() -> some Sequence {
buildSequence().wrap()
}
Is this just a limitation of the compiler, or is there a deeper issue here? Is there a workaround to get the Foo extension initializer to infer S from the return value (other than declaring it as a function)?