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

Kevin Ballard kevin at sb.org
Tue Dec 15 20:46:35 CST 2015


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.

> 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


More information about the swift-dev mailing list