[swift-dev] `withUnsafePointer` mutates `self`

Dave Abrahams dabrahams at apple.com
Wed Dec 16 01:25:25 CST 2015


> On Dec 15, 2015, at 6:46 PM, Kevin Ballard <kevin at sb.org> wrote:
> 
> On Tue, Dec 15, 2015, at 06:39 PM, Dave Abrahams wrote:
>> 
>>> On Dec 15, 2015, at 6:33 PM, Kevin Ballard via swift-dev <swift-dev at swift.org> wrote:
>>> 
>>> On Tue, Dec 15, 2015, at 03:03 PM, Joe Groff via swift-dev wrote:
>>>> 
>>>> Yeah, it seems to me like a reasonable refinement for 'withUnsafePointer' to take an immutable parameter. Since this is a stdlib API change, you should suggest that on swift-evolution.
>>> 
>>> A change like that is going to break any code that relies on the inout optimization (where it uses call-by-reference instead of copy-in copy-out when possible). Yes, such code is in violation of Swift semantics today, but it does work.
>> 
>> Two questions:
>> 
>> 1. Don’t we want a withUnsafeMutablePointer for the mutating cases (where the inout optimization can take effect) anyway?
> 
> I'm thinking here of cases like passing a context pointer to KVO. You're not actually mutating it, you just need a pointer that's the same every time you call the code.

Well, it is not possible to code a version of withUnsafePointer that makes that guarantee in Swift.

> 
>> 2. Joe, these APIs predate many of your changes that make &x transparently convert to Unsafe[Mutable]Pointer arguments. Are they obsolete?  Can we replace them with { x: Unsafe[Mutable]Pointer in … }(&y) ?
> 
> Interesting idea. I rarely use withUnsafePointer/withUnsafeMutablePointer because the &x shorthand exists. If withUnsafePointer() is modified to take its argument by-value and create a pointer from it, I expect people will start using it in place of &x shorthand so they can use it with immutable values, without realizing that they're getting a different pointer back each time (whether they notice this depends on what they're using the pointer for).
> 
> If { x: UnsafePointer<Int> in ... }(&y) works, that's a cute replacement. Although it does move the &y reference to after the scope instead of before, which is a little unfortunate.
> 
> ...huh. On a whim I tested the following and it shocked me by working.
> 
> var x: Int = 42
> withExtendedLifetime(&x) { (x: UnsafeMutablePointer<Int>) in
>    x.memory += 1
> }
> print(x) // prints 43
> 
> If we want to replace withUnsafe[Mutable]Pointer() with a common idiom, I'd recommend using withExtendedLifetime like that, because a) it guarantees the pointed-to value exists for the duration of the scope, and b) it already works.
> 
> -Kevin Ballard

-Dave





More information about the swift-dev mailing list