Skip to content

Commit 41fcd63

Browse files
committed
[many more edits]
1 parent 38786be commit 41fcd63

File tree

1 file changed

+25
-21
lines changed

1 file changed

+25
-21
lines changed

proposals/nnnn-MutableSpan.md

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
[SE-0447]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0447-span-access-shared-contiguous-storage.md
1313
[SE-0456]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0456-stdlib-span-properties.md
1414
[PR-2305]: https://github.com/swiftlang/swift-evolution/pull/2305
15+
[SE-0437]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0437-noncopyable-stdlib-primitives.md
1516
[SE-0453]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0453-vector.md
1617
[SE-0223]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0223-array-uninitialized-initializer.md
1718
[SE-0176]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0176-enforce-exclusive-access-to-memory.md
@@ -29,7 +30,7 @@ These functions have a few different drawbacks, most prominently their reliance
2930
In addition to the new types, we will propose adding new API some standard library types to take advantage of `MutableSpan` and `MutableRawSpan`.
3031

3132
## Proposed solution
32-
We previously introduced `Span` to provide shared read-only access to containers. We cannot use `Span` to also model container mutations, due to the [law of exclusivity][SE-0176]. `Span` is copyable, and must be copyable in order to properly model read access under the law of exclusivity: a value can be simultaneously accessed through multiple read-only accesses. Mutations, on the other hand, require _exclusive access_. Exclusive access cannot be modeled through a copyable type, since a copy of the value representing the access would by definition violate exclusivity. We therefore need a non-copyable type separate from `Span` in order to model mutations.
33+
We introduced `Span` to provide shared read-only access to containers. We cannot use `Span` to also model container mutations, due to the [law of exclusivity][SE-0176]. `Span` is copyable, and must be copyable in order to properly model read access under the law of exclusivity: a value can be simultaneously accessed through multiple read-only accesses. Mutations, on the other hand, require _exclusive access_. Exclusive access cannot be modeled with a copyable type, since a copy of the value representing the access would violate exclusivity by adding a second access. We therefore need a non-copyable type separate from `Span` in order to model mutations.
3334

3435
#### MutableSpan
3536

