This is what I am getting "de facto":
import Foundation
typealias B = UInt8
struct S {
static var bytes: (B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B) = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18)
}
func bar() -> UnsafeMutablePointer<UInt8> {
withUnsafeMutableBytes(of: &S.bytes) { bp in
bp.baseAddress!.assumingMemoryBound(to: UInt8.self)
}
}
let r = bar()
print("bar address", r) // 0x000000010000c018 (Static data)
print("bar", r[0], r[1], r[2]) // bar 1 2 3
print(S.bytes) // (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18)
r[1] = 42
print("bar", r[0], r[1], r[2]) // bar 1 42 3
print(S.bytes) // (1, 42, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18)
Same happens when I declare "bytes" as a global variable. I can see the static address is being returned (checked with vmmap).
So while it is triggering UB, it at least works for me on all tested configurations today (tested on both godbolt and macOS with debug and release).
I can see this working on godbolt (debug+release) and macOS(release) but interestingly not on macOS+debug:
import Foundation
func foo() -> UnsafePointer<UInt8> {
[UInt8(1),2,3].withUnsafeBufferPointer { $0.baseAddress! }
}
let p = foo()
print("foo", p[0], p[1], p[2]) // 0, 0, 0 (macOS + debug)
When it doesn't work I could see the heap address being returned (and where I works the static data address is being returned).