swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.46k stars 10.35k forks source link

[SR-11087] Add a closure taking API: UnsafeRaw[Mutable][Buffer]Pointer.withMemoryRebound(to:[capacity:]) #53479

Closed atrick closed 2 years ago

atrick commented 5 years ago
Previous ID SR-11087
Radar rdar://81800124
Original Reporter @atrick
Type New Feature
Status Resolved
Resolution Done
Additional Detail from JIRA | | | |------------------|-----------------| |Votes | 1 | |Component/s | Standard Library | |Labels | New Feature, LanguageFeatureRequest | |Assignee | @glessard | |Priority | Medium | md5: 21b1f3b49a4fdfac61bbe80110d519eb

Issue Description:

Specifically:

extension Unsafe[Mutable]RawPointer {
  public func withMemoryRebound<T, Result>(to type: T.Type, capacity count: Int,
    _ body: (UnsafePointer<T>) throws -> Result
  ) rethrows -> Result
  {...}
}

extension Unsafe[Mutable]RawBufferPointer {
  public func withMemoryRebound<T, Result>(
    to type: T.Type, _ body: (${Self}<T>) throws -> Result
  ) rethrows -> Result
  {...}
}

This API will allow code to temporarily view raw memory as a memory holding the specified type. Within the closure scope, it will be legal to access memory via a typed pointer of the rebound type.

This is both a standard library addition and SIL-level compiler feature.

Note that we still don't want higher-level APIs (e.g. Foundation Data) that already erased the pointer type to vend a typed pointer to the user in any way, unless we can guarantee that they have exclusive access to the memory. In other words, providing the user with a non-unique typed pointer into raw memory of unknown provenance is inherently unsafe and shouldn't be hidden behind a commonly used convenience API that implies safety.

Suggested design:

In SIL, add a return type to the bind_memory memory instruction. The returned $Builtin.Word would be a token representing the previously bound memory state. The token is not actually a type and can't be used for anything other than rebinding the memory. Add a new rebind_memory instruction that takes this token instead of a type parameter.

If the prior bound memory type is available via static analysis, then the rebind_memory instruction can be substituted with a normal bind_memory.

Note: Although deprecated, the Foundation Data APIs withUnsafeBytes and withUnsafeMutableBytes should be fixed to use

withMemoryRebound(to:)

instead of

assumingMemoryBound(to:)

.

glessard commented 2 years ago

Addressed by https://github.com/apple/swift/pull/40156, SE-0333 and https://github.com/apple/swift/pull/39529