Skip to content

Update availability macros for macOS 15 deployment target #1397

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 1 commit into from
Jul 1, 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
11 changes: 2 additions & 9 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,11 @@ 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
list(APPEND _SwiftFoundation_versions
"0.1"
"0.2"
"0.3"
"0.4"
"6.0.2"
"6.1"
"6.2"
Expand All @@ -110,16 +107,12 @@ list(APPEND _SwiftFoundation_versions
# Each availability name to define
list(APPEND _SwiftFoundation_availability_names
"FoundationPreview"
"FoundationPredicate"
"FoundationPredicateRegex"
"FoundationSpan")

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

foreach(version ${_SwiftFoundation_versions})
foreach(name release IN ZIP_LISTS _SwiftFoundation_availability_names _SwiftFoundation_availability_releases)
Expand Down
9 changes: 4 additions & 5 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,16 @@ import CompilerPluginSupport
// Availability Macros

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("FoundationSpan", availability: .future), // Availability of Span types
_Availability("FoundationPreview"), // Default FoundationPreview availability
_Availability("FoundationSpan", availability: .macOS26), // Availability of Span types
]
let versionNumbers = ["0.1", "0.2", "0.3", "0.4", "6.0.2", "6.1", "6.2"]
let versionNumbers = ["6.0.2", "6.1", "6.2"]

// Availability Macro Utilities

enum _OSAvailability: String {
case alwaysAvailable = "macOS 15, iOS 18, tvOS 18, watchOS 11" // This should match the package's deployment target
case macOS26 = "macOS 26, iOS 26, tvOS 26, watchOS 26"
// Use 10000 for future availability to avoid compiler magic around the 9999 version number but ensure it is greater than 9999
case future = "macOS 10000, iOS 10000, tvOS 10000, watchOS 10000"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ extension AttributedString.CharacterView: BidirectionalCollection {
return _defaultCount
}

@available(FoundationPreview 0.1, *)
@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *)
@usableFromInline
internal var _count: Int {
_characters.count
Expand Down Expand Up @@ -153,7 +153,7 @@ extension AttributedString.CharacterView: BidirectionalCollection {
return _defaultIndex(i, offsetBy: distance)
}

@available(FoundationPreview 0.1, *)
@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *)
@usableFromInline
internal func _index(_ i: AttributedString.Index, offsetBy distance: Int) -> AttributedString.Index {
precondition(i >= startIndex && i <= endIndex, "AttributedString index out of bounds")
Expand All @@ -176,7 +176,7 @@ extension AttributedString.CharacterView: BidirectionalCollection {
return _defaultIndex(i, offsetBy: distance, limitedBy: limit)
}

@available(FoundationPreview 0.1, *)
@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *)
@usableFromInline
internal func _index(
_ i: AttributedString.Index,
Expand Down Expand Up @@ -207,7 +207,7 @@ extension AttributedString.CharacterView: BidirectionalCollection {
return _defaultDistance(from: start, to: end)
}

@available(FoundationPreview 0.1, *)
@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *)
@usableFromInline
internal func _distance(from start: AttributedString.Index, to end: AttributedString.Index) -> Int {
precondition(start >= startIndex && start <= endIndex, "AttributedString index out of bounds")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ extension AttributedString.Runs: BidirectionalCollection {
#endif
}

@available(FoundationPreview 0.1, *)
@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *)
@usableFromInline
internal func _index(_ index: Index, offsetBy distance: Int) -> Index {
guard _isDiscontiguous else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ extension AttributedString.UnicodeScalarView: BidirectionalCollection {
return _defaultCount
}

@available(FoundationPreview 0.1, *)
@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *)
@usableFromInline
internal var _count: Int {
_unicodeScalars.count
Expand Down Expand Up @@ -165,7 +165,7 @@ extension AttributedString.UnicodeScalarView: BidirectionalCollection {
return _defaultIndex(i, offsetBy: distance, limitedBy: limit)
}

@available(FoundationPreview 0.1, *)
@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *)
@usableFromInline
internal func _index(
_ i: AttributedString.Index,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ extension String {
}
#endif

@available(FoundationPreview 0.1, *)
@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *)
@usableFromInline
internal init(_characters: AttributedString.CharacterView) {
self.init(_characters._characters)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ extension AttributeScopes {
public let writingDirection: WritingDirectionAttribute

#if FOUNDATION_FRAMEWORK
@available(FoundationPreview 0.1, *)
@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *)
public let agreementConcept: AgreementConceptAttribute
@available(FoundationPreview 0.1, *)
@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *)
public let agreementArgument: AgreementArgumentAttribute
@available(FoundationPreview 0.1, *)
@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *)
public let referentConcept: ReferentConceptAttribute
@available(FoundationPreview 0.4, *)
@available(macOS 15, iOS 18, tvOS 18, watchOS 11, *)
public let localizedNumberFormat: LocalizedNumberFormatAttribute

