VAndrJ
(VAndrJ)
March 5, 2024, 7:33am
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)
March 6, 2024, 7:34pm
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)
March 6, 2024, 7:45pm
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:
opened 06:51PM - 25 Oct 23 UTC
bug
compiler
SILGen
generics
closures
expressions
swift 5.9
unexpected error
variadic generics
<!--
This repository tracks issues related to the implementation of the Swift
… compiler, standard library, runtime, and tools that provide IDE support for
Swift (e.g. code completion). If the bug relates to the implementation of a
proprietary (closed-source) Apple framework such as UIKit, SwiftUI, Combine,
etc., please report it to https://feedbackassistant.apple.com instead.
-->
**Description**
I want to implement a variadic version of the currying function.
```swift
func curried<First, each T, Result>(
_ originalFunc: @escaping (First, repeat each T) -> Result
) -> (First) -> (repeat each T) -> Result {
return { (first: First) in
return { (remanings: repeat each T) -> Result in
return originalFunc(first, repeat each remanings)
}
}
}
```
The error message is:
```
error: cannot fully abstract a value of variadic function type '(repeat each T) -> Result' because different contexts will not be able to reliably agree on a calling convention; try wrapping it in a struct
error: cannot fully abstract a value of variadic function type '(repeat each T) -> Result' because different contexts will not be able to reliably agree on a calling convention; try wrapping it in a struct
```
I have no idea what it means by " try wrapping it in a struct", it seems unrelated.
**Environment**
- 1.87.1 Apple Swift version 5.9 (swiftlang-5.9.0.128.108 clang-1500.0.40.1)
- Xcode 15.0 (15A240d)
2 Likes
xwu
(Xiaodi Wu)
March 6, 2024, 8:07pm
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