@@ -141,9 +142,9 @@ extension MutableSpan where Element: ~Copyable {
141142
```
142143
##### Bulk updating of a `MutableSpan`'s elements:
143144

144-
We include functions to perform bulk copies into the memory represented by a `MutableSpan`. Updating a `MutableSpan` from known-sized sources (such as `Collection` or `Span`) copies every element of a source. It is an error to do so when there is the span is too short to contain every element from the source. Updating a `MutableSpan` from `Sequence` or `IteratorProtocol` instances will copy as many items as possible, either until the input is empty or until the operation has updated the item at the last index.
145+
We include functions to perform bulk copies of elements into the memory represented by a `MutableSpan`. Updating a `MutableSpan` from known-sized sources (such as `Collection` or `Span`) copies every element of a source. It is an error to do so when there is the span is too short to contain every element from the source. Updating a `MutableSpan` from `Sequence` or `IteratorProtocol` instances will copy as many items as possible, either until the input is empty or until the operation has updated the item at the last index.
145146

146-
**Note:** This set of functions is sufficiently complete in functionality, but this minimal approach to slicing is only one of many possible approaches. We could revive the option of using a `some RangeExpression` parameter, or we could use the return value of a `func extracting(_: some RangeExpression)` such as was recently added to `UnsafeBufferPointer` in support of non-copyable elements. The latter option in combination with `mutating` functions requires the use of intermediate bindings.
147+
**Note:** This set of functions is sufficiently complete in functionality, but uses a minimal approach to slicing. This is only one of many possible approaches to slicing `MutableSpan`. We could revive the option of using a `some RangeExpression` parameter, or we could use the return value of a `func extracting(_: some RangeExpression)` such as was [recently added][SE-0437] to `UnsafeBufferPointer`. The latter option in combination with `mutating` functions requires the use of intermediate bindings. This section may change in response to feedback and our investigations.
147148

148149
```swift
149150
extension MutableSpan {
@@ -251,7 +252,22 @@ extension MutableRawSpan {
251252

252253
##### Accessing and modifying the memory of a `MutableRawSpan`:
253254

254-
The basic operations available on `RawSpan` are available for `MutableRawSpan`. These operations are not type-safe, in that the loaded value returned by the operation can be invalid, and violate type invariants. Some types have a property that makes the `unsafeLoad(as:)` function safe, but we don't have a way to [formally identify](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0447-span-access-shared-contiguous-storage.md#SurjectiveBitPattern) such types at this time.
255+
`MutableRawSpan` supports storing the bytes of a `BitwiseCopyable` value to its underlying memory:
256+
257+
```swift
258+
extension MutableRawSpan {
259+
mutating func storeBytes<T: BitwiseCopyable>(
260+
of value: T, toByteOffset offset: Int = 0, as type: T.Type
261+
)
262+
263+
@unsafe
264+
mutating func storeBytes<T: BitwiseCopyable>(
265+
of value: T, toUncheckedByteOffset offset: Int, as type: T.Type
266+
)
267+
}
268+
```
269+
270+
Additionally, the basic loading operations available on `RawSpan` are available for `MutableRawSpan`. These operations are not type-safe, in that the loaded value returned by the operation can be invalid, and violate type invariants. Some types have a property that makes the `unsafeLoad(as:)` function safe, but we don't have a way to [formally identify](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0447-span-access-shared-contiguous-storage.md#SurjectiveBitPattern) such types at this time.
255271

256272
```swift
257273
extension MutableRawSpan {
@@ -277,22 +293,10 @@ extension MutableRawSpan {
277293
}
278294
```
279295

280-
To these, `MutableRawSpan` adds functions to store the bytes of a `BitwiseCopyable` value:
281-
282-
```swift
283-
extension MutableRawSpan {
284-
mutating func storeBytes<T: BitwiseCopyable>(
285-
of value: T, toByteOffset offset: Int = 0, as type: T.Type
286-
)
296+
We include functions to perform bulk copies into the memory represented by a `MutableRawSpan`. Updating a `MutableRawSpan` from a `Collection` or a `Span` copies every element of a source. It is an error to do so when there is are not enough bytes in the span to contain every element from the source. Updating `MutableRawSpan` from `Sequence` or `IteratorProtocol` instance copies as many items as possible, either until the input is empty or until there are not enough bytes in the span to store another element.
287297

288-
@unsafe
289-
mutating func storeBytes<T: BitwiseCopyable>(
290-
of value: T, toUncheckedByteOffset offset: Int, as type: T.Type
291-
)
292-
}
293-
```
298+
**Note:** This set of functions is sufficiently complete in functionality, but uses a minimal approach to slicing. This is only one of many possible approaches to slicing `MutableRawSpan`. (See the note above on )
294299

295-
We include functions to perform bulk copies into the memory represented by a `MutableRawSpan`. Updating a `MutableRawSpan` from a `Collection` or a `Span` copies every element of a source. It is an error to do so when there is are not enough bytes in the span to contain every element from the source. Updating `MutableRawSpan` from `Sequence` or `IteratorProtocol` instance copies as many items as possible, either until the input is empty or until there are not enough bytes in the span to store another element.
296300
```swift
297301
extension MutableRawSpan {
298302
mutating func update<S: Sequence>(
@@ -440,7 +444,7 @@ This proposal is additive and ABI-compatible with existing code.
440444

441445
## Implications on adoption
442446

443-
The additions described in this proposal require a new version of the Swift standard library and runtime.
447+
The additions described in this proposal require a new version of the Swift standard library.
444448

445449
## Alternatives considered
446450

@@ -504,7 +508,7 @@ extension MutableSpan where Element: ~Copyable {
504508
}
505509
```
506510

507-
Unfortunately, tuples do not support non-copyable values yet. We may be able to use `InlineArray` ([SE-0453][SE-0453]), or a bespoke type, but destructuring the non-copyable constituent part remains a challenge. Solving this issue for `Span` as well as `MutableSpan` is a top priority.
511+
Unfortunately, tuples do not support non-copyable values yet. We may be able to use `InlineArray` ([SE-0453][SE-0453]), or a bespoke type, but destructuring the non-copyable constituent part remains a challenge. Solving this issue for `Span` and `MutableSpan` is a top priority.
508512

509513
#### Mutating algorithms
510514

@@ -514,5 +518,5 @@ Algorithms defined on `MutableCollection` such as `sort(by:)` and `partition(b
514518

515519
Some data structures can delegate initialization of parts of their owned memory. The standard library added the `Array` initializer `init(unsafeUninitializedCapacity:initializingWith:)` in [SE-0223][SE-0223]. This initializer relies on `UnsafeMutableBufferPointer` and correct usage of initialization primitives. We should present a simpler and safer model of initialization by leveraging non-copyability and non-escapability.
516520

517-
## Acknowledgements
521+
We expect to propose an `OutputSpan<T>` type to represent partially-initialized memory, and to support to the initialization of memory by appending to the initialized portion of the underlying storage.
518522

0 commit comments

Comments
 (0)