Skip to content

Commit 41c26fc

Browse files
[SE-0467] Update the MutableSpan proposal
1 parent 6ef8cf3 commit 41c26fc

File tree

1 file changed

+10
-10
lines changed

1 file changed

+10
-10
lines changed

proposals/0467-MutableSpan.md

+10-10
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@
55
* Review Manager: [Joe Groff](https://github.com/jckarter)
66
* Status: **Active review (March 11...25, 2025)**
77
* Roadmap: [BufferView Roadmap](https://forums.swift.org/t/66211)
8-
* Implementation: "Future" target of [swift-collections](https://github.com/apple/swift-collections/tree/future)
9-
* Review: [Pitch](https://forums.swift.org/t/pitch-mutablespan/77790)
8+
* Implementation: [swiftlang/swift#79650](https://github.com/swiftlang/swift/pull/79650)
9+
* Review: ([pitch](https://forums.swift.org/t/pitch-mutablespan/77790)) ([review](https://forums.swift.org/t/se-0467-mutablespan/78454))
1010

1111
[SE-0446]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0446-non-escapable.md
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
1515
[SE-0437]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0437-noncopyable-stdlib-primitives.md
1616
[SE-0453]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0453-vector.md
17-
[SE-0223]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0223-array-uninitialized-initializer.md
17+
[SE-0245]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0245-array-uninitialized-initializer.md
1818
[SE-0176]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0176-enforce-exclusive-access-to-memory.md
1919

2020
## Introduction
@@ -27,7 +27,7 @@ Many standard library container types can provide direct access to modify their
2727

2828
These functions have a few different drawbacks, most prominently their reliance on unsafe types, which makes them unpalatable in security-conscious environments. We continue addressing these issues with `MutableSpan` and `MutableRawSpan`, new non-copyable and non-escapable types that manage respectively mutations of typed and untyped memory.
2929

30-
In addition to the new types, we will propose adding new API some standard library types to take advantage of `MutableSpan` and `MutableRawSpan`.
30+
In addition to the new types, we will propose adding new API to some standard library types to take advantage of `MutableSpan` and `MutableRawSpan`.
3131

3232
## Proposed solution
3333

@@ -53,7 +53,7 @@ A `MutableSpan` provided by a container represents a mutation of that container,
5353
The standard library will provide `mutableSpan` computed properties. These return a new lifetime-dependent `MutableSpan` instance, and that `MutableSpan` represents a mutation of the instance that provided it. The `mutableSpan` computed properties are the safe and composable replacements for the existing `withUnsafeMutableBufferPointer` closure-taking functions. For example,
5454

5555
```swift
56-
func(_ array: inout Array<Int>) {
56+
func example(_ array: inout Array<Int>) {
5757
var ms = array.mutableSpan
5858
modify(&ms) // call function that mutates a MutableSpan<Int>
5959
// array.append(2) // attempt to modify `array` would be an error here
@@ -119,7 +119,7 @@ public struct MutableSpan<Element: ~Copyable & ~Escapable>: ~Copyable, ~Escapabl
119119
internal var _count: Int
120120
}
121121

122-
extension MutableSpan: @unchecked Sendable where Element: Sendable {}
122+
extension MutableSpan: @unchecked Sendable where Element: Sendable & ~Copyable & ~Escapable {}
123123
````
124124

125125
We store a `UnsafeMutableRawPointer` 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 `MutableSpan`, since accesses are bounds-checked and the pointer is only dereferenced when the `MutableSpan` isn't empty, when the pointer cannot be `nil`.
@@ -532,7 +532,7 @@ extension MutableRawSpan {
532532
) throws(E) -> Result
533533
}
534534
```
535-
These functions use a closure to define the scope of validity of `buffer`, ensuring that the underlying `MutableSpan` and the binding it depends on both remain valid through the end of the closure. They have the same shape as the equivalents on `Array` because they fulfill the same purpose, namely to keep the underlying binding alive.
535+
These functions use a closure to define the scope of validity of `buffer`, ensuring that the underlying `MutableRawSpan` and the binding it depends on both remain valid through the end of the closure. They have the same shape as the equivalents on `Array` because they fulfill the same purpose, namely to keep the underlying binding alive.
536536

537537
#### <a name="extensions"></a>Properties providing `MutableSpan` or `MutableRawSpan` instances
538538

@@ -657,7 +657,7 @@ During the evolution of Swift, we have learned that closure-based API are diffic
657657

658658
#### Omitting extensions to `UnsafeBufferPointer` and related types
659659

660-
We could omit the extensions to `UnsafeMutableBufferPointer` and related types, and rely instead of future `MutableSpan` and `MutableRawSpan` initializers. The initializers can have the advantage of being able to communicate semantics (somewhat) through their parameter labels. However, they also have a very different shape than the `storage` computed properties we are proposing for the safe types such as `Array`. We believe that the adding the same API on both safe and unsafe types is advantageous, even if the preconditions for the properties cannot be statically enforced.
660+
We could omit the extensions to `UnsafeMutableBufferPointer` and related types, and rely instead of future `MutableSpan` and `MutableRawSpan` initializers. The initializers can have the advantage of being able to communicate semantics (somewhat) through their parameter labels. However, they also have a very different shape than the `mutableSpan` computed properties we are proposing for the safe types such as `Array`. We believe that the adding the same API on both safe and unsafe types is advantageous, even if the preconditions for the properties cannot be statically enforced.
661661

662662
## <a name="directions"></a>Future directions
663663

@@ -667,7 +667,7 @@ Note: The future directions stated in [SE-0447](https://github.com/swiftlang/swi
667667

668668
`MutableSpan` represents a region of memory and, as such, must be initialized using an unsafe pointer. This is an unsafe operation which will typically be performed internally to a container's implementation. In order to bridge to safe code, these initializers require new annotations that indicate to the compiler how the newly-created `Span` can be used safely.
669669

670-
These annotations have been [pitched][PR-2305-pitch] and, after revision, are expected to be pitched again soon. `MutableSpan` initializers using lifetime annotations will be proposed alongside the annotations themselves.
670+
These annotations have been [pitched][PR-2305] and, after revision, are expected to be pitched again soon. `MutableSpan` initializers using lifetime annotations will be proposed alongside the annotations themselves.
671671

672672
#### Functions providing variants of `MutableRawSpan` to `MutableSpan`
673673

@@ -717,6 +717,6 @@ The range of `extracting()` functions proposed here expands upon the range accep
717717

718718
#### <a name="OutputSpan"></a>Delegated initialization with `OutputSpan<T>`
719719

720-
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.
720+
Some data structures can delegate initialization of parts of their owned memory. The standard library added the `Array` initializer `init(unsafeUninitializedCapacity:initializingWith:)` in [SE-0245][]. 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.
721721

722722
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.

0 commit comments

Comments
 (0)