-
Notifications
You must be signed in to change notification settings - Fork 191
[SE-0456, -0467] Data+Span+MutableSpan #1276
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5196b1e
9857ce1
efd6b6c
8a6a7d9
a02e0b7
88e1cbd
9e8be79
fa9f9fb
9913bdd
9ed87ab
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,7 +9,8 @@ import CompilerPluginSupport | |
let availabilityTags: [_Availability] = [ | ||
_Availability("FoundationPreview"), // Default FoundationPreview availability, | ||
_Availability("FoundationPredicate"), // Predicate relies on pack parameter runtime support | ||
_Availability("FoundationPredicateRegex") // Predicate regexes rely on new stdlib APIs | ||
_Availability("FoundationPredicateRegex"), // Predicate regexes rely on new stdlib APIs | ||
_Availability("FoundationSpan", availability: .future), // Availability of Span types | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could choose to change that to 6.0, or maybe 6.1, if we wanted but we don't want to make this 6.2 yet so I think it's best to keep it as-is. The tools version is not the same as the compiler version for Xcode/Darwin as the tools version is strictly equivalent to what tools are packaged in Xcode when you build the package in Xcode (and not the tools in your selected toolchain). There isn't yet an Xcode that ships with 6.2 tools, so to support building this project with older Xcodes (even with a downloaded 6.2 OSS toolchain) we'd want to support a lower tools version. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was thinking of doing that in a follow-up PR |
||
] | ||
let versionNumbers = ["0.1", "0.2", "0.3", "0.4", "6.0.2", "6.1", "6.2"] | ||
|
||
|
@@ -134,6 +135,18 @@ let package = Package( | |
] + wasiLibcCSettings, | ||
swiftSettings: [ | ||
.enableExperimentalFeature("VariadicGenerics"), | ||
.enableExperimentalFeature("LifetimeDependence"), | ||
.enableExperimentalFeature( | ||
"InoutLifetimeDependence", | ||
.when(platforms: [.macOS, .iOS, .watchOS, .tvOS, .linux]) | ||
), | ||
.enableExperimentalFeature( | ||
"LifetimeDependenceMutableAccessors", | ||
.when(platforms: [.macOS, .iOS, .watchOS, .tvOS, .linux]) | ||
), | ||
.enableExperimentalFeature("AddressableTypes"), | ||
.enableExperimentalFeature("AllowUnsafeAttribute"), | ||
.enableExperimentalFeature("BuiltinModule"), | ||
.enableExperimentalFeature("AccessLevelOnImport") | ||
] + availabilityMacros + featureSettings, | ||
linkerSettings: [ | ||
|
@@ -149,7 +162,16 @@ let package = Package( | |
resources: [ | ||
.copy("Resources") | ||
], | ||
swiftSettings: availabilityMacros + featureSettings | ||
swiftSettings: [ | ||
.enableExperimentalFeature( | ||
"InoutLifetimeDependence", | ||
.when(platforms: [.macOS, .iOS, .watchOS, .tvOS, .linux]) | ||
), | ||
.enableExperimentalFeature( | ||
"LifetimeDependenceMutableAccessors", | ||
.when(platforms: [.macOS, .iOS, .watchOS, .tvOS, .linux]) | ||
), | ||
] + availabilityMacros + featureSettings | ||
), | ||
|
||
// FoundationInternationalization | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,6 +49,7 @@ | |
#endif | ||
|
||
internal import _FoundationCShims | ||
import Builtin | ||
glessard marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
#if canImport(Darwin) | ||
import Darwin | ||
|
@@ -604,6 +605,9 @@ internal final class __DataStorage : @unchecked Sendable { | |
|
||
@frozen | ||
@available(macOS 10.10, iOS 8.0, watchOS 2.0, tvOS 9.0, *) | ||
#if compiler(>=6.2) | ||
@_addressableForDependencies | ||
glessard marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#endif | ||
public struct Data : Equatable, Hashable, RandomAccessCollection, MutableCollection, RangeReplaceableCollection, MutableDataProtocol, ContiguousBytes, Sendable { | ||
|
||
public typealias Index = Int | ||
|
@@ -2198,7 +2202,107 @@ public struct Data : Equatable, Hashable, RandomAccessCollection, MutableCollect | |
public func withUnsafeBytes<ResultType>(_ body: (UnsafeRawBufferPointer) throws -> ResultType) rethrows -> ResultType { | ||
return try _representation.withUnsafeBytes(body) | ||
} | ||
|
||
|
||
#if compiler(>=6.2) && $LifetimeDependence | ||
@available(FoundationSpan 6.2, *) | ||
public var bytes: RawSpan { | ||
@lifetime(borrow self) | ||
borrowing get { | ||
let buffer: UnsafeRawBufferPointer | ||
switch _representation { | ||
case .empty: | ||
buffer = UnsafeRawBufferPointer(start: nil, count: 0) | ||
case .inline: | ||
buffer = unsafe UnsafeRawBufferPointer( | ||
start: UnsafeRawPointer(Builtin.addressOfBorrow(self)), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we opening the door here for Foundation to use the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The issue with the |
||
count: _representation.count | ||
) | ||
case .large(let slice): | ||
buffer = unsafe UnsafeRawBufferPointer( | ||
start: slice.storage.mutableBytes?.advanced(by: slice.startIndex), count: slice.count | ||
) | ||
case .slice(let slice): | ||
buffer = unsafe UnsafeRawBufferPointer( | ||
start: slice.storage.mutableBytes?.advanced(by: slice.startIndex), count: slice.count | ||
) | ||
} | ||
let span = unsafe RawSpan(_unsafeBytes: buffer) | ||
return unsafe _overrideLifetime(span, borrowing: self) | ||
} | ||
} | ||
|
||
@available(FoundationSpan 6.2, *) | ||
public var span: Span<UInt8> { | ||
@lifetime(borrow self) | ||
borrowing get { | ||
let span = unsafe bytes._unsafeView(as: UInt8.self) | ||
return _overrideLifetime(span, borrowing: self) | ||
} | ||
} | ||
#endif | ||
|
||
#if compiler(>=5.9) && $InoutLifetimeDependence && $LifetimeDependenceMutableAccessors | ||
@available(FoundationSpan 6.2, *) | ||
public var mutableBytes: MutableRawSpan { | ||
@lifetime(&self) | ||
mutating get { | ||
let buffer: UnsafeMutableRawBufferPointer | ||
switch _representation { | ||
case .empty: | ||
buffer = UnsafeMutableRawBufferPointer(start: nil, count: 0) | ||
case .inline: | ||
buffer = unsafe UnsafeMutableRawBufferPointer( | ||
start: UnsafeMutableRawPointer(Builtin.addressOfBorrow(self)), | ||
count: _representation.count | ||
) | ||
case .large(let slice): | ||
buffer = unsafe UnsafeMutableRawBufferPointer( | ||
start: slice.storage.mutableBytes?.advanced(by: slice.startIndex), count: slice.count | ||
) | ||
case .slice(let slice): | ||
buffer = unsafe UnsafeMutableRawBufferPointer( | ||
start: slice.storage.mutableBytes?.advanced(by: slice.startIndex), count: slice.count | ||
) | ||
} | ||
let span = unsafe MutableRawSpan(_unsafeBytes: buffer) | ||
return unsafe _overrideLifetime(span, mutating: &self) | ||
} | ||
} | ||
|
||
@available(FoundationSpan 6.2, *) | ||
public var mutableSpan: MutableSpan<UInt8> { | ||
@lifetime(&self) | ||
mutating get { | ||
#if false // see https://github.com/swiftlang/swift/issues/81218 | ||
var bytes = mutableBytes | ||
let span = unsafe bytes._unsafeMutableView(as: UInt8.self) | ||
return _overrideLifetime(span, mutating: &self) | ||
#else | ||
let buffer: UnsafeMutableRawBufferPointer | ||
switch _representation { | ||
case .empty: | ||
buffer = UnsafeMutableRawBufferPointer(start: nil, count: 0) | ||
case .inline: | ||
buffer = unsafe UnsafeMutableRawBufferPointer( | ||
start: UnsafeMutableRawPointer(Builtin.addressOfBorrow(self)), | ||
count: _representation.count | ||
) | ||
case .large(let slice): | ||
buffer = unsafe UnsafeMutableRawBufferPointer( | ||
start: slice.storage.mutableBytes?.advanced(by: slice.startIndex), count: slice.count | ||
) | ||
case .slice(let slice): | ||
buffer = unsafe UnsafeMutableRawBufferPointer( | ||
start: slice.storage.mutableBytes?.advanced(by: slice.startIndex), count: slice.count | ||
) | ||
} | ||
let span = unsafe MutableSpan<UInt8>(_unsafeBytes: buffer) | ||
return unsafe _overrideLifetime(span, mutating: &self) | ||
#endif | ||
} | ||
} | ||
#endif // $InoutLifetimeDependence && $LifetimeDependenceMutableAccessors | ||
|
||
@_alwaysEmitIntoClient | ||
public func withContiguousStorageIfAvailable<ResultType>(_ body: (_ buffer: UnsafeBufferPointer<UInt8>) throws -> ResultType) rethrows -> ResultType? { | ||
return try _representation.withUnsafeBytes { | ||
|
@@ -2870,3 +2974,57 @@ extension Data : Codable { | |
} | ||
} | ||
} | ||
|
||
// TODO: remove once _overrideLifetime is public in the standard library | ||
glessard marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#if compiler(>=6.2) && $LifetimeDependence | ||
/// Unsafely discard any lifetime dependency on the `dependent` argument. Return | ||
/// a value identical to `dependent` with a lifetime dependency on the caller's | ||
/// borrow scope of the `source` argument. | ||
@unsafe | ||
@_unsafeNonescapableResult | ||
@_alwaysEmitIntoClient | ||
@_transparent | ||
@lifetime(borrow source) | ||
internal func _overrideLifetime< | ||
T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable | ||
>( | ||
_ dependent: consuming T, borrowing source: borrowing U | ||
) -> T { | ||
dependent | ||
} | ||
|
||
/// Unsafely discard any lifetime dependency on the `dependent` argument. Return | ||
/// a value identical to `dependent` that inherits all lifetime dependencies from | ||
/// the `source` argument. | ||
@unsafe | ||
@_unsafeNonescapableResult | ||
@_alwaysEmitIntoClient | ||
@_transparent | ||
@lifetime(copy source) | ||
internal func _overrideLifetime< | ||
T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable | ||
>( | ||
_ dependent: consuming T, copying source: borrowing U | ||
) -> T { | ||
dependent | ||
} | ||
#endif | ||
|
||
#if compiler(>=5.9) && $InoutLifetimeDependence && $LifetimeDependenceMutableAccessors | ||
/// Unsafely discard any lifetime dependency on the `dependent` argument. | ||
/// Return a value identical to `dependent` with a lifetime dependency | ||
/// on the caller's exclusive borrow scope of the `source` argument. | ||
@unsafe | ||
@_unsafeNonescapableResult | ||
@_alwaysEmitIntoClient | ||
@_transparent | ||
@lifetime(&source) | ||
internal func _overrideLifetime< | ||
T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable | ||
>( | ||
_ dependent: consuming T, | ||
mutating source: inout U | ||
) -> T { | ||
dependent | ||
} | ||
#endif // $InoutLifetimeDependence && $LifetimeDependenceMutableAccessors |
Uh oh!
There was an error while loading. Please reload this page.