You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* [se0447] reorder future-direction sections
- “Index Validation Utilites” was mistakenly inserted between two other sections that should remain contiguous.
* [se0447] use the indices property in an example
* [se0447] add omitted `Sendable` conformances
- while these were discussed in the form threads and were in the prototype implementations, they weren’t in this document.
* [se0447] fix typos
* [se0447] address telemetry domain’s Span naming
* [se0447] discuss sendability of RawSpan
We store a `UnsafeRawPointer` value internally in order to explicitly support reinterpreted views of memory as containing different types of `BitwiseCopyable` elements. Note that the the optionality of the pointer does not affect usage of `Span`, since accesses are bounds-checked and the pointer is only dereferenced when the `Span` isn't empty, and the pointer cannot be `nil`.
@@ -95,7 +97,7 @@ Like `UnsafeBufferPointer`, `Span` uses a simple offset-based indexing. The firs
95
97
As a side-effect of not conforming to `Collection` or `Sequence`, `Span` is not directly supported by `for` loops at this time. It is, however, easy to use in a `for` loop via indexing:
96
98
97
99
```swift
98
-
for i in0..<mySpan.count {
100
+
for i in mySpan.indices {
99
101
calculation(mySpan[i])
100
102
}
101
103
```
@@ -225,6 +227,8 @@ public struct RawSpan: Copyable, ~Escapable {
225
227
internalvar _start: UnsafeRawPointer
226
228
internalvar _count: Int
227
229
}
230
+
231
+
extensionRawSpan: Sendable {}
228
232
```
229
233
230
234
Initializers, required for library adoption, will be proposed alongside [lifetime annotations][PR-2305]; for details, see "[Initializers](#Initializers)" in the [future directions](#Directions) section.
@@ -402,6 +406,12 @@ A non-escapable index type implies that any indexing operation would borrow its
402
406
403
407
The ideas in this proposal previously used the name `BufferView`. While the use of the word "buffer" would be consistent with the `UnsafeBufferPointer` type, it is nevertheless not a great name, since "buffer"is commonly used in reference to transient storage. Another previous pitch used the term `StorageView` in reference to the `withContiguousStorageIfAvailable()` standard library function. We also considered the name `StorageSpan`, but that did not add much beyond the shorter name `Span`. `Span` clearly identifies itself as a relative of C++'s `std::span`.
404
408
409
+
The OpenTelemetry project and its related libraries use the word "span"for a concept of a timespan. The domains of use between that and direct memory access are very distinct, and we believe that the confusability between the use cases should be low. We also note that standard library type names can always be shadowed by type names from packages, mitigating the risk of source breaks.
410
+
411
+
##### <a name="Sendability"></a>Sendability of `RawSpan`
412
+
413
+
This proposal makes `RawSpan` a `Sendable` type. We believe this is the right decision. The sendability of `RawSpan` could be used to unsafely transfer a pointer value across an isolation boundary, despite the non-sendability of pointers. For example, suppose a `RawSpan` were obtained from an existing `Array<UnsafeRawPointer>` variable. We could send the `RawSpan` across the isolation boundary, and there extract the pointer using `rawSpan.unsafeLoad(as: UnsafeRawPointer.self)`. While this is an unsafe outcome, a similar operation can be done encoding a pointer as an `Int`, and then using `UnsafeRawPointer(bitPattern: mySentInt)` on the other side of the isolation boundary.
414
+
405
415
##### A more sophisticated approach to indexing
406
416
407
417
This is discussed more fully in the [indexing appendix](#Indexing) below.
@@ -444,7 +454,7 @@ This proposal includes some `_read` accessors, the coroutine version of the `get
444
454
445
455
#### Extensions to Standard Library and Foundation types
446
456
447
-
The standard library and Foundation has a number of types that can in principle provide access to their internal storage as a `Span`. We could provide `withSpan()` and `withBytes()` closure-taking functions as safe replacements for the existing `withUnsafeBufferPointer()` and `withUnsafeBytes()` functions. We could also also provide lifetime-dependent `span` or `bytes` properties. For example, `Array` could be extended as follows:
457
+
The standard library and Foundation has a number of types that can in principle provide access to their internal storage as a `Span`. We could provide `withSpan()` and `withBytes()` closure-taking functions as safe replacements for the existing `withUnsafeBufferPointer()` and `withUnsafeBytes()` functions. We could also provide lifetime-dependent `span` or `bytes` properties. For example, `Array` could be extended as follows:
448
458
449
459
```swift
450
460
extensionArray {
@@ -466,10 +476,6 @@ extension Array where Element: BitwiseCopyable {
466
476
467
477
Of these, the closure-taking functions can be implemented now, but it is unclear whether they are desirable. The lifetime-dependent computed properties require lifetime annotations, as initializers do. We are deferring proposing these extensions until the lifetime annotations are proposed.
468
478
469
-
#### Index Validation Utilities
470
-
471
-
This proposal originally included index validation utilities for `Span`. such as `boundsContain(_: Index) ->Bool` and `boundsContain(_: Range<Index>) ->Bool`. After review feedback, we believe that the utilities proposed would also be useful for index validation on `UnsafeBufferPointer`, `Array`, and other similar `RandomAccessCollection` types. `Range` already a single-element `contains(_: Bound) ->Bool` function which can be made even more efficient. We should add an additional function that identifies whether a `Range` contains the _endpoints_ of another `Range`. Note that this is not the same as the existing `contains(_: some Collection<Bound>) ->Bool`, which is about the _elements_ of the collection. This semantic difference can lead to different results when examing empty `Range` instances.
An earlier version of this proposal proposed a `ContiguousStorage` protocolby which a type could indicate that it can provide a `Span`. `ContiguousStorage` would form a bridge between generically-typed interfaces and a performant concrete implementation. It would supersede the rejected [SE-0256](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0256-contiguous-collection.md).
@@ -495,6 +501,10 @@ Two issues prevent us from proposing it at this time: (a) the ability to suppres
495
501
496
502
Many of the standard library collections could conform to `ContiguousStorage`.
497
503
504
+
#### Index Validation Utilities
505
+
506
+
This proposal originally included index validation utilities for `Span`. such as `boundsContain(_: Index) -> Bool`and `boundsContain(_: Range<Index>) -> Bool`. After review feedback, we believe that the utilities proposed would also be useful for index validation on `UnsafeBufferPointer`, `Array`, and other similar `RandomAccessCollection` types. `Range` already a single-element `contains(_: Bound) -> Bool`function which can be made even more efficient. We should add an additional function that identifies whether a `Range` contains the _endpoints_ of another `Range`. Note that this is not the same as the existing `contains(_: some Collection<Bound>) -> Bool`, which is about the _elements_ of the collection. This semantic difference can lead to different results when examining empty `Range` instances.
507
+
498
508
#### Support for `Span` in `for` loops
499
509
500
510
This proposal does not define an `IteratorProtocol` conformance, since an iterator for `Span` would need to be non-escapable. This is not compatible with `IteratorProtocol`. As such, `Span` is not directly usable in `for` loops as currently defined. A `BorrowingIterator` protocol for non-escapable and non-copyable containers must be defined, providing a `for` loop syntax where the element is borrowed through each iteration. Ultimately we should arrive at a way to iterate through borrowed elements from a borrowed view:
0 commit comments