Problems with binding and unboxing an internal associated type

Hi guys, I've been stuck at this point for a while and I don't know if it's because of an unpacking limitation or that I'm doing something wrong.
To start with I have a Template which is a protocol that has an associated type which is a View.

I am having a complication with the existential types at the time of doing the unpacking when the type is inside a SwiftUI Binding with the structure that I have explained, here the code.

    @Binding var input: any InputTemplate

    var body: some View {
        self.SomeInputBar(self.$input)
    }
    
    private func SomeInputBar<T: InputTemplate>(_ input: Binding<T>) -> AnyView {
        AnyView(
            T.InputBar(
                input: input
            )
        )
    }

The compiler gives me the following error

Type 'any InputTemplate' cannot conform to 'InputTemplate'

I have fixed it as follows but I don't like the solution at all

    @Binding var input: any InputTemplate
    
    var body: some View {
        self.SomeInputBar(self.input)
            .task {
                state.executeOnAppearEvent(input: input)
            }
            .id(input.id)
    }
    
    private func SomeInputBar<T: InputTemplate>(_ input: T) -> AnyView {
        AnyView(
            T.InputBar(
                input: Binding(
                    get: { input },
                    set: { self.input = $0 }
                )
            )
        )
    }

Could one of you help me with this? I think there's something I'm not understanding.

I believe that binding generic types doesn't work. For example, it should be relatively clear why this won't work:

func sum<T: AdditiveArithmetic>(arr: Array<T>) -> T {
  return arr.reduce(into: T.zero, +=)
}

let myArray: Array<any AdditiveArithmetic> = [(1 as Int), (2.0 as Double)]
_ = sum(arr: myArray) // What is T? It can't be Int nor Double

Currently, the type system has no way to encode whether it's possible to do the Foo<any Bar> -> Foo<some Bar> transformation, so the compiler conservatively assumes that it never is.

Would it be possible to make the view itself generic over the input type?

struct EnclosingView<T: InputTemplate>: View {
  @Binding var input: T

  var body: some View {
    someInputBar($input)
  }

  private func someInputBar(_ input: Binding<T>) -> AnyView {
    // ...
  }
}
1 Like

Thanks for the explanation, that makes sense,

But the example you have given just moves the problem up, at some point I have to convert the any into some somewhere and it has to be inside a Binding.
It really comes from an array, so it can't be opaque, it has to be an existential type and somewhere have to be the unboxing.

Ok, I have seen that the optional type also has this limitation too :smiling_face_with_tear:, it is a pity, it is a very big limitation in the potential of my code.

Edit:
I tried even this approach without expectatives, but does not work neither

I tried doing it using as? but neither

self.input as? Binding

but doesnt work neither should work it, but the compiler said that

Cast from 'any InputTemplate' to unrelated type 'Binding' always fails
Cast from 'Binding' to unrelated type 'Binding' always fails

But I think the as? should have worked, I was very surprised it didn't work.

Any clue about that please?