Skip to content

Commit e9406cb

Browse files
authored
Merge pull request #772 from parkera/parkera/rel_60_merge
[6.0] Final merge of main to release/6.0
2 parents c0a485e + 0086133 commit e9406cb

37 files changed

+1138
-242
lines changed

CMakeLists.txt

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -69,20 +69,40 @@ FetchContent_MakeAvailable(SwiftFoundationICU SwiftCollections)
6969
list(APPEND CMAKE_MODULE_PATH ${SwiftFoundation_SOURCE_DIR}/cmake/modules)
7070

7171
# Availability Macros (only applies to FoundationEssentials and FoundationInternationalization)
72-
set(_SwiftFoundation_availability_macros)
73-
list(APPEND _SwiftFoundation_availability_macros
74-
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -enable-experimental-feature -Xfrontend \"AvailabilityMacro=FoundationPreview 0.1:macOS 13.3, iOS 16.4, tvOS 16.4, watchOS 9.4\">"
75-
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -enable-experimental-feature -Xfrontend \"AvailabilityMacro=FoundationPreview 0.2:macOS 13.3, iOS 16.4, tvOS 16.4, watchOS 9.4\">"
76-
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -enable-experimental-feature -Xfrontend \"AvailabilityMacro=FoundationPreview 0.3:macOS 13.3, iOS 16.4, tvOS 16.4, watchOS 9.4\">"
77-
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -enable-experimental-feature -Xfrontend \"AvailabilityMacro=FoundationPreview 0.4:macOS 13.3, iOS 16.4, tvOS 16.4, watchOS 9.4\">"
78-
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -enable-experimental-feature -Xfrontend \"AvailabilityMacro=FoundationPredicate 0.1:macOS 14, iOS 17, tvOS 17, watchOS 10\">"
79-
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -enable-experimental-feature -Xfrontend \"AvailabilityMacro=FoundationPredicate 0.2:macOS 14, iOS 17, tvOS 17, watchOS 10\">"
80-
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -enable-experimental-feature -Xfrontend \"AvailabilityMacro=FoundationPredicate 0.3:macOS 14, iOS 17, tvOS 17, watchOS 10\">"
81-
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -enable-experimental-feature -Xfrontend \"AvailabilityMacro=FoundationPredicate 0.4:macOS 14, iOS 17, tvOS 17, watchOS 10\">"
82-
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -enable-experimental-feature -Xfrontend \"AvailabilityMacro=FoundationPredicateRegex 0.1:macOS 10000, iOS 10000, tvOS 10000, watchOS 10000\">"
83-
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -enable-experimental-feature -Xfrontend \"AvailabilityMacro=FoundationPredicateRegex 0.2:macOS 10000, iOS 10000, tvOS 10000, watchOS 10000\">"
84-
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -enable-experimental-feature -Xfrontend \"AvailabilityMacro=FoundationPredicateRegex 0.3:macOS 10000, iOS 10000, tvOS 10000, watchOS 10000\">"
85-
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -enable-experimental-feature -Xfrontend \"AvailabilityMacro=FoundationPredicateRegex 0.4:macOS 10000, iOS 10000, tvOS 10000, watchOS 10000\">")
72+
set(_SwiftFoundation_BaseAvailability "macOS 13.3, iOS 16.4, tvOS 16.4, watchOS 9.4")
73+
set(_SwiftFoundation_macOS14Availability "macOS 14, iOS 17, tvOS 17, watchOS 10")
74+
set(_SwiftFoundation_macOS15Availability "macOS 15, iOS 18, tvOS 18, watchOS 11")
75+
set(_SwiftFoundation_FutureAvailability "macOS 10000, iOS 10000, tvOS 10000, watchOS 10000")
76+
77+
# All versions to define for each availability name
78+
list(APPEND _SwiftFoundation_versions
79+
"0.1"
80+
"0.2"
81+
"0.3"
82+
"0.4")
83+
84+
# Each availability name to define
85+
list(APPEND _SwiftFoundation_availability_names
86+
"FoundationPreview"
87+
"FoundationPredicate"
88+
"FoundationPredicateRegex")
89+
90+
# The aligned availability for each name (in the same order)
91+
list(APPEND _SwiftFoundation_availability_releases
92+
${_SwiftFoundation_BaseAvailability}
93+
${_SwiftFoundation_macOS14Availability}
94+
${_SwiftFoundation_macOS15Availability})
95+
96+
foreach(version ${_SwiftFoundation_versions})
97+
foreach(name release IN ZIP_LISTS _SwiftFoundation_availability_names _SwiftFoundation_availability_releases)
98+
if(NOT DEFINED name OR NOT DEFINED release)
99+
message(FATAL_ERROR "_SwiftFoundation_availability_names and _SwiftFoundation_availability_releases are not the same length")
100+
endif()
101+
102+
list(APPEND _SwiftFoundation_availability_macros
103+
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -enable-experimental-feature -Xfrontend \"AvailabilityMacro=${name} ${version}:${release}\">")
104+
endforeach()
105+
endforeach()
86106

