tera
1
Is it possible to restrict T in such a way that I am not getting this error?
(I only plan to use it with POD value types)
// -experimental-performance-annotations
struct Test<T> {
var x: T?
@_noLocks
init() {}
// 🛑 error: Using type 'Test<T>' can cause metadata allocation or locks
}
1 Like
Joe_Groff
(Joe Groff)
2
As currently implemented, you have to apply @_noLocks to the caller of generic APIs, not to generic APIs themselves, since applying them to the generic function will attempt to restrict the unspecialized version of the generic function.
1 Like
tera
3
Thank you.
Not sure if I'll be able using it though. For example:
// -experimental-performance-annotations
public struct Test<T> {
private var x = 0
private var y: T?
init() {}
}
@_noLocks
func test() {
typealias FiveInt8s = (Int8, Int8, Int8, Int8, Int8)
typealias SixInt8s = (Int8, Int8, Int8, Int8, Int8, Int8)
//_ = Test<FiveInt8s>() // ✅
_ = Test<SixInt8s>() // 🛑
}
(compiles ok with 5 uint8's but not six).
jcavar
(Josip Cavar)
4
I am not sure what is happening here, but if y is T and not T? it compiles ok.
// -experimental-performance-annotations
public struct Test<T> {
private var x = 0
private var y: T
init(_ x: T) {
y = x
}
}
typealias SixInt8s = (Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8)
@_noLocks
func test() {
_ = Test<SixInt8s>((1, 1, 1, 1, 1, 1, 1, 1, 1)) // ✅
}
jcavar
(Josip Cavar)
5
It is actually more subtle. y can be T? if it is declared with let.
tera
6
a simpler example:
// -experimental-performance-annotations
@_noLocks
func foo<T>(_ v: T?) -> T {
if let v { // 🛑 Using type 'T' can cause metadata allocation or locks
return v
}
while true {}
}
Ditto with a custom optional:
// -experimental-performance-annotations
enum MyOptional<Wrapped> {
case none, some(Wrapped)
}
@_noLocks
func foo<T>(_ v: MyOptional<T>) -> T {
switch v { // 🛑 Using type 'MyOptional<T>' can cause metadata allocation or locks
case .none: while true {}
case let .some(v): return v
}
}
or just this:
// -experimental-performance-annotations
@_noLocks
func foo<T>(_ v: T) -> T {
v // 🛑 Using type 'T' can cause metadata allocation or locks
}
Nothing suspicious in the asm (-O):
main:
xor eax, eax
ret
output.foo<A>(A) -> A:
mov rdx, rsi
mov rsi, rdi
mov rcx, qword ptr [rdx - 8]
mov rcx, qword ptr [rcx + 16]
mov rdi, rax
jmp rcx
__swift_reflection_version:
.short 3