> On Aug 9, 2017, at 8:51 AM, Taylor Swift <kelvin1...@gmail.com> wrote:
> 
> 
> 
> On Wed, Aug 9, 2017 at 2:34 AM, Andrew Trick <atr...@apple.com 
> <mailto:atr...@apple.com>> wrote:
> 
>> On Aug 8, 2017, at 11:10 PM, Taylor Swift <kelvin1...@gmail.com 
>> <mailto:kelvin1...@gmail.com>> wrote:
>> 
>> 
>> On Wed, Aug 9, 2017 at 1:51 AM, Andrew Trick <atr...@apple.com 
>> <mailto:atr...@apple.com>> wrote:
>> 
>>> On Aug 8, 2017, at 8:44 PM, Taylor Swift <kelvin1...@gmail.com 
>>> <mailto:kelvin1...@gmail.com>> wrote:
>>> 
>>> cool,, as for UnsafeMutableRawBufferPointer.copy(from:bytes:), I cannot 
>>> find such a function anywhere in the API. There is copyBytes(from:) 
>>> <https://developer.apple.com/documentation/swift/unsafemutablerawbufferpointer/2635415-copybytes>,
>>>  but the documentation is messed up and mentions a nonexistent count: 
>>> argument over and over again. The documentation also doesn’t mention what 
>>> happens if there is a length mismatch, so users are effectively relying on 
>>> an implementation detail. I don’t know how to best resolve this.
>> 
>> We currently have `UnsafeMutableRawBufferPointer.copyBytes(from:)`. I don’t 
>> think your proposal changes that. The current docs refer to the `source` 
>> parameter, which is correct. Docs refer to the parameter name, not the label 
>> name. So `source.count` is the size of the input. I was pointing out that it 
>> has the semantics: `debugAssert(source.count <= self.count)`.
>> 
>> Your proposal changes `UnsafeRawPointer.copyBytes(from:count:)` to 
>> `UnsafeRawPointer.copy(from:bytes:)`. Originally we wanted to those API 
>> names to match, but I’m fine with your change. What is more important is 
>> that the semantics are the same as `copyBytes(from:)`. Furthermore, any new 
>> methods that you add that copy into a raw buffer (e.g. 
>> initializeMemory(as:from:count:)) should have similar behavior.
>> 
>>  
>> I’m fine with switching to taking the count from the source, though I think 
>> taking the count from the destination is slightly better because 1) the use 
>> cases I mentioned in the other email, and 2) all the other memorystate 
>> functions use self.count instead of source.count, if they take a source 
>> argument. But being consistent with the raw pointer version is more 
>> important.
> 
> If it’s copying from a buffer it should not take a count, if it’s copying 
> from a pointer it obviously needs to take a count. What I mean by the two 
> versions being named consistently is simply that they’re both named 
> `copyBytes`. That really isn’t important though. The overflow/underflow 
> semantics being consistent are important.
> 
> (Incidentally, the reason “bytes” needs to be in the somewhere name is 
> because this method isn’t capable of copying nontrivial values)
> 
>> Should the methods that don’t deal with raw buffers also be modified to use 
>> the source argument (i.e. UnsafeMutableBufferPointer.initialize(from:))?
> 
> I’m not sure what you mean by this. It also allows the destination to be 
> larger than the source. Initializing from a sequence does not trap on 
> overflow because we can’t guarantee the size of the sequence ahead of time. 
> When I talk about consistent overflow/underflow semantics, I’m only talking 
> about initializing one unsafe buffer/pointer from another unsafe 
> buffer/pointer.
> 
>> Also, was there a reason why UnsafeMutableRawBufferPointer.copyBytes(from:) 
>> uses the source’s count instead of its own? Right now this behavior is 
>> “technically” undocumented behavior (as the public docs haven’t been 
>> updated) so if there was ever a time to change it, now would be it.
> 
> Mainly because partial initialization is more expected than dropping data on 
> the floor. Ultimately, this should be whatever typical developers would 
> expect the behavior to be. I would be very hesitant to change the behavior 
> now though.
> 
> -Andy
> 
> The problem is I would expect to be able to safely call deinitialize() and 
> friends after calling initialize(from:). If Element is a class type and 
> initialize doesn’t fill the entire buffer range, calling deinitialize() will 
> crash. That being said, since copy(from:bytes:) and copyBytes(from:) don’t do 
> any initialization and have no direct counterparts in 
> UnsafeMutableBufferPointer, it’s okay if they have different behavior than 
> the other methods.

You astutely pointed out that the UnsafeMutableBufferPointer.deinitialize() 
method is dangerous, and I asked you to add a warning to its comments. However, 
given the danger, I think we need to justify adding the method to begin with. 
Are there real use cases that greatly benefit from it?

We have to accept that UnsafeBufferPointer is simply not a safe API for 
managing initialization and deinitialization. Adding a convenience method only 
makes it less safe.

The standard library *should* vend a safe API for initializing and 
deinitializing manually allocated memory. However, that will require a new 
"buffer" type that wraps UnsafeBufferPointer. That will be a major design 
discussion that is both out of scope for Swift 5 and makes sense to defer until 
we have move-only types.

-Andy
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to