Skip to content

Commit d3e3766

Browse files
committed
Use noncopyable State type for DateFormatter
1 parent 5cb2337 commit d3e3766

File tree

1 file changed

+58
-54
lines changed

1 file changed

+58
-54
lines changed

Diff for: Sources/Foundation/DateFormatter.swift

+58-54
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,13 @@ open class DateFormatter : Formatter, @unchecked Sendable {
1919
}
2020

2121
// Consumes state
22-
private convenience init(state: State) {
22+
private convenience init(state: consuming State) {
2323
self.init()
24-
nonisolated(unsafe) let consumedState = state
25-
_lock.withLock { $0 = consumedState }
24+
// work around issue that state needs to be reinitialized after consuming
25+
var tmp = Optional(state)
26+
_lock.withLock {
27+
$0 = tmp.take()!
28+
}
2629
}
2730

2831
open override func copy(with zone: NSZone? = nil) -> Any {
@@ -37,56 +40,57 @@ open class DateFormatter : Formatter, @unchecked Sendable {
3740
super.init(coder: coder)
3841
}
3942

40-
final class State {
41-
private var _formatter : CFDateFormatter? = nil
43+
struct State : ~Copyable {
44+
class Box {
45+
var formatter: CFDateFormatter?
46+
init() {}
47+
}
48+
49+
private var _formatter = Box()
4250

43-
func copy(with zone: NSZone? = nil) -> State {
44-
let copied = State()
45-
46-
func __copy<T>(_ keyPath: ReferenceWritableKeyPath<State, T>) {
47-
copied[keyPath: keyPath] = self[keyPath: keyPath]
48-
}
49-
50-
__copy(\.formattingContext)
51-
__copy(\.dateStyle)
52-
__copy(\.timeStyle)
53-
__copy(\._locale)
54-
__copy(\.generatesCalendarDates)
55-
__copy(\._timeZone)
56-
__copy(\._calendar)
57-
__copy(\.isLenient)
58-
__copy(\._twoDigitStartDate)
59-
__copy(\._eraSymbols)
60-
__copy(\._monthSymbols)
61-
__copy(\._shortMonthSymbols)
62-
__copy(\._weekdaySymbols)
63-
__copy(\._shortWeekdaySymbols)
64-
__copy(\._amSymbol)
65-
__copy(\._pmSymbol)
66-
__copy(\._longEraSymbols)
67-
__copy(\._veryShortMonthSymbols)
68-
__copy(\._standaloneMonthSymbols)
69-
__copy(\._shortStandaloneMonthSymbols)
70-
__copy(\._veryShortStandaloneMonthSymbols)
71-
__copy(\._veryShortWeekdaySymbols)
72-
__copy(\._standaloneWeekdaySymbols)
73-
__copy(\._shortStandaloneWeekdaySymbols)
74-
__copy(\._veryShortStandaloneWeekdaySymbols)
75-
__copy(\._quarterSymbols)
76-
__copy(\._shortQuarterSymbols)
77-
__copy(\._standaloneQuarterSymbols)
78-
__copy(\._shortStandaloneQuarterSymbols)
79-
__copy(\._gregorianStartDate)
80-
__copy(\.doesRelativeDateFormatting)
51+
func copy(with zone: NSZone? = nil) -> sending State {
52+
var copied = State()
53+
54+
copied.formattingContext = formattingContext
55+
copied.dateStyle = dateStyle
56+
copied.timeStyle = timeStyle
57+
copied._locale = _locale
58+
copied.generatesCalendarDates = generatesCalendarDates
59+
copied._timeZone = _timeZone
60+
copied._calendar = _calendar
61+
copied.isLenient = isLenient
62+
copied._twoDigitStartDate = _twoDigitStartDate
63+
copied._eraSymbols = _eraSymbols
64+
copied._monthSymbols = _monthSymbols
65+
copied._shortMonthSymbols = _shortMonthSymbols
66+
copied._weekdaySymbols = _weekdaySymbols
67+
copied._shortWeekdaySymbols = _shortWeekdaySymbols
68+
copied._amSymbol = _amSymbol
69+
copied._pmSymbol = _pmSymbol
70+
copied._longEraSymbols = _longEraSymbols
71+
copied._veryShortMonthSymbols = _veryShortMonthSymbols
72+
copied._standaloneMonthSymbols = _standaloneMonthSymbols
73+
copied._shortStandaloneMonthSymbols = _shortStandaloneMonthSymbols
74+
copied._veryShortStandaloneMonthSymbols = _veryShortStandaloneMonthSymbols
75+
copied._veryShortWeekdaySymbols = _veryShortWeekdaySymbols
76+
copied._standaloneWeekdaySymbols = _standaloneWeekdaySymbols
77+
copied._shortStandaloneWeekdaySymbols = _shortStandaloneWeekdaySymbols
78+
copied._veryShortStandaloneWeekdaySymbols = _veryShortStandaloneWeekdaySymbols
79+
copied._quarterSymbols = _quarterSymbols
80+
copied._shortQuarterSymbols = _shortQuarterSymbols
81+
copied._standaloneQuarterSymbols = _standaloneQuarterSymbols
82+
copied._shortStandaloneQuarterSymbols = _shortStandaloneQuarterSymbols
83+
copied._gregorianStartDate = _gregorianStartDate
84+
copied.doesRelativeDateFormatting = doesRelativeDateFormatting
8185

8286
// The last is `_dateFormat` because setting `dateStyle` and `timeStyle` make it `nil`.
83-
__copy(\._dateFormat)
87+
copied._dateFormat = _dateFormat
8488

8589
return copied
8690
}
8791

8892
func formatter() -> CFDateFormatter {
89-
guard let obj = _formatter else {
93+
guard let obj = _formatter.formatter else {
9094
let dateStyle = CFDateFormatterStyle(rawValue: CFIndex(dateStyle.rawValue))!
9195
let timeStyle = CFDateFormatterStyle(rawValue: CFIndex(timeStyle.rawValue))!
9296

@@ -95,14 +99,14 @@ open class DateFormatter : Formatter, @unchecked Sendable {
9599
if let dateFormat = _dateFormat {
96100
CFDateFormatterSetFormat(obj, dateFormat._cfObject)
97101
}
98-
_formatter = obj
102+
_formatter.formatter = obj
99103
return obj
100104
}
101105
return obj
102106
}
103107

104-
private func _reset() {
105-
_formatter = nil
108+
private mutating func _reset() {
109+
_formatter.formatter = nil
106110
}
107111

108112
// MARK: -
@@ -143,7 +147,7 @@ open class DateFormatter : Formatter, @unchecked Sendable {
143147
_setFormatterAttribute(formatter, attributeName: kCFDateFormatterGregorianStartDate, value: _gregorianStartDate?._cfObject)
144148
}
145149

146-
internal final func _setFormatterAttribute(_ formatter: CFDateFormatter, attributeName: CFString, value: AnyObject?) {
150+
internal func _setFormatterAttribute(_ formatter: CFDateFormatter, attributeName: CFString, value: AnyObject?) {
147151
if let value = value {
148152
CFDateFormatterSetProperty(formatter, attributeName, value)
149153
}
@@ -174,7 +178,7 @@ open class DateFormatter : Formatter, @unchecked Sendable {
174178
}
175179
}
176180

177-
/*@NSCopying*/ internal var _locale: Locale? { willSet { _reset() } }
181+
internal var _locale: Locale? { willSet { _reset() } }
178182
var locale: Locale! {
179183
get {
180184
guard let locale = _locale else { return .current }
@@ -187,7 +191,7 @@ open class DateFormatter : Formatter, @unchecked Sendable {
187191

188192
var generatesCalendarDates = false { willSet { _reset() } }
189193

190-
/*@NSCopying*/ internal var _timeZone: TimeZone? { willSet { _reset() } }
194+
internal var _timeZone: TimeZone? { willSet { _reset() } }
191195
var timeZone: TimeZone! {
192196
get {
193197
guard let tz = _timeZone else {
@@ -203,7 +207,7 @@ open class DateFormatter : Formatter, @unchecked Sendable {
203207
}
204208
}
205209

206-
/*@NSCopying*/ internal var _calendar: Calendar! { willSet { _reset() } }
210+
internal var _calendar: Calendar! { willSet { _reset() } }
207211
var calendar: Calendar! {
208212
get {
209213
guard let calendar = _calendar else {
@@ -221,7 +225,7 @@ open class DateFormatter : Formatter, @unchecked Sendable {
221225

222226
var isLenient = false { willSet { _reset() } }
223227

224-
/*@NSCopying*/ internal var _twoDigitStartDate: Date? { willSet { _reset() } }
228+
internal var _twoDigitStartDate: Date? { willSet { _reset() } }
225229
var twoDigitStartDate: Date? {
226230
get {
227231
guard let startDate = _twoDigitStartDate else {
@@ -234,7 +238,7 @@ open class DateFormatter : Formatter, @unchecked Sendable {
234238
}
235239
}
236240

237-
/*@NSCopying*/ var defaultDate: Date? { willSet { _reset() } }
241+
var defaultDate: Date? { willSet { _reset() } }
238242

239243
internal var _eraSymbols: [String]? { willSet { _reset() } }
240244
var eraSymbols: [String] {

0 commit comments

Comments
 (0)