Xcode 7 (7A176x): [Swift] Extend special [T] behaviour when passing to a function expecting a Unsafe(Mutable)Pointer to ContiguousArray<T> and ArraySlice<T>

Originator:janoschhildebrand
Number:rdar://22220025 Date Originated:11-Aug-2015
Status:Open Resolved:
Product:Developer Tools Product Version:Xcode 7 (7A176x)
Classification:Enhancement Reproducible:N/A
 
Summary:
Array<T> a.k.a [T] is special cased by the compiler to enable easy interoperability with APIs expecting a pointer to contiguous element storage.

Array instances can be passed directly to functions expecting an argument of type UnsafePointer<T> or UnsafePointer<Void> or to functions expecting an UnsafeMutablePointer<T> or UnsafeMutablePointer<Void> by marking it as inout using &.
The compiler automatically converts this so that a pointer to the first element in a contiguous buffer containing the array's elements is passed.


The other array types in the Swift standard library, ArraySlice<T> and ContiguousArray<T>, however do not receive this special treatment. I think it would be both convenient and safer to extend this behaviour to these other array types.

Currently the situation can be confusing as one might reasonably expect the same syntax to work with all array types and extra typing is required when one is not working with an Array<T> instance.
Additionally passing an ArraySlice<T> or ContiguousArray<T> to a function taking an Unsafe(Mutable)Pointer<Void> can lead to unexpected results. As this falls back to the "general" special case for UnsafePointer<Void>, a pointer to the array buffer storage object is passed instead of a pointer to the first array element in the buffer which results in "wrong" elements and can lead to unexpected crashes when writing to the pointer.


Here is a short snippet demonstrating this potentially confusing issue:

import Foundation

var data = NSData(base64EncodedString: "dGVzdA==", options:[])!

var arrayBuffer = [UInt8](count: data.length, repeatedValue:0)
data.getBytes(&arrayBuffer, length: data.length)
arrayBuffer

var contigBuffer = ContiguousArray<UInt8>(count: data.length, repeatedValue:0)
data.getBytes(&contigBuffer, length: data.length)
contigBuffer // crash

Steps to Reproduce:


Expected Results:
Ideally, all standard library array types should provide identical behaviour in this case for consistency and ease of use.

Actual Results:
Currently Array<T> behaviour differs from ArraySlice<T> and ContiguousArray<T> behaviour in this case.

Version:
Xcode 7 (7A176x)
Apple Swift version 2.0 (swiftlang-700.0.52.2 clang-700.0.65)

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!