Same-type requirement makes generic parameters 'T' and 'Pointee' equivalent; this is an error in Swift 6 warning

I had this this extensions that used to work before swift 5.7, now it throws a warning.
It is used to create a contiguous array from a buffer of C structs.

extension UnsafeMutablePointer {
   func toContiguousArray<T>(count: Int) -> ContiguousArray<T> where Pointee == T {
        let size = MemoryLayout<T>.size
        let bufferPtr = UnsafeMutablePointer<T>.allocate(capacity: count)
        memcpy(bufferPtr, self, count * size)
        let buffer = UnsafeBufferPointer(start: self, count: count)
        let values = ContiguousArray(buffer)
        defer {
            bufferPtr.deinitialize(count: count)
            bufferPtr.deallocate()
        }
        return values
    }
}

If I remove the constraint I get this error:

Cannot convert return expression of type 'ContiguousArray<Pointee>' to return type 'ContiguousArray<T>'

Event if I say that the type alias Pointee is equals to T I get the the same error.
typealias Pointee = T
Which is the correct way to fix that issue?

You need to remove the generic method parameter T completely and just use Pointee everywhere you are currently using T.


Looking at the implementing, I think that you probably want to use stride instead of size to compute the total size of the contiguous storage in memory as stride respects the alignment of the type. If this is the case, we can simplify it quite a bit by just using the appropriate initialiser on UnsafeBufferPointer:

extension UnsafeMutablePointer {
    func toContiguousArray(count: Int) -> ContiguousArray<Pointee> {
        ContiguousArray(UnsafeBufferPointer(start: self, count: count))
    }
}

And as always, it's best to not use anything with unsafe in the name but I can't recommend anything else without more context.

2 Likes

OMG, it was so easy, need to rest.
Thank you!!

1 Like