VAndrJ
(VAndrJ)
1
When using Value and Type Parameter Packs, I can mix optional and non-optional values.
Example code:
func weakify<T: AnyObject, each U>(_ obj: T?, _ block: @escaping (T, repeat each U) -> Void) -> (repeat each U) -> Void {
return { [weak obj] (values: repeat each U) in
guard let obj else { return }
block(obj, repeat each values)
}
}
class SomeClass {
func someFunc(number: Int, string: String) {
print(number, string)
}
}
let someClass = SomeClass()
var someClosure: ((Int, String?) -> Void)?
someClosure = weakify(someClass) { someClass, number, string in
someClass.someFunc(number: number, string: string)
}
someClosure?(1, "")
It compiles and works, but crashes when passing nil:
someClosure?(1, nil)
1 Like
xwu
(Xiaodi Wu)
2
What version of Swift are you using?
In Xcode 15.3 (Swift 5.10), weakify does not compile, with the error given as follows:
error: 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
VAndrJ
(VAndrJ)
3
Xcode 15.0.1(Swift 5.9), 15.2(Swift 5.9.2), 15.3(Swift 5.10).
This error appears to be a known bug in Playground:
2 Likes
xwu
(Xiaodi Wu)
4
Ah yes, good point.
I can indeed reproduce and reduce the test case:
func f<each U>(_ block: @escaping (repeat each U) -> Void) -> (repeat each U) -> Void {
return { (values: repeat each U) in block(repeat each values) }
}
func g(_ x: Int) { print(x) }
let closure: (Int?) -> Void = f { g($0) }
closure(nil) // compiles; runtime error
It does seem unexpected that the compiler permits this with implicit unwrapping.
cc @hborla
The same is of course not permitted when parameter packs are not involved:
func f2<U>(_ block: @escaping (U) -> Void) -> (U) -> Void {
return { (value: U) in block(value) }
}
func g(_ x: Int) { print(x) }
let closure: (Int?) -> Void = f2 { g($0) } // compile-time error
closure(nil)
2 Likes