[swift-evolution] Proposal: [stdlib] Remove withUnsafe[Mutable]Pointer[s]()

Joe Groff jgroff at apple.com
Wed Dec 16 15:38:48 CST 2015


> On Dec 16, 2015, at 1:30 PM, Kevin Ballard <kevin at sb.org> wrote:
> 
> On Wed, Dec 16, 2015, at 01:20 PM, Joe Groff wrote:
>> 
>>>> withExtendedLifetime doesn't have this overload. Adding it would essentially be just renaming withUnsafePointer.
>>> 
>>> No overload necessary. As I said, it already works today (tested in Swift 2.1). The generic type T is resolved to UnsafePointer<Int>, and so you can pass &x into it just fine because you're passing it to a parameter of type UnsafePointer.
>> 
>> That's interesting emergent behavior, but it's not something we anticipated withUnsafePointer being used for.
> 
> Sure, which is why there's 2 other alternatives that work just fine as well (nested function, or anonymous closure). And I listed that mostly because I find it neat that it actually works and it has the nice property of keeping the &x ref above the scoped pointer instead of putting it below. But at this point I'm inclined to encourage the nested function approach instead as it's simpler.
> 
>>> Why constrain the magic pointer conversions?
>> 
>> In general, implicit conversions are bad. These particular conversions lead to lots of gross knock-on effects, things like [1] - [2] working by taking the difference of two transient pointers.
> 
> I meant why constrain them to just imported functions. I fully agree with the current constraint of only doing the conversion when the &x ref is passed as a parameter to a function expecting Unsafe[Mutable]Pointer. I don't see any compelling reason to constrain it further to only imported functions, and that would be rather confusing (looking at the function signature, there'd be no way to tell whether the conversion would work or not).

The pointer conversions are already poorly discoverable, and people don't know they exist since code completion doesn't make it apparent. Showing the APIs as overloaded taking 'inout's or something similar would make it more apparent how you can use them. It's my hope that better SDK annotations can make these conversions less necessary too, by letting us eventually import well-behaved in/inout/out arguments directly as value arguments/inouts/extra returns.

>>> We should discourage people from writing Swift functions that take UnsafePointers, but sometimes it is appropriate (e.g. when wrapping imported C functions, if you need a stable pointer or need to do pointer math, then your function should be taking Unsafe[Mutable]Pointer instead of taking an inout parameter).
>> 
>> If you need a stable pointer internally in your implementation, I don't see a reason to expose that implementation detail to users. You could use withUnsafeMutablePointer(&inoutParameter) internally.
> 
> You could, and in many cases that may be appropriate, but it really depends on the function. If I'm writing a private function that wraps a few calls to a C library, I may still want it to accept a pointer because e.g. the caller may need to pass a stable pointer to several functions including my Swift wrapper function.
> 
>>>> Your proposed alternatives all involve essentially reimplementing withUnsafePointer in a different way.
>>> 
>>> Well yeah, but without requiring anything in the stdlib. swiftdoc.org lists 36 global Swift functions. 4 of them are unsafe[Mutable]Pointer[s]. That's 11% of the global functions in the stdlib, for functionality that can already be accomplished without any stdlib support and which is relatively rare.
>> 
>> I agree, it's unfortunate that these functions pollute the global namespace. Maybe they should be static methods of Unsafe[Mutable]Pointer instead?
>> 
>>> The way I see it, if the stdlib didn't already have these functions, we wouldn't add them. So why keep them around? All they do is make people think they're necessary.
>> 
>> We added them because they *are* necessary.
> 
> You still haven't demonstrated that. Every single use of withUnsafe[Mutable]Pointer[s] that can't be handled with the implicit &x conversion can be replaced with a nested function, a call to an anonymous closure, or an (ab)use of withExtendedLifetime. And the existence of the functions encourages people to call them when a simple &x ref would have sufficed.

I guess it's a difference of perspective. Your alternatives hinge on blessing the pointer conversions as a core part of the language, rather than an affordance to make many C APIs not totally awful, which I'm not comfortable with.

-Joe


More information about the swift-evolution mailing list