87107
include(GNUInstallDirs)
88108
include(SwiftFoundationSwiftSupport)

Package.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import CompilerPluginSupport
99
let availabilityTags: [_Availability] = [
1010
_Availability("FoundationPreview"), // Default FoundationPreview availability,
1111
_Availability("FoundationPredicate", availability: .macOS14_0), // Predicate relies on pack parameter runtime support
12-
_Availability("FoundationPredicateRegex", availability: .future) // Predicate regexes rely on new stdlib APIs
12+
_Availability("FoundationPredicateRegex", availability: .macOS15_0) // Predicate regexes rely on new stdlib APIs
1313
]
1414
let versionNumbers = ["0.1", "0.2", "0.3", "0.4"]
1515

@@ -18,6 +18,7 @@ let versionNumbers = ["0.1", "0.2", "0.3", "0.4"]
1818
enum _OSAvailability: String {
1919
case alwaysAvailable = "macOS 13.3, iOS 16.4, tvOS 16.4, watchOS 9.4" // This should match the package's deployment target
2020
case macOS14_0 = "macOS 14, iOS 17, tvOS 17, watchOS 10"
21+
case macOS15_0 = "macOS 15, iOS 18, tvOS 18, watchOS 11"
2122
// Use 10000 for future availability to avoid compiler magic around the 9999 version number but ensure it is greater than 9999
2223
case future = "macOS 10000, iOS 10000, tvOS 10000, watchOS 10000"
2324
}

Sources/FoundationEssentials/CMakeLists.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,13 @@ if(NOT BUILD_SHARED_LIBS)
7777
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -public-autolink-library -Xfrontend _FoundationCShims>")
7878
target_compile_options(FoundationEssentials PRIVATE
7979
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -public-autolink-library -Xfrontend _FoundationCollections>")
80+
target_compile_options(FoundationEssentials PRIVATE
81+
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -public-autolink-library -Xfrontend swiftSynchronization>")
8082
endif()
8183

82-
target_link_options(FoundationEssentials PRIVATE
83-
"SHELL:-no-toolchain-stdlib-rpath")
84-
8584
set_target_properties(FoundationEssentials PROPERTIES
86-
INSTALL_RPATH "$ORIGIN")
85+
INSTALL_RPATH "$ORIGIN"
86+
INSTALL_REMOVE_ENVIRONMENT_RPATH ON)
8787

8888
set_property(GLOBAL APPEND PROPERTY SWIFT_FOUNDATION_EXPORTS FoundationEssentials)
8989
_swift_foundation_install_target(FoundationEssentials)

Sources/FoundationEssentials/Calendar/Calendar_Cache.swift

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,30 +15,26 @@ internal import _ForSwiftFoundation
1515
import CoreFoundation
1616
#endif
1717

18-
/// Singleton which listens for notifications about preference changes for Calendar and holds cached singletons for the current locale, calendar, and time zone.
19-
struct CalendarCache : Sendable {
20-
21-
// MARK: - Concrete Classes
22-
23-
// _CalendarICU, if present
24-
static func calendarICUClass(identifier: Calendar.Identifier, useGregorian: Bool) -> _CalendarProtocol.Type? {
2518
#if FOUNDATION_FRAMEWORK && canImport(_FoundationICU)
26-
if useGregorian && identifier == .gregorian {
27-
return _CalendarGregorian.self
28-
} else {
29-
return _CalendarICU.self
30-
}
19+
internal func _calendarICUClass() -> _CalendarProtocol.Type? {
20+
_CalendarICU.self
21+
}
3122
#else
32-
if useGregorian && identifier == .gregorian {
33-
return _CalendarGregorian.self
34-
} else if let name = _typeByName("FoundationInternationalization._CalendarICU"), let t = name as? _CalendarProtocol.Type {
35-
return t
36-
} else {
37-
return nil
38-
}
23+
dynamic package func _calendarICUClass() -> _CalendarProtocol.Type? {
24+
nil
25+
}
3926
#endif
27+
28+
func _calendarClass(identifier: Calendar.Identifier, useGregorian: Bool) -> _CalendarProtocol.Type? {
29+
if useGregorian && identifier == .gregorian {
30+
return _CalendarGregorian.self
31+
} else {
32+
return _calendarICUClass()
4033
}
34+
}
4135

36+
/// Singleton which listens for notifications about preference changes for Calendar and holds cached singletons for the current locale, calendar, and time zone.
37+
struct CalendarCache : Sendable {
4238
// MARK: - State
4339

4440
struct State : Sendable {
@@ -78,7 +74,7 @@ struct CalendarCache : Sendable {
7874
} else {
7975
let id = Locale.current._calendarIdentifier
8076
// If we cannot create the right kind of class, we fail immediately here
81-
let calendarClass = CalendarCache.calendarICUClass(identifier: id, useGregorian: true)!
77+
let calendarClass = _calendarClass(identifier: id, useGregorian: true)!
8278
let calendar = calendarClass.init(identifier: id, timeZone: nil, locale: Locale.current, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil)
8379
currentCalendar = calendar
8480
return calendar
@@ -101,7 +97,7 @@ struct CalendarCache : Sendable {
10197
return cached
10298
} else {
10399
// If we cannot create the right kind of class, we fail immediately here
104-
let calendarClass = CalendarCache.calendarICUClass(identifier: id, useGregorian: true)!
100+
let calendarClass = _calendarClass(identifier: id, useGregorian: true)!
105101
let new = calendarClass.init(identifier: id, timeZone: nil, locale: nil, firstWeekday: nil, minimumDaysInFirstWeek: nil, gregorianStartDate: nil)
106102
fixedCalendars[id] = new
107103
return new
@@ -140,7 +136,7 @@ struct CalendarCache : Sendable {
140136
func fixed(identifier: Calendar.Identifier, locale: Locale?, timeZone: TimeZone?, firstWeekday: Int?, minimumDaysInFirstWeek: Int?, gregorianStartDate: Date?) -> any _CalendarProtocol {
141137
// Note: Only the ObjC NSCalendar initWithCoder supports gregorian start date values. For Swift it is always nil.
142138
// If we cannot create the right kind of class, we fail immediately here
143-
let calendarClass = CalendarCache.calendarICUClass(identifier: identifier, useGregorian: true)!
139+
let calendarClass = _calendarClass(identifier: identifier, useGregorian: true)!
144140
return calendarClass.init(identifier: identifier, timeZone: timeZone, locale: locale, firstWeekday: firstWeekday, minimumDaysInFirstWeek: minimumDaysInFirstWeek, gregorianStartDate: gregorianStartDate)
145141
}
146142

Sources/FoundationEssentials/Calendar/Calendar_Gregorian.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -134,19 +134,19 @@ enum ResolvedDateComponents {
134134
adjustedYear = year
135135
}
136136
self = .day(year: adjustedYear, month: month, day: d, weekOfYear: components.weekOfYear)
137+
} else if let weekdayOrdinal = components.weekdayOrdinal, let weekday = components.weekday {
138+
self = .weekdayOrdinal(year: year, month: month, weekdayOrdinal: weekdayOrdinal, weekday: weekday)
137139
} else if let woy = components.weekOfYear, let weekday = components.weekday {
138140
self = .weekOfYear(year: year, weekOfYear: woy, weekday: weekday)
139141
} else if let wom = components.weekOfMonth, let weekday = components.weekday {
140142
self = .weekOfMonth(year: year, month: month, weekOfMonth: wom, weekday: weekday)
141-
} else if let weekdayOrdinal = components.weekdayOrdinal, let weekday = components.weekday {
142-
self = .weekdayOrdinal(year: year, month: month, weekdayOrdinal: weekdayOrdinal, weekday: weekday)
143143
} else if let dayOfYear = components.dayOfYear {
144144
self = .dayOfYear(year: year, dayOfYear: dayOfYear)
145-
} else if components.year != nil {
146-
self = .day(year: year, month: month, day: components.day, weekOfYear: components.weekOfYear)
147145
} else if components.yearForWeekOfYear != nil {
148146
self = .weekOfYear(year: year, weekOfYear: components.weekOfYear, weekday: components.weekday)
149-
} else if let weekOfYear = components.weekOfYear {
147+
} else if components.year != nil {
148+
self = .day(year: year, month: month, day: components.day, weekOfYear: components.weekOfYear)
149+
} else if let weekOfYear = components.weekOfYear {
150150
self = .weekOfYear(year: year, weekOfYear: weekOfYear, weekday: components.weekday)
151151
} else if let weekOfMonth = components.weekOfMonth {
152152
self = .weekOfMonth(year: year, month: month, weekOfMonth: weekOfMonth, weekday: components.weekday)

Sources/FoundationEssentials/Decimal/Decimal+Compatibility.swift

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -409,8 +409,24 @@ public func _NSDecimalCompact(_ number: UnsafeMutablePointer<Decimal>) {
409409
_ decimal: UnsafePointer<Decimal>,
410410
_ locale: Any? = nil
411411
) -> String {
412-
let useLocale = locale as? Locale
413-
return decimal.pointee._toString(with: useLocale)
412+
var decimalSeparator = "."
413+
if let useLocale = locale as? Locale,
414+
let separator = useLocale.decimalSeparator {
415+
decimalSeparator = separator
416+
}
417+
#if FOUNDATION_FRAMEWORK
418+
if let dictionary = locale as? [AnyHashable : Any] {
419+
// NSDecimal favored NSLocale.Key.decimalSeparator if
420+
// both keys are present.
421+
if let separator = dictionary["NSDecimalSeparator"] as? String {
422+
decimalSeparator = separator
423+
}
424+
if let separator = dictionary[NSLocale.Key.decimalSeparator.rawValue] as? String {
425+
decimalSeparator = separator
426+
}
427+
}
428+
#endif
429+
return decimal.pointee._toString(withDecimalSeparator: decimalSeparator)
414430
}
415431

416432
#if FOUNDATION_FRAMEWORK
@@ -435,7 +451,7 @@ internal func __NSStringToDecimal(
435451
from: string.utf8,
436452
decimalSeparator: ".".utf8,
437453
matchEntireString: false
438-
)
454+
).asOptional
439455
processedLength.pointee = parsed.processedLength
440456
if let parsedResult = parsed.result {
441457
result.pointee = parsedResult

Sources/FoundationEssentials/Decimal/Decimal+Conformances.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,18 @@ internal import _ForSwiftFoundation
1818
extension Decimal : CustomStringConvertible {
1919
public init?(string: __shared String, locale: __shared Locale? = nil) {
2020
let decimalSeparator = locale?.decimalSeparator ?? "."
21-
guard let value = Decimal._decimal(
21+
guard case let .success(value, _) = Decimal._decimal(
2222
from: string.utf8,
2323
decimalSeparator: decimalSeparator.utf8,
2424
matchEntireString: false
25-
).result else {
25+
) else {
2626
return nil
2727
}
2828
self = value
2929
}
3030

3131
public var description: String {
32-
return self._toString()
32+
return self._toString(withDecimalSeparator: ".")
3333
}
3434
}
3535

0 commit comments

Comments
 (0)