<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On 24 Mar 2017, at 07:49, Andrew Trick <<a href="mailto:atrick@apple.com" class="">atrick@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Mar 23, 2017, at 7:34 PM, Karl Wagner <<a href="mailto:razielim@gmail.com" class="">razielim@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Oh, one more thing (about this specific change): If we do this, we should add an “offset” parameter to UnsafeMutableBufferPointer.[move]initialize/assign (with a default of 0 for source compatibility). Otherwise, it becomes awkward to initialise a region of a buffer from another buffer.<div class=""><br class=""></div><div class="">What I want to write:</div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Courier" class="">buffer.suffix(from: filled).initialize(from: newData)</font></div></blockquote><div class=""><br class=""></div>If SubSequence is not another unsafe pointer, I’d have to do this:<blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Courier" class="">buffer.baseAddress!.advanced(by: filled).initialize(from: newData) // Warning: deprecated in Swift 4.0</font></div></blockquote></div></div></blockquote><div class=""><br class=""></div><div class="">Oh no. Don't do that. You're supposed to do:</div><div class=""><br class=""></div><div class="">UnsafeMutableRawBufferPointer(rebasing: buffer.suffix(from: filled)).initialize(from: newData)</div><div class=""><br class=""></div><div class="">I don't blame you for not wanting to write out the type name.</div><div class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><br class=""></div></blockquote>So instead, we should have the ability to write this:<blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Courier" class="">buffer.initialize(startingAt: filled, from: newData) // awkward labels, but src compat…</font></div></blockquote></div></div></blockquote><div class=""><br class=""></div><div class=""><div class="">I agree that's worth doing as a result of changing the slice type. You</div><div class="">shouldn't need to "rebase" the buffer each time you want to initialize</div><div class="">a region. My concern is that there are a handful of APIs to fix</div><div class="">(initialize, initializeMemory, copyBytes, load). We should handle them</div><div class="">all in one proposal, and we may want time to bikeshed the API. I'm</div><div class="">unconvinced this is worth pursuing for Swift 4. Can you file a bug?</div><div class=""><br class=""></div></div></div></div></div></blockquote><div><br class=""></div><div>It might be related to the existing bug about unsafely initialising an Array’s storage (SR-3087). We could add these methods as a protocol extension or refined protocol on “UnsafelyInitializable”.</div><div><br class=""></div><div>Then, in a similar fashion to SR-3631, which would introduce ContiguouslyStored and remove ArraySlice, Slice<T> could conditionally conform to that protocol when its base does. That would make the first example — buffer.suffix().initialize(from:), work.</div><div><br class=""></div><div><div><a href="https://bugs.swift.org/browse/SR-3087" class="">https://bugs.swift.org/browse/SR-3087</a></div><div><a href="https://bugs.swift.org/browse/SR-3631" class="">https://bugs.swift.org/browse/SR-3631</a></div></div><div><br class=""></div><div><br class=""></div><div>Fleshing out those unsafe-initialisation protocols would be useful in general, not just for slices of unsafe buffers. For example, if you’re initialising such any such Collection from something which is ContiguouslyStored, we could optimise that operation quite a lot. Currently, the standard library has private, underscored methods on Sequence to do that: “_copyContentsToContiguousArray” and “_copyContents(initializing:)”.</div><div><br class=""></div><div>I hope unsafe-initialisation is something which can make Swift 4. It would align well with other features in that release.</div><div><br class=""></div><div>Where ownership is concerned, I feel we still need to express how code which wishes to avoid copies should get its data in to standard-library datatypes: the ownership manifesto only covers data at the Swift-type level, and provides no way to express ownership over an arbitrary buffer of allocated memory (that you might, for example, be able to safely wrap as an Array or String). Unsafe initialisation is a great answer to this - the standard library type owns its backing, which remains a private implementation detail, but you get the opportunity to have it allocate a buffer for you to fill up directly, using whichever unsafe operations you like and eliminating copies.</div><div><br class=""></div><div>In particular, the new String model will expose its backing as a contiguous RandomAccessCollection of CodeUnits. It would be totally badass if we could unsafely initialise a standard Swift.String, using its backing storage <i class="">directly</i> as the buffer for file read/network recv operations.</div><div><br class=""></div><div>- Karl</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><div class=""><br class=""></div><div class="">But yeah, this post just reminded me that there are a number of small consistency tweaks we could make to the unsafe-buffer API.</div></div></div></div></div></blockquote><div class=""><br class=""></div><div class="">Yeah, but these are convenience issues, not correctness issues.</div><div class=""><br class=""></div><div class="">I think these are the ones that are important, obvious, and trivial</div><div class="">enough that might make sense in Swift 4.</div><div class=""><br class=""></div><div class="">** UnsafeBufferPointer should have init from mutable</div><div class=""><a href="https://bugs.swift.org/browse/SR-3929" class="">https://bugs.swift.org/browse/SR-3929</a></div><div class=""><br class=""></div><div class="">** UnsafeMutableBufferPointer doesn't have an allocating init</div><div class=""><a href="https://bugs.swift.org/browse/SR-3088" class="">https://bugs.swift.org/browse/SR-3088</a></div><div class=""><br class=""></div><div class="">** UnsafeBufferPointer needs a withMemoryRebound method</div><div class=""><a href="https://bugs.swift.org/browse/SR-4340" class="">https://bugs.swift.org/browse/SR-4340</a></div><div class=""><br class=""></div><div class="">** Implicit Conversion: &Tuple to UnsafePointer<Tuple.Element></div><div class=""><a href="https://bugs.swift.org/browse/SR-3590" class="">https://bugs.swift.org/browse/SR-3590</a></div><div class=""><br class=""></div><div class="">-Andy</div><div class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><div class=""><br class=""></div><div class="">- Karl</div><div class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On 24 Mar 2017, at 03:22, Karl Wagner <<a href="mailto:karl.swift@springsup.com" class="">karl.swift@springsup.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">The convenience initialiser should exist on all of the unsafe buffers, not just the raw (untyped) ones.</div><div class=""><br class=""></div>I’ve run in to this problem a few times, and I think it would get worse if we adopted a ContiguouslyStored protocol to formalise accessing the raw-pointers of generic collections. It would mean that you couldn’t write code that works with UnsafeRawBufferPointer/Data/DispatchData generically, or with UnsafeBufferPointer<T>/Array<T>.<div class=""><br class=""></div><div class="">Also, there seem to be some implicit conversions for the unsafe-pointer types, but UMBP -> UBP requires an awkward initialiser. We should introduce an implicit conversion for that case or add an “immutable” computed property to UMBP.</div><div class=""><br class=""></div><div class="">And while we’re on the subject, memory allocation/deallocation functions are weirdly dispersed. In order to allocate an UnsafeMutableBufferPointer<T>, for instance, you have to do:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Courier" class="">var buffer: UnsafeMutableBufferPointer<T></font></div><div class=""><font face="Courier" class="">init(length: Int) {</font></div><div class=""><font face="Courier" class=""> let b = UnsafeMutablePointer<T>.allocate(capacity: length)</font></div><div class=""><font face="Courier" class=""> buffer = UnsafeMutableBufferPointer(start: b, count: length)</font></div><div class=""><font face="Courier" class="">}</font></div></blockquote><div class=""><br class=""></div><div class="">Also, the deallocate API feels weird - since it deallocates n items from the head of the pointer, it is a consuming operation and I feel like it should return a new pointer (with @discardableResult). Once you’ve deallocated a memory address, you can never re-allocate that specific location so there is no reason to know about it any more.</div><div class=""><br class=""></div><div class="">- Karl</div><div class=""><div class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On 21 Mar 2017, at 03:21, Andrew Trick via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">This proposal amends SE-0138: Normalize UnsafeRawBufferPointer Slices<br class="">to fix a design bug: <a href="https://github.com/apple/swift-evolution/pull/651" class="">https://github.com/apple/swift-evolution/pull/651</a><br class=""><br class="">The issue was discussed on swift-evolution in Nov/Dec:<br class="">See [swift-evolution] [Pitch] Normalize Slice Types for Unsafe Buffers<br class=""><a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20161128/029108.html" class="">https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20161128/029108.html</a><br class=""><br class="">The implementation of this fix is in PR #8222:<br class=""><a href="https://github.com/apple/swift/pull/8222" class="">https://github.com/apple/swift/pull/8222</a><br class=""><br class="">Fix: Change Unsafe[Mutable]RawBufferPointer's SubSequence type<br class=""><br class="">Original: Unsafe[Mutable]RawBufferPointer.SubSequence = Unsafe[Mutable]RawBufferPointer<br class=""><br class="">Fixed: Unsafe[Mutable]RawBufferPointer.SubSequence = [Mutable]RandomAccessSlice<Unsafe[Mutable]RawBufferPointer><br class=""><br class="">This is a source breaking bug fix that only applies to<br class="">post-3.0.1. It's extremely unlikely that any Swift 3 code would rely<br class="">on the SubSequence type beyond the simple use case of passing a<br class="">raw buffer subrange to an another raw buffer argument:<br class=""><br class="">`takesRawBuffer(buffer[i..<j])`<br class=""><br class="">A diagnostic message now instructs users to convert the slice to a<br class="">buffer using a `rebasing` initializer:<br class=""><br class="">`takesRawBuffer(UnsafeRawBufferPointer(rebasing: buffer[i..<j]))`<br class=""><br class="">To support this, the following `rebasing` initializers are added:<br class=""><br class="">extension UnsafeRawBufferPointer {<br class=""> public init(rebasing slice: RandomAccessSlice<UnsafeRawBufferPointer>)<br class=""> public init(<br class=""> rebasing slice: MutableRandomAccessSlice<UnsafeMutableRawBufferPointer><br class=""> )<br class="">}<br class=""><br class="">extension UnsafeMutableRawBufferPointer {<br class=""> public init(<br class=""> rebasing slice: MutableRandomAccessSlice<UnsafeMutableRawBufferPointer><br class=""> )<br class="">}<br class=""><br class="">The source compatibility test builds are unnaffected by this change.<br class=""><br class="">-Andy<br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></div></blockquote></div><br class=""></div></div></div></div></blockquote></div><br class=""></div></div></div></div></div></blockquote></div><br class=""></div></div></blockquote></div><br class=""></body></html>