From 27ac1982ae6ccbe248ea1980e878beb4a5b7a614 Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Fri, 30 Mar 2018 14:56:02 -0700 Subject: [PATCH 1/2] Proposal to add value-taking forms of `withUnsafeBytes` and `withUnsafePointer`. --- proposals/NNNN-withUnsafePointer-for-lets.md | 88 ++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 proposals/NNNN-withUnsafePointer-for-lets.md diff --git a/proposals/NNNN-withUnsafePointer-for-lets.md b/proposals/NNNN-withUnsafePointer-for-lets.md new file mode 100644 index 0000000000..1db02d03ad --- /dev/null +++ b/proposals/NNNN-withUnsafePointer-for-lets.md @@ -0,0 +1,88 @@ +# `withUnsafePointer(to:_:)` and `withUnsafeBytes(of:_:)` for immutable values + +* Proposal: [SE-NNNN](NNNN-withUnsafePointer-for-lets.md) +* Authors: [Joe Groff](https://github.com/jckarter) +* Review Manager: TBD +* Status: **Awaiting review** +* Implementation: [apple/swift#15608](https://github.com/apple/swift/pull/15608) + +## Introduction + +We propose to extend the toplevel `withUnsafePointer(to:_:)` and +`withUnsafeBytes(of:_:)` functions to work with read-only values. + +Swift-evolution thread: [`withUnsafePointer` and `withUnsafeBytes` for immutable arguments](https://forums.swift.org/t/withunsafepointer-and-withunsafebytes-for-immutable-arguments/11493/5) + +## Motivation + +`withUnsafePointer` and `withUnsafeBytes` provide temporary scoped access to +the in-memory representation of variables and properties via pointers. They +currently only accept `inout` arguments, which makes working with the +in-memory representation of immutable values more awkward and inefficient +than it ought to be, requiring a copy: + +``` +let x = 1 + 2 +var x2 = x +withUnsafeBytes(of: &x2) { ... } +``` + +Even for `inout` arguments, the semantics of `withUnsafeBytes` and +`withUnsafePointer` are extremely narrow: the pointer cannot be used after +the closure returns, cannot be mutably aliased, and is not guaranteed to +have a stable identity across `withUnsafe*` applications to the same +property. There's therefore no fundamental reason these operations couldn't +also be offered on arbitrary read-only variables or temporary values, since +memory does not need to be persisted for longer than a call. It is a +frequent request to extend these APIs to work with read-only values. + +## Proposed solution + +We add overloads of `withUnsafeBytes` and `withUnsafePointer` that accept +their `to`/`of` argument by value (by shared borrow, when we get moveonly +types). + +## Detailed design + +The following top-level functions are added to the standard library: + +``` +public func withUnsafePointer( + to value: /*borrowed*/ T, + _ body: (UnsafePointer) throws -> Result +) rethrows -> Result + +public func withUnsafeBytes( + of value: /*borrowed*/ T, + _ body: (UnsafeRawBufferPointer) throws -> Result +) rethrows -> Result +``` + +Like their `inout`-taking siblings, each method produces a pointer to +the in-memory representation of its `value` argument and invokes the `body` +closure with the pointer. The pointer is only valid for the duration of `body`. +It is undefined behavior to write through the pointer or access it after +`body` returns. It is unspecified whether taking a pointer to the same +variable or property produces a consistent pointer value across different +`withUnsafePointer`/`Bytes` calls. + +We do not propose removing the `inout`-taking forms of `withUnsafePointer` +and `withUnsafeBytes`, both for source compatibility, and because in Swift +today, using `inout` is still the only reliably way to assert exclusive +access to storage and suppress implicit copying. Optimized Swift code +ought to in principle avoid copying when `withUnsafePointer(to: x)` is passed +a stored `let` property `x` that is known to be immutable, and with moveonly +types it would be possible to statically guarantee this, but in Swift today +this cannot be guaranteed. + +## Source compatibility + +Existing code can continue to use the `inout`-taking forms without modification. + +## Effect on ABI stability/API resilience + +This is a purely additive change to the standard library. In anticipation +of a future version of Swift adding moveonly types, we should ensure that +the implementations of `withUnsafePointer` and `withUnsafeBytes` takes their +arguments +0 so that they will be ABI-compatible with shared borrows of +moveonly types in the future. From 5552133e9bce0cb6b34d7688c7e7ef0bb1b13799 Mon Sep 17 00:00:00 2001 From: Ben Cohen Date: Wed, 4 Apr 2018 16:14:21 -0700 Subject: [PATCH 2/2] Running as SE-0205 --- ...inter-for-lets.md => 0205-withUnsafePointer-for-lets.md} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename proposals/{NNNN-withUnsafePointer-for-lets.md => 0205-withUnsafePointer-for-lets.md} (95%) diff --git a/proposals/NNNN-withUnsafePointer-for-lets.md b/proposals/0205-withUnsafePointer-for-lets.md similarity index 95% rename from proposals/NNNN-withUnsafePointer-for-lets.md rename to proposals/0205-withUnsafePointer-for-lets.md index 1db02d03ad..81a328375a 100644 --- a/proposals/NNNN-withUnsafePointer-for-lets.md +++ b/proposals/0205-withUnsafePointer-for-lets.md @@ -1,9 +1,9 @@ # `withUnsafePointer(to:_:)` and `withUnsafeBytes(of:_:)` for immutable values -* Proposal: [SE-NNNN](NNNN-withUnsafePointer-for-lets.md) +* Proposal: [SE-0205](0205-withUnsafePointer-for-lets.md) * Authors: [Joe Groff](https://github.com/jckarter) -* Review Manager: TBD -* Status: **Awaiting review** +* Review Manager: [Ben Cohen](https://github.com/airspeedswift) +* Status: **In review (4th to 11th April)** * Implementation: [apple/swift#15608](https://github.com/apple/swift/pull/15608) ## Introduction