Skip to content

Adjust availability and inlinability of span projections #1400

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

Merged
merged 7 commits into from
Jul 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ list(APPEND CMAKE_MODULE_PATH ${SwiftFoundation_SOURCE_DIR}/cmake/modules)

# Availability Macros (only applies to FoundationEssentials and FoundationInternationalization)
set(_SwiftFoundation_BaseAvailability "macOS 15, iOS 18, tvOS 18, watchOS 11")
set(_SwiftFoundation_macOS26Availability "macOS 26, iOS 26, tvOS 26, watchOS 26")
set(_SwiftFoundation_FutureAvailability "macOS 10000, iOS 10000, tvOS 10000, watchOS 10000")

# All versions to define for each availability name
Expand All @@ -106,13 +105,11 @@ list(APPEND _SwiftFoundation_versions

# Each availability name to define
list(APPEND _SwiftFoundation_availability_names
"FoundationPreview"
"FoundationSpan")
"FoundationPreview")

# The aligned availability for each name (in the same order)
list(APPEND _SwiftFoundation_availability_releases
${_SwiftFoundation_BaseAvailability}
${_SwiftFoundation_macOS26Availability})
${_SwiftFoundation_BaseAvailability})

foreach(version ${_SwiftFoundation_versions})
foreach(name release IN ZIP_LISTS _SwiftFoundation_availability_names _SwiftFoundation_availability_releases)
Expand Down
1 change: 0 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import CompilerPluginSupport

let availabilityTags: [_Availability] = [
_Availability("FoundationPreview"), // Default FoundationPreview availability
_Availability("FoundationSpan", availability: .macOS26), // Availability of Span types
]
let versionNumbers = ["6.0.2", "6.1", "6.2"]

Expand Down
62 changes: 8 additions & 54 deletions Sources/FoundationEssentials/Data/Data.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2203,7 +2203,8 @@ public struct Data : Equatable, Hashable, RandomAccessCollection, MutableCollect
return try _representation.withUnsafeBytes(body)
}

@available(FoundationSpan 6.2, *)
@available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.1, *)
@_alwaysEmitIntoClient
public var bytes: RawSpan {
@lifetime(borrow self)
borrowing get {
Expand All @@ -2230,7 +2231,8 @@ public struct Data : Equatable, Hashable, RandomAccessCollection, MutableCollect
}
}

@available(FoundationSpan 6.2, *)
@available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.1, *)
@_alwaysEmitIntoClient
public var span: Span<UInt8> {
@lifetime(borrow self)
borrowing get {
Expand All @@ -2239,7 +2241,8 @@ public struct Data : Equatable, Hashable, RandomAccessCollection, MutableCollect
}
}

@available(FoundationSpan 6.2, *)
@available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.1, *)
@_alwaysEmitIntoClient
public var mutableBytes: MutableRawSpan {
@lifetime(&self)
mutating get {
Expand All @@ -2266,7 +2269,8 @@ public struct Data : Equatable, Hashable, RandomAccessCollection, MutableCollect
}
}

@available(FoundationSpan 6.2, *)
@available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.1, *)
@_alwaysEmitIntoClient
public var mutableSpan: MutableSpan<UInt8> {
@lifetime(&self)
mutating get {
Expand Down Expand Up @@ -2970,53 +2974,3 @@ extension Data : Codable {
}
}
}

// TODO: remove once _overrideLifetime is public in the standard library
/// 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
}

/// 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
}
27 changes: 12 additions & 15 deletions Tests/FoundationEssentialsTests/DataTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1645,8 +1645,8 @@ private final class DataTests {
#endif
}

@available(FoundationSpan 6.2, *)
@Test func inlineDataSpan() throws {
@Test
func inlineDataSpan() throws {
var source = Data()
var span = source.span
var isEmpty = span.isEmpty
Expand All @@ -1661,16 +1661,16 @@ private final class DataTests {
#expect(firstElement == 1)
}

@available(FoundationSpan 6.2, *)
@Test func inlineSliceDataSpan() throws {
@Test
func inlineSliceDataSpan() throws {
let source = Data(0 ... .max)
let span = source.span
#expect(span.count == source.count)
#expect(span[span.indices.last!] == .max)
}

@available(FoundationSpan 6.2, *)
@Test func inlineDataMutableSpan() throws {
@Test
func inlineDataMutableSpan() throws {
#if !canImport(Darwin) || FOUNDATION_FRAMEWORK
var source = Data()
var span = source.mutableSpan
Expand All @@ -1693,8 +1693,8 @@ private final class DataTests {
#endif
}

@available(FoundationSpan 6.2, *)
@Test func inlineSliceDataMutableSpan() throws {
@Test
func inlineSliceDataMutableSpan() throws {
#if !canImport(Darwin) || FOUNDATION_FRAMEWORK
var source = Data(0..<100)
let count = source.count
Expand All @@ -1707,8 +1707,8 @@ private final class DataTests {
#endif
}

@available(FoundationSpan 6.2, *)
@Test func inlineDataMutableRawSpan() throws {
@Test
func inlineDataMutableRawSpan() throws {
var source = Data()
var span = source.mutableBytes
var isEmpty = span.isEmpty
Expand All @@ -1728,8 +1728,8 @@ private final class DataTests {
#expect(source[i] == v)
}

@available(FoundationSpan 6.2, *)
@Test func inlineSliceDataMutableRawSpan() throws {
@Test
func inlineSliceDataMutableRawSpan() throws {
var source = Data(0..<100)
let count = source.count
var span = source.mutableBytes
Expand Down Expand Up @@ -2386,7 +2386,6 @@ extension DataTests {
@Suite("Large Data Tests", .serialized)
struct LargeDataTests {
@Test
@available(FoundationSpan 6.2, *)
func largeSliceDataSpan() throws {
#if _pointerBitWidth(_64)
let count = Int(Int32.max)
Expand All @@ -2404,7 +2403,6 @@ struct LargeDataTests {
}

@Test
@available(FoundationSpan 6.2, *)
func largeSliceDataMutableSpan() throws {
#if _pointerBitWidth(_64)
var count = Int(Int32.max)
Expand All @@ -2428,7 +2426,6 @@ struct LargeDataTests {
}

@Test
@available(FoundationSpan 6.2, *)
func largeSliceDataMutableRawSpan() throws {
#if _pointerBitWidth(_64)
var count = Int(Int32.max)
Expand Down