Ok, I'll update the proposal to withdraw the change of inout for withUnsafePointer.
Under the discussion for the pull request, Bob mentioned possible removal of the multi-pointer variants (i.e. withUnsafe[Mutable]Pointers) - is this something that you'd agree on? If so, I'd add this to the proposal since I agree that this is an API that is rarely used, can be used by nesting two withUnsafe[Mutable]Pointer calls and is limited to three pointers at max anyway. It almost feels like NSAssert1, NSAssert2, etc. > On Jul 23, 2016, at 3:35 AM, Dave Abrahams via swift-evolution > <[email protected]> wrote: > > > on Fri Jul 22 2016, Xiaodi Wu <xiaodi.wu-AT-gmail.com> wrote: > >> On Fri, Jul 22, 2016 at 6:49 PM, Dave Abrahams via swift-evolution < >> [email protected]> wrote: >> >>> >>> on Fri Jul 22 2016, Xiaodi Wu <[email protected]> wrote: >>> >>>> On Fri, Jul 22, 2016 at 5:06 PM, Dave Abrahams via swift-evolution < >>>> [email protected]> wrote: >>>> >>>>> >>>>> on Fri Jul 22 2016, Bob Wilson <[email protected]> wrote: >>>>> >>>>>> It is not so clear what to do about SR-1956. (Charlie and I had some >>>>>> comments on this in https://github.com/apple/swift-evolution/pull/437 >>>>>> <https://github.com/apple/swift-evolution/pull/437>.) Jordan raised >>>>>> the objection that when using withUnsafePointer with a global, there >>>>>> is an expectation that you’ll get the same address every >>>>>> time. Removing inout would cause the argument to be passed by value >>>>>> and the address would refer to a copy. Dmitri agreed that this could >>>>>> be a problem. On the other hand, if you don’t care about the address, >>>>>> or if you’re not using a value type, it would indeed be convenient to >>>>>> have a version of withUnsafePointer that does not require an inout >>>>>> argument. >>>>>> >>>>>> Option 1: Keep inout (not addressing SR-1956). In this case, there’s >>>>>> no reason to have both withUnsafePointer and >>>>>> withUnsafeMutablePointer. If you want to call a function that expects >>>>>> an UnsafePointer, you can give it an UnsafeMutablePointer and there >>>>>> will be an implicit conversion to make it work. I discussed this with >>>>>> Apple’s stdlib team and they recommended that if we have only one >>>>>> function we use the shorter name “withUnsafePointer” and have it use >>>>>> an UnsafeMutablePointer. >>>>> >>>>> Very much in favor of Option 1. >>>>> >>>> >>>> Ditto, except that I think there is some value in keeping both (i.e. >>> doing >>>> nothing): allowing the user to document intent. It would be inconsistent >>>> and potentially confusing to call the function that returns an >>>> `UnsafeMutablePointer` `withUnsafePointer`. >>> >>> It doesn't return an `UnsafeMutablePointer`, it passes an >>> `UnsafeMutablePointer` to the body of the closure. >>> >> >> Brainfart. Yes, that's what I meant to write. Sorry. >> >>>> It's rarely used enough, and the shorter name needlessly raises the >>>> question of where I'm really "supposed to be" mutating the >>>> pointee. >>> >>> I don't understand; you only have the pointee inside the closure. >>> That's where you mutate it (obviously?) >>> >> >> If my closure does not mutate the pointee, `withUnsafePointer(_:)` allows >> me to document that. Everything *works* with >> `withUnsafeMutablePointer(_:)`, but I cannot read the code and understand >> that no mutation has happened within the body of the closure. [Am I wrong >> on this?] > > No, you're right. > >> For instance, I've been working with some of the Accelerate.framework >> functions and the arguments are often cryptic. Take this call: >> >> ``` >> cblas_sgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, m, n, k, 1, matrix, >> m, b, k, 1, &c, m) >> ``` >> >> There are times when I'd want to >> call `cblas_sgemm(_:_:_:_:_:_:_:_:_:_:_:_:_:_:)` inside an >> `withUnsafe[Mutable]Pointer(_:)` closure. Distinguishing >> `withUnsafePointer(_:)` and `withUnsafeMutablePointer(_:)` would allow a >> reader to know from the outset if `$0.pointee is mutated without having to >> know that the second-from-last argument is the one that stores the result >> (it is not consistently second-from-last; for vDSP_* functions, it's often >> the third-from-last argument, and for others it can be the first argument). >> Removing the current `withUnsafePointer(_:)` would decrease clarity for the >> reader here. > > Okay, fair enough. > >>> I've not had to use these functions much, but the distinction between >>>> `Array.withUnsafeBufferPointer(_:)` and >>>> `Array.withUnsafeMutableBufferPointer(_:)` has conditioned me to >>>> mutate the pointee using only "mutable" functions. >>> >>> Not sure if you're just drawing an analogy, >> >> I was trying to. I guess ineffectively. >> >>> but if not, those two >>> methods are not under discussion here. They are meaningfully different, >>> whereas the existing functions are not, and the one currently called >>> withUnsafePointer is always going to cause people to complain about >>> having to pass a mutable variable. >>> >>> As a fallback position, I would suggest we only provide the mutating >>> one, but with its existing name. But I still prefer the shorter name. >>> >>>> >>>>>> >>>>>> Option 2: Fix SR-1956 and have two functions, one with inout and the >>>>>> other not. This would address the inconvenience of not being able to >>>>>> use withUnsafePointer with immutable values, while still supporting >>>>>> the existing behavior. The question then would be what to call these >>>>>> two functions. >>>>> >>>>> We do not need to support new use-cases in this release, and this would >>>>> be unsatisfying because the “address of a global” property that Jordan >>>>> argued for would not hold for the immutable version. >>>>> >>>>>> - Option 2a. Combine the two existing functions as in Option 1 and use >>>>>> a new name for the non-inout version, e.g., >>>>>> withUnsafePointer(toCopyOf:), so that it won’t be confused with the >>>>>> old function. (That particular name doesn’t work very well when >>>>>> dealing with references to objects, since the object itself would not >>>>>> be copied. I haven’t yet come up with a better name, though.) One >>>>>> advantage of this approach is that we would not need to rush the new >>>>>> function into Swift 3 since it would be an additive change. >>>>> >>>>> Not rushing that into Swift 3 is the same as Option 1. >>>>> >>>>>> - Option 2b. Switch to use withUnsafeMutablePointer for all the cases >>>>>> where you care about the getting the same address. Change >>>>>> withUnsafePointer to be the non-inout version. Charlie suggested that >>>>>> we could have the migrator convert all existing uses on >>>>>> withUnsafePointer in Swift 2 code to use withUnsafeMutablePointer in >>>>>> Swift 3, but I’m not sure how well that would work. >>>>> >>>>> That's exactly the same outcome, with respect to the language/library >>>>> surface, as Option 2 AFAICT. Can we simplify this list of options? >>>>> >>>>> -- >>>>> Dave >>>>> >>>>> _______________________________________________ >>>>> swift-evolution mailing list >>>>> [email protected] >>>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>>> >>>> _______________________________________________ >>>> swift-evolution mailing list >>>> [email protected] >>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>> >>> >>> -- >>> Dave >>> >>> _______________________________________________ >>> swift-evolution mailing list >>> [email protected] >>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> > > -- > Dave > _______________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution _______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
