[swift-users] non-mutating func that still mutates a struct, compiler not aware

Jordan Rose jordan_rose at apple.com
Fri Aug 5 11:58:06 CDT 2016


Those UnsafeMutablePointer<T>(…) calls aren’t correct. When an array is implicitly converted to a pointer in Swift, the pointer is only valid for the immediate call that it’s being passed to. In this case, that’s the UnsafeMutablePointer initializer, and after that the pointer is invalid. So it’s possible that either the same space is being reused for both pointers, or that it’s not uniquing the array because it thinks it only has to make an UnsafePointer<T>, or both.

As Brent says, passing the arrays directly to the method using inout semantics (&) should get you the behavior you want.

(Yes, there should be a diagnostic for this. I’m pretty sure we have a bug already, so no need to file. The Swift 3 pointer APIs make this a little harder to do by accident, too.)

Jordan


> On Aug 5, 2016, at 08:14, Raphael Sebbe via swift-users <swift-users at swift.org> wrote:
> 
> Do you see a reason why the copy isn't happening in this specific case? Is it a bug, or a mistake in my code?
> 
> Thank you,
> 
> Raphael
> 
> On Thu, Aug 4, 2016 at 4:18 PM Brent Royal-Gordon <brent at architechies.com <mailto:brent at architechies.com>> wrote:
> > On Aug 4, 2016, at 1:25 AM, Raphael Sebbe via swift-users <swift-users at swift.org <mailto:swift-users at swift.org>> wrote:
> >
> > My understanding is that the compiler doesn't make a real copy in the acopy =  self instruction, and then provides that contents to the mx_gels_ function which modifies the memory contents.
> >
> >
> > public func solve(rhs b: Matrix<T>) -> Matrix<T>? {
> >       // ...
> >       var acopy = self
> >       // ...
> >
> >       T.mx_gels_(&trans, &m, &n, &nrhs, UnsafeMutablePointer<T>(acopy.values), &lda, UnsafeMutablePointer<T>(x.values), &ldb, UnsafeMutablePointer<T>(workspace), &lwork, &status);
> >
> >       // ...
> >       }
> >
> >
> > Is this expected? I mean, I can force a real copy of course, but value semantics would suggest the code above is correct and wouldn't need that. Shouldn't the cast trigger the copy somehow? Or is there a better way of expressing this operation? Thx.
> 
> The `acopy = self` line only copies the reference to the internal buffer. However, converting the array into a pointer will—or at least, if done properly, *should*—force the array to create and switch to using a unique copy of its buffer in preparation for writes through the UnsafeMutablePointer. I believe that happens here: <https://github.com/apple/swift/blob/master/stdlib/public/core/Pointer.swift#L79 <https://github.com/apple/swift/blob/master/stdlib/public/core/Pointer.swift#L79>>
> 
> (I say "should" because I'm not sure you're actually creating those pointers correctly. I believe you ought to be able to just say `&acopy.values` and `&x.values`, and that should be a more reliable way to do it.)
> 
> --
> Brent Royal-Gordon
> Architechies
> 
> _______________________________________________
> swift-users mailing list
> swift-users at swift.org
> https://lists.swift.org/mailman/listinfo/swift-users

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20160805/66c6d77c/attachment.html>


More information about the swift-users mailing list