Skip to content

Commit 669d00e

Browse files
invalidnameChris Adamsonamartini51glessard
authored
StdlibRef: Sequence.withContiguousStorageIfAvailable(_:) abstract needs a rewrite (#40334) (#40572)
* First draft of incorporating material from #38891 * Apply suggestions from Alex's review Co-authored-by: Alex Martini <[email protected]> * Rephrase suggested by Alex. * Remove redundancy re: "don't replace buffer". * Apply changes from editorial review. * Apply Sequence edits (a3a3ff1) to MutableCollect'n * Remove errant space. Co-authored-by: Guillaume Lessard <[email protected]> Co-authored-by: Chris Adamson <[email protected]> Co-authored-by: Alex Martini <[email protected]> Co-authored-by: Guillaume Lessard <[email protected]> (cherry picked from commit 59559ca)
1 parent 2ca988e commit 669d00e

File tree

2 files changed

+48
-24
lines changed

2 files changed

+48
-24
lines changed

stdlib/public/core/MutableCollection.swift

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -194,29 +194,46 @@ where SubSequence: MutableCollection
194194
_ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R
195195
) rethrows -> R?
196196

197-
/// Call `body(buffer)`, where `buffer` provides access to the contiguous
198-
/// mutable storage of the entire collection. If no such storage exists, it is
199-
/// first created. If the collection does not support an internal
200-
/// representation in the form of contiguous mutable storage, `body` is not
201-
/// called and `nil` is returned.
197+
/// Executes a closure on the collection's contiguous storage.
198+
///
199+
/// This method calls `body(buffer)`, where `buffer` provides access to the
200+
/// contiguous mutable storage of the entire collection. If the contiguous
201+
/// storage doesn't exist, the collection creates it. If the collection
202+
/// doesn't support an internal representation in the form of contiguous
203+
/// mutable storage, this method doesn't call `body` --- it immediately
204+
/// returns `nil`.
202205
///
203206
/// The optimizer can often eliminate bounds- and uniqueness-checking
204207
/// within an algorithm. When that fails, however, invoking the same
205-
/// algorithm on `body`\ 's argument may let you trade safety for speed.
208+
/// algorithm on the `buffer` argument may let you trade safety for speed.
209+
///
210+
/// Always perform any necessary cleanup in the closure, because the
211+
/// method makes no guarantees about the state of the collection if the
212+
/// closure throws an error. Your changes to the collection may be absent
213+
/// from the collection after throwing the error, because the closure could
214+
/// receive a temporary copy rather than direct access to the collection's
215+
/// storage.
216+
///
217+
/// - Warning: Your `body` closure must not replace `buffer`. This leads
218+
/// to a crash in all implementations of this method within the standard
219+
/// library.
220+
///
221+
/// Successive calls to this method may provide a different pointer on each
222+
/// call. Don't store `buffer` outside of this method.
206223
///
207224
/// A `Collection` that provides its own implementation of this method
208225
/// must provide contiguous storage to its elements in the same order
209-
/// as they appear in the collection. This guarantees that contiguous
210-
/// mutable storage to any of its subsequences can be generated by slicing
226+
/// as they appear in the collection. This guarantees that it's possible to
227+
/// generate contiguous mutable storage to any of its subsequences by slicing
211228
/// `buffer` with a range formed from the distances to the subsequence's
212229
/// `startIndex` and `endIndex`, respectively.
213230
///
214-
/// - Note: `buffer` must not be replaced by `body`.
215-
///
216231
/// - Parameters:
217-
/// - body: a closure to be executed using the elements of this collection.
218-
/// - buffer: a buffer to the mutable contiguous storage of this collection.
219-
/// - Returns: the value returned by `body`, or `nil`.
232+
/// - body: A closure that receives an in-out
233+
/// `UnsafeMutableBufferPointer` to the collection's contiguous storage.
234+
/// - Returns: The value returned from `body`, unless the collection doesn't
235+
/// support contiguous storage, in which case the method ignores `body` and
236+
/// returns `nil`.
220237
mutating func withContiguousMutableStorageIfAvailable<R>(
221238
_ body: (_ buffer: inout UnsafeMutableBufferPointer<Element>) throws -> R
222239
) rethrows -> R?

stdlib/public/core/Sequence.swift

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -384,27 +384,34 @@ public protocol Sequence {
384384
initializing ptr: UnsafeMutableBufferPointer<Element>
385385
) -> (Iterator,UnsafeMutableBufferPointer<Element>.Index)
386386

387-
/// Call `body(buffer)`, where `buffer` provides access to the contiguous
388-
/// storage of the entire collection. If no such storage exists, it is
389-
/// first created. If the collection does not support an internal
390-
/// representation in the form of contiguous storage, `body` is not
391-
/// called and `nil` is returned.
387+
/// Executes a closure on the sequence’s contiguous storage.
388+
///
389+
/// This method calls `body(buffer)`, where `buffer` is a pointer to the
390+
/// collection’s contiguous storage. If the contiguous storage doesn't exist,
391+
/// the collection creates it. If the collection doesn’t support an internal
392+
/// representation in a form of contiguous storage, the method doesn’t call
393+
/// `body` --- it immediately returns `nil`.
392394
///
393395
/// The optimizer can often eliminate bounds- and uniqueness-checking
394396
/// within an algorithm. When that fails, however, invoking the same
395-
/// algorithm on `body`\ 's argument may let you trade safety for speed.
397+
/// algorithm on the `buffer` argument may let you trade safety for speed.
398+
///
399+
/// Successive calls to this method may provide a different pointer on each
400+
/// call. Don't store `buffer` outside of this method.
396401
///
397402
/// A `Collection` that provides its own implementation of this method
398403
/// must provide contiguous storage to its elements in the same order
399-
/// as they appear in the collection. This guarantees that contiguous
400-
/// storage to any of its subsequences can be generated by slicing
404+
/// as they appear in the collection. This guarantees that it's possible to
405+
/// generate contiguous mutable storage to any of its subsequences by slicing
401406
/// `buffer` with a range formed from the distances to the subsequence's
402407
/// `startIndex` and `endIndex`, respectively.
403408
///
404409
/// - Parameters:
405-
/// - body: a closure to be executed using the elements of this collection.
406-
/// - buffer: a buffer to the contiguous storage of this collection.
407-
/// - Returns: the value returned by `body`, or `nil`.
410+
/// - body: A closure that receives an `UnsafeBufferPointer` to the
411+
/// sequence's contiguous storage.
412+
/// - Returns: The value returned from `body`, unless the sequence doesn't
413+
/// support contiguous storage, in which case the method ignores `body` and
414+
/// returns `nil`.
408415
func withContiguousStorageIfAvailable<R>(
409416
_ body: (_ buffer: UnsafeBufferPointer<Element>) throws -> R
410417
) rethrows -> R?

0 commit comments

Comments
 (0)