Skip to content
Permalink
main
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time

Add overrides taking an UnsafePointer source to non-destructive copying methods on UnsafeMutablePointer

Introduction

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

Motivation

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.

Proposed solution

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)

Detailed design

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)

Impact on existing code

This proposal is additive and does not impact existing code.

Alternatives considered

  • 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 to UnsafePointer could be leveraged to work around the need for overloads by dropping the existing methods taking UnsafeMutablePointer source arguments. Adding explicit overloads seems a better solution than depending on compiler magic and is clearer from a documentation and auto-completion perspective.