This code fails to build with the error message "Cannot fully abstract a value of variadic function type '(repeat each U) -> ()' because different contexts will not be able to reliably agree on a calling convention; try wrapping it in a struct"
func f<T, each U>(
instance: T,
kp: KeyPath<T, (repeat each U) -> ()>,
args: (repeat each U)
) {
instance[keyPath: kp](repeat each args)
}
This isn't discussed anywhere in the original SE, but I'm going to assume that this is not a bug, and is intended.
But why is it intended, and how does "wrapped it in a struct" help? I tried doing so, to the best of my understanding, and got an increasing strange series of errors, culminating in the compiler crashing while generating SIL.
@convention(swift)
doesn't help, so I'm guessing this has more to do with thin, thick, etc conventions, of which my understanding is dim at best.
I'm happy to post what I'm Really Trying to Do if it would be helpful, and I may have the possibility to convert from a "raw" parameter pack to a variadic tuple for the keypath type, though I want to be able to pass the args
as a non-tuple ideally.
So there's two asks to this question: first, for my understanding, why does this happen. Second, any pointers on how to work around it?
EDIT: I tried wrapping the args in a tuple, which gets past type checking, then crashes while generating SIL:
func f<T, each U>(
instance: T,
kp: KeyPath<T, ((repeat each U)) -> ()>,
args: (repeat each U)
) {
instance[keyPath: kp]((repeat each args))
}
One More EDIT: I guess this works:
struct S<T> {
var wrapped: T
}
func f<T, each U>(
instance: T,
kp: KeyPath<T, (S<(repeat each U)>) -> ()>,
args: (repeat each U)
) {
instance[keyPath: kp](.init(wrapped: (repeat each args)))
}
I originally thought that this was about wrapping the function, not the arguments, which was kind of silly in retrospect..