// TODO: Support AttributedString markdown in FoundationPreview: https://github.com/apple/swift-foundation/issues/44
Expand Down Expand Up @@ -119,23 +119,23 @@ extension AttributeScopes.FoundationAttributes {
#if FOUNDATION_FRAMEWORK

@frozen
@available(FoundationPreview 0.1, *)
@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *)
public enum ReferentConceptAttribute : CodableAttributedStringKey, MarkdownDecodableAttributedStringKey {
public typealias Value = Int
public static let name = NSAttributedString.Key.referentConcept.rawValue
public static let markdownName = "referentConcept"
}

@frozen
@available(FoundationPreview 0.1, *)
@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *)
public enum AgreementConceptAttribute : CodableAttributedStringKey, MarkdownDecodableAttributedStringKey {
public typealias Value = Int
public static let name = NSAttributedString.Key.agreeWithConcept.rawValue
public static let markdownName = "agreeWithConcept"
}

@frozen
@available(FoundationPreview 0.1, *)
@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *)
public enum AgreementArgumentAttribute : CodableAttributedStringKey, MarkdownDecodableAttributedStringKey {
public typealias Value = Int
public static let name = NSAttributedString.Key.agreeWithArgument.rawValue
Expand Down Expand Up @@ -168,7 +168,7 @@ extension AttributeScopes.FoundationAttributes {
}

@frozen
@available(FoundationPreview 0.4, *)
@available(macOS 15, iOS 18, tvOS 18, watchOS 11, *)
public enum LocalizedNumberFormatAttribute : CodableAttributedStringKey, MarkdownDecodableAttributedStringKey {
public struct Value: Equatable, Hashable, Codable, Sendable {
enum Format {
Expand Down Expand Up @@ -851,7 +851,7 @@ extension AttributeScopes.FoundationAttributes.PersonNameComponentAttribute : Ob
public typealias ObjectiveCValue = NSString
}

@available(FoundationPreview 0.4, *)
@available(macOS 15, iOS 18, tvOS 18, watchOS 11, *)
extension AttributeScopes.FoundationAttributes.LocalizedNumberFormatAttribute.Value: _ObjectiveCBridgeable {
public func _bridgeToObjectiveC() -> __NSLocalizedNumberFormatRule {
switch self.format {
Expand Down
14 changes: 7 additions & 7 deletions Sources/FoundationEssentials/Calendar/Calendar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -323,10 +323,10 @@ public struct Calendar : Hashable, Equatable, Sendable {
case nanosecond
case calendar
case timeZone
@available(FoundationPreview 0.1, *)
@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *)
case isLeapMonth

@available(FoundationPreview 0.4, *)
@available(macOS 15, iOS 18, tvOS 18, watchOS 11, *)
case dayOfYear

fileprivate var componentSetValue: ComponentSet.RawValue {
Expand Down Expand Up @@ -620,7 +620,7 @@ public struct Calendar : Hashable, Equatable, Sendable {
/// - parameter value: The value of the specified component to add or subtract. The default value is `1`. The value can be negative, which causes subtraction.
/// - parameter wrappingComponents: If `true`, the component should be incremented and wrap around to zero/one on overflow, and should not cause higher components to be incremented. The default value is `false`.
/// - returns: A `Sequence` of `Date` values, or an empty sequence if no addition could be performed.
@available(FoundationPreview 0.4, *)
@available(macOS 15, iOS 18, tvOS 18, watchOS 11, *)
public func dates(byAdding component: Calendar.Component,
value: Int = 1,
startingAt start: Date,
Expand All @@ -641,7 +641,7 @@ public struct Calendar : Hashable, Equatable, Sendable {
/// - parameter components: The components to add or subtract.
/// - parameter wrappingComponents: If `true`, the component should be incremented and wrap around to zero/one on overflow, and should not cause higher components to be incremented. The default value is `false`.
/// - returns: A `Sequence` of `Date` values, or an empty sequence if no addition could be performed.
@available(FoundationPreview 0.4, *)
@available(macOS 15, iOS 18, tvOS 18, watchOS 11, *)
public func dates(byAdding components: DateComponents,
startingAt start: Date,
in range: Range<Date>? = nil,
Expand Down Expand Up @@ -1222,7 +1222,7 @@ public struct Calendar : Hashable, Equatable, Sendable {
/// - parameter matchingPolicy: Determines the behavior of the search algorithm when the input produces an ambiguous result.
/// - parameter repeatedTimePolicy: Determines the behavior of the search algorithm when the input produces a time that occurs twice on a particular day.
/// - parameter direction: Which direction in time to search. The default value is `.forward`, which means later in time.
@available(FoundationPreview 0.4, *)
@available(macOS 15, iOS 18, tvOS 18, watchOS 11, *)
public func dates(byMatching components: DateComponents,
startingAt start: Date,
in range: Range<Date>? = nil,
Expand Down Expand Up @@ -1617,7 +1617,7 @@ package struct WeekendRange: Equatable, Hashable {
}
}

@available(FoundationPreview 0.4, *)
@available(macOS 15, iOS 18, tvOS 18, watchOS 11, *)
extension Calendar.MatchingPolicy: Codable {
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
Expand Down Expand Up @@ -1650,7 +1650,7 @@ extension Calendar.MatchingPolicy: Codable {
}
}

@available(FoundationPreview 0.4, *)
@available(macOS 15, iOS 18, tvOS 18, watchOS 11, *)
extension Calendar.RepeatedTimePolicy: Codable {
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1580,7 +1580,7 @@ extension Calendar {
return result
}

@available(FoundationPreview 0.4, *)
@available(macOS 15, iOS 18, tvOS 18, watchOS 11, *)
internal func dateAfterMatchingDayOfYear(startingAt: Date, components: DateComponents, direction: SearchDirection) throws -> Date? {
guard let dayOfYear = components.dayOfYear else {
// Nothing to do
Expand Down
2 changes: 1 addition & 1 deletion Sources/FoundationEssentials/Calendar/DateComponents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ public struct DateComponents : Hashable, Equatable, Sendable {
/// A day of the year.
/// For example, in the Gregorian calendar, can go from 1 to 365 or 1 to 366 in leap years.
/// - note: This value is interpreted in the context of the calendar in which it is used.
@available(FoundationPreview 0.4, *)
@available(macOS 15, iOS 18, tvOS 18, watchOS 11, *)
public var dayOfYear: Int? {
get { _dayOfYear }
set { _dayOfYear = converted(newValue) }
Expand Down
10 changes: 5 additions & 5 deletions Sources/FoundationEssentials/Calendar/RecurrenceRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

extension Calendar {
/// A rule which specifies how often an event should repeat in the future
@available(FoundationPreview 0.4, *)
@available(macOS 15, iOS 18, tvOS 18, watchOS 11, *)
public struct RecurrenceRule: Sendable, Equatable {
/// The calendar in which the recurrence occurs
public var calendar: Calendar
Expand Down Expand Up @@ -304,7 +304,7 @@ extension Calendar {
}
}

@available(FoundationPreview 0.4, *)
@available(macOS 15, iOS 18, tvOS 18, watchOS 11, *)
extension Calendar.RecurrenceRule.End: Codable {
enum CodingKeys: String, CodingKey {
case count
Expand Down Expand Up @@ -332,7 +332,7 @@ extension Calendar.RecurrenceRule.End: Codable {
}
}
}
@available(FoundationPreview 0.4, *)
@available(macOS 15, iOS 18, tvOS 18, watchOS 11, *)
extension Calendar.RecurrenceRule.Weekday: Codable {
enum CodingKeys: String, CodingKey {
case weekday
Expand All @@ -359,7 +359,7 @@ extension Calendar.RecurrenceRule.Weekday: Codable {
}
}
}
@available(FoundationPreview 0.4, *)
@available(macOS 15, iOS 18, tvOS 18, watchOS 11, *)
extension Calendar.RecurrenceRule.Month: Codable {
enum CodingKeys: String, CodingKey {
case month
Expand Down Expand Up @@ -388,7 +388,7 @@ extension Calendar.RecurrenceRule.Month: Codable {
}
}
}
@available(FoundationPreview 0.4, *)
@available(macOS 15, iOS 18, tvOS 18, watchOS 11, *)
extension Calendar.RecurrenceRule: Codable {
enum CodingKeys: String, CodingKey {
case calendar
Expand Down
2 changes: 1 addition & 1 deletion Sources/FoundationEssentials/ComparisonResult.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public enum ComparisonResult : Int, Sendable {

#endif // !FOUNDATION_FRAMEWORK

@available(FoundationPreview 0.1, *)
@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *)
extension ComparisonResult : Codable {
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
Expand Down
2 changes: 1 addition & 1 deletion Sources/FoundationEssentials/Data/Data.swift
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ internal final class __DataStorage : @unchecked Sendable {
}

#if FOUNDATION_FRAMEWORK
@available(FoundationPreview 0.1, *)
@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *)
#endif
@usableFromInline // This is not @inlinable as it is a non-trivial, non-generic function.
func replaceBytes(in range_: Range<Int>, with replacementBytes: UnsafeRawPointer?, length replacementLength: Int) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
/// - the formatted output for `xA` and higher is **most likely** different from `format(y)`
/// - the formatted output between `xB` and `zB`, as well as `zA` and `xA` (excluding bounds) cannot
/// be predicted
@available(FoundationPreview 0.4, *)
@available(macOS 15, iOS 18, tvOS 18, watchOS 11, *)
public protocol DiscreteFormatStyle<FormatInput, FormatOutput> : FormatStyle {
/// The next discretization boundary before the given input.
///
Expand Down Expand Up @@ -191,7 +191,7 @@ public protocol DiscreteFormatStyle<FormatInput, FormatOutput> : FormatStyle {
func input(after input: FormatInput) -> FormatInput?
}

@available(FoundationPreview 0.4, *)
@available(macOS 15, iOS 18, tvOS 18, watchOS 11, *)
extension DiscreteFormatStyle where FormatInput : FloatingPoint {
public func input(before input: FormatInput) -> FormatInput? {
guard input > -FormatInput.infinity else {
Expand All @@ -210,7 +210,7 @@ extension DiscreteFormatStyle where FormatInput : FloatingPoint {
}
}

@available(FoundationPreview 0.4, *)
@available(macOS 15, iOS 18, tvOS 18, watchOS 11, *)
extension DiscreteFormatStyle where FormatInput : FixedWidthInteger {
public func input(before input: FormatInput) -> FormatInput? {
guard input > FormatInput.min else {
Expand All @@ -229,7 +229,7 @@ extension DiscreteFormatStyle where FormatInput : FixedWidthInteger {
}
}

@available(FoundationPreview 0.4, *)
@available(macOS 15, iOS 18, tvOS 18, watchOS 11, *)
extension DiscreteFormatStyle where FormatInput == Date {
public func input(before input: FormatInput) -> FormatInput? {
guard input > Date.distantPast else {
Expand Down Expand Up @@ -258,7 +258,7 @@ extension Date {
}
}

@available(FoundationPreview 0.4, *)
@available(macOS 15, iOS 18, tvOS 18, watchOS 11, *)
extension DiscreteFormatStyle where FormatInput == Duration {
public func input(before input: FormatInput) -> FormatInput? {
guard input > .seconds(Int64.min) else {
Expand Down
4 changes: 2 additions & 2 deletions Sources/FoundationEssentials/JSON/JSONDecoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -346,14 +346,14 @@ open class JSONDecoder {
}, from: data)
}

@available(FoundationPreview 0.1, *)
@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *)
open func decode<T: DecodableWithConfiguration>(_ type: T.Type, from data: Data, configuration: T.DecodingConfiguration) throws -> T {
try _decode({
try $0.unwrap($1, as: type, configuration: configuration, for: .root, _CodingKey?.none)
}, from: data)
}

@available(FoundationPreview 0.1, *)
@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *)
open func decode<T, C>(_ type: T.Type, from data: Data, configuration: C.Type) throws -> T where T : DecodableWithConfiguration, C : DecodingConfigurationProviding, T.DecodingConfiguration == C.DecodingConfiguration {
try decode(type, from: data, configuration: C.decodingConfiguration)
}
Expand Down
Loading