Add overrides taking an UnsafePointer source to non-destructive copying methods on UnsafeMutablePointer
- Proposal: SE-0076
- Author: Janosch Hildebrand
- Status: Accepted with Revisions for Swift 3 (Rationale, Bug)
- Review manager: Chris Lattner
UnsafeMutablePointer
includes several methods to non-destructively copy elements from memory pointed to by another UnsafeMutablePointer
instance. I propose adding overloads of these methods to UnsafeMutablePointer
that allow an UnsafePointer
source.
Swift-evolution thread: [Pitch] Add overrides with UnsafePointer sources to non-destructive copying methods on UnsafeMutablePointer
To copy values from memory pointed to by an UnsafePointer
it is currently necessary to perform a cast to UnsafeMutablePointer
beforehand:
let source: UnsafePointer<Int> = ...
let destination: UnsafeMutablePointer<Int> = ...
// Today:
destination.assignFrom(UnsafeMutablePointer(source), count: count)
These casts are unnecessary visual noise as non-destructively copying from an UnsafePointer
source is perfectly safe.
Furthermore, these casts are a source of confusion and increased cognitive load on a reader since any such cast is likely to throw up a red flag at first.
In addition to these existing methods on UnsafeMutablePointer:
func assignBackwardFrom(source: UnsafeMutablePointer<Pointee>, count: Int)
func assignFrom(source: UnsafeMutablePointer<Pointee>, count: Int)
func initializeFrom(source: UnsafeMutablePointer<Pointee>, count: Int)
I propose adding the following overloads:
func assignBackwardFrom(source: UnsafePointer<Pointee>, count: Int)
func assignFrom(source: UnsafePointer<Pointee>, count: Int)
func initializeFrom(source: UnsafePointer<Pointee>, count: Int)
This would transform the given example as follows:
let source: UnsafePointer<Int> = ...
let destination: UnsafeMutablePointer<Int> = ...
// Today:
destination.assignFrom(UnsafeMutablePointer(source), count: count)
// This proposal:
destination.assignFrom(source, count: count)
The following methods are added to UnsafeMutablePointer
:
/// Assign from `count` values beginning at source into initialized
/// memory, proceeding from the first element to the last.
public func assignFrom(source: UnsafePointer<Pointee>, count: Int)
/// Assign from `count` values beginning at `source` into
/// initialized memory, proceeding from the last value to the first.
/// Use this for assigning ranges into later memory that may overlap
/// with the source range.
///
/// - Requires: Either `source` precedes `self` or follows `self + count`.
public func assignBackwardFrom(source: UnsafePointer<Pointee>, count: Int)
/// Copy `count` values beginning at source into raw memory.
///
/// - Precondition: The memory is not initialized.
///
/// - Requires: `self` and `source` may not overlap.
public func initializeFrom(source: UnsafePointer<Pointee>, count: Int)
This proposal is additive and does not impact existing code.
-
Keep the status quo: I'd argue that they provide enough benefit to justify their existence while only minimally increasing the stdlib surface area, especially by merit of being overloads.
-
Introduce a
PointerProtocol
protocol: A common protocol could be used to avoid the need for overloads in this case. However, without additional use cases this seems like severe over-engineering for this simple issue. This would also require a lot more design work, performance considerations, etc... -
Leverage implicit conversions: The implicit conversions from
UnsafeMutablePointer
toUnsafePointer
could be leveraged to work around the need for overloads by dropping the existing methods takingUnsafeMutablePointer
source arguments. Adding explicit overloads seems a better solution than depending on compiler magic and is clearer from a documentation and auto-completion perspective.