Skip to content

Commit b76985d

Browse files
authored
Merge branch 'swiftlang:main' into implementation/progress-manager
2 parents 28c44d7 + 574d608 commit b76985d

File tree

8 files changed

+196
-59
lines changed

8 files changed

+196
-59
lines changed

Proposals/0023-progress-reporter.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ overall.assign(count: 3, to: examCountdown.progressReporter)
347347

348348
// Add `ProgressReporter` to another parent `ProgressManager` with different assigned count
349349
let deadlineTracker = ProgressManager(totalCount: 2)
350-
overall.assign(count: 1, to: examCountdown, progressReporter)
350+
deadlineTracker.assign(count: 1, to: examCountdown.progressReporter)
351351
```
352352

353353
### Reporting Progress With Type-Safe Custom Properties

Sources/FoundationEssentials/AttributedString/AttributeScope.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ internal func _loadDefaultAttributes() -> [String : any AttributedStringKey.Type
131131
// UIKit on macOS
132132
let macUIScope = (
133133
"$s10Foundation15AttributeScopesO5UIKitE0D10AttributesVN",
134-
"/System/iOSSupport/System/Library/Frameworks/UIKit.framework/UIKit"
134+
"/System/iOSSupport/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore"
135135
)
136136
#endif
137137

@@ -142,12 +142,12 @@ internal func _loadDefaultAttributes() -> [String : any AttributedStringKey.Type
142142
// UIKit
143143
(
144144
"$s10Foundation15AttributeScopesO5UIKitE0D10AttributesVN",
145-
"/System/Library/Frameworks/UIKit.framework/UIKit"
145+
"/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore"
146146
),
147147
// SwiftUI
148148
(
149149
"$s10Foundation15AttributeScopesO7SwiftUIE0D12UIAttributesVN",
150-
"/System/Library/Frameworks/SwiftUI.framework/SwiftUI"
150+
"/System/Library/Frameworks/SwiftUICore.framework/SwiftUICore"
151151
),
152152
// Accessibility
153153
(

Sources/FoundationEssentials/Data/Data+Writing.swift

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,37 @@ private func createTemporaryFile(at destinationPath: String, inPath: PathOrURL,
157157

158158
let pidString = String(ProcessInfo.processInfo.processIdentifier, radix: 16, uppercase: true)
159159
let template = directoryPath + prefix + pidString + ".XXXXXX"
160-
var count = 0
161160
let maxCount = 7
162-
repeat {
161+
for _ in 0 ..< maxCount {
162+
#if FOUNDATION_FRAMEWORK
163+
let (sandboxResult, amkrErrno) = inPath.withFileSystemRepresentation { inPathFileSystemRep -> ((Int32, String)?, Int32?) in
164+
guard let inPathFileSystemRep else {
165+
return (nil, nil)
166+
}
167+
// First, try _amkrtemp to carry over any sandbox extensions for inPath to the temporary file (even if the application isn't sandboxed)
168+
guard let uniqueTempFile = _amkrtemp(inPathFileSystemRep) else {
169+
return (nil, errno)
170+
}
171+
defer { free(uniqueTempFile) }
172+
let fd = openFileDescriptorProtected(path: uniqueTempFile, flags: O_CREAT | O_EXCL | O_RDWR, options: options)
173+
if fd >= 0 {
174+
// Got a good fd
175+
return ((fd, String(cString: uniqueTempFile)), nil)
176+
}
177+
return (nil, errno)
178+
}
179+
180+
// If _amkrtemp succeeded, return its result
181+
if let sandboxResult {
182+
return sandboxResult
183+
}
184+
// If _amkrtemp failed with EEXIST, just retry
185+
if amkrErrno == EEXIST {
186+
continue
187+
}
188+
// Otherwise, fall through to mktemp below
189+
#endif
190+
163191
let result = try template.withMutableFileSystemRepresentation { templateFileSystemRep -> (Int32, String)? in
164192
guard let templateFileSystemRep else {
165193
throw CocoaError(.fileWriteInvalidFileName)
@@ -187,7 +215,12 @@ private func createTemporaryFile(at destinationPath: String, inPath: PathOrURL,
187215

188216
// If the file exists, we repeat. Otherwise throw the error.
189217
if errno != EEXIST {
190-
throw CocoaError.errorWithFilePath(inPath, errno: errno, reading: false, variant: variant)
218+
#if FOUNDATION_FRAMEWORK
219+
let debugDescription = "Creating a temporary file via mktemp failed. Creating the temporary file via _amkrtemp previously also failed with errno \(amkrErrno)"
220+
#else
221+
let debugDescription: String? = nil
222+
#endif
223+
throw CocoaError.errorWithFilePath(inPath, errno: errno, reading: false, variant: variant, debugDescription: debugDescription)
191224
}
192225

193226
// Try again
@@ -196,14 +229,10 @@ private func createTemporaryFile(at destinationPath: String, inPath: PathOrURL,
196229

197230
if let result {
198231
return result
199-
} else {
200-
count += 1
201-
if count > maxCount {
202-
// Prevent an infinite loop; even if the error is obscure
203-
throw CocoaError(.fileWriteUnknown)
204-
}
205232
}
206-
} while true
233+
}
234+
// We hit max count, prevent an infinite loop; even if the error is obscure
235+
throw CocoaError(.fileWriteUnknown)
207236
#endif // os(WASI)
208237
}
209238

Sources/FoundationEssentials/Decimal/Decimal+Compatibility.swift

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,23 +80,13 @@ extension Decimal : _ObjectiveCBridgeable {
8080
// MARK: - Bridging code to C functions
8181
// We have one implementation function for each, and an entry point for both Darwin (cdecl, exported from the framework), and swift-corelibs-foundation (SPI here and available via that package as API)
8282

83-
#if FOUNDATION_FRAMEWORK
8483
@available(macOS 10.10, iOS 8.0, watchOS 2.0, tvOS 9.0, *)
8584
public func pow(_ x: Decimal, _ y: Int) -> Decimal {
8685
let result = try? x._power(
8786
exponent: y, roundingMode: .plain
8887
)
8988
return result ?? .nan
9089
}
91-
#else
92-
@_spi(SwiftCorelibsFoundation)
93-
public func _pow(_ x: Decimal, _ y: Int) -> Decimal {
94-
let result = try? x._power(
95-
exponent: y, roundingMode: .plain
96-
)
97-
return result ?? .nan
98-
}
99-
#endif
10090

10191
private func __NSDecimalAdd(
10292
_ result: UnsafeMutablePointer<Decimal>,

Sources/FoundationEssentials/Error/CocoaError+FilePath.swift

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ import WinSDK
3131
// MARK: - Error Creation with CocoaError.Code
3232

3333
extension CocoaError {
34-
static func errorWithFilePath(_ code: CocoaError.Code, _ path: String, variant: String? = nil, source: String? = nil, destination: String? = nil) -> CocoaError {
35-
CocoaError(code, path: path, variant: variant, source: source, destination: destination)
34+
static func errorWithFilePath(_ code: CocoaError.Code, _ path: String, variant: String? = nil, source: String? = nil, destination: String? = nil, debugDescription: String? = nil) -> CocoaError {
35+
CocoaError(code, path: path, variant: variant, source: source, destination: destination, debugDescription: debugDescription)
3636
}
3737

38-
static func errorWithFilePath(_ code: CocoaError.Code, _ url: URL, variant: String? = nil, source: String? = nil, destination: String? = nil) -> CocoaError {
39-
CocoaError(code, url: url, variant: variant, source: source, destination: destination)
38+
static func errorWithFilePath(_ code: CocoaError.Code, _ url: URL, variant: String? = nil, source: String? = nil, destination: String? = nil, debugDescription: String? = nil) -> CocoaError {
39+
CocoaError(code, url: url, variant: variant, source: source, destination: destination, debugDescription: debugDescription)
4040
}
4141
}
4242

@@ -81,21 +81,21 @@ extension POSIXError {
8181
}
8282

8383
extension CocoaError {
84-
static func errorWithFilePath(_ pathOrURL: PathOrURL, errno: Int32, reading: Bool, variant: String? = nil, source: String? = nil, destination: String? = nil) -> CocoaError {
84+
static func errorWithFilePath(_ pathOrURL: PathOrURL, errno: Int32, reading: Bool, variant: String? = nil, source: String? = nil, destination: String? = nil, debugDescription: String? = nil) -> CocoaError {
8585
switch pathOrURL {
8686
case .path(let path):
87-
return Self.errorWithFilePath(path, errno: errno, reading: reading, variant: variant, source: source, destination: destination)
87+
return Self.errorWithFilePath(path, errno: errno, reading: reading, variant: variant, source: source, destination: destination, debugDescription: debugDescription)
8888
case .url(let url):
89-
return Self.errorWithFilePath(url, errno: errno, reading: reading, variant: variant, source: source, destination: destination)
89+
return Self.errorWithFilePath(url, errno: errno, reading: reading, variant: variant, source: source, destination: destination, debugDescription: debugDescription)
9090
}
9191
}
9292

93-
static func errorWithFilePath(_ path: String, errno: Int32, reading: Bool, variant: String? = nil, source: String? = nil, destination: String? = nil) -> CocoaError {
94-
CocoaError(Code(fileErrno: errno, reading: reading), path: path, underlying: POSIXError(errno: errno), variant: variant, source: source, destination: destination)
93+
static func errorWithFilePath(_ path: String, errno: Int32, reading: Bool, variant: String? = nil, source: String? = nil, destination: String? = nil, debugDescription: String? = nil) -> CocoaError {
94+
CocoaError(Code(fileErrno: errno, reading: reading), path: path, underlying: POSIXError(errno: errno), variant: variant, source: source, destination: destination, debugDescription: debugDescription)
9595
}
9696

97-
static func errorWithFilePath(_ url: URL, errno: Int32, reading: Bool, variant: String? = nil, source: String? = nil, destination: String? = nil) -> CocoaError {
98-
CocoaError(Code(fileErrno: errno, reading: reading), url: url, underlying: POSIXError(errno: errno), variant: variant, source: source, destination: destination)
97+
static func errorWithFilePath(_ url: URL, errno: Int32, reading: Bool, variant: String? = nil, source: String? = nil, destination: String? = nil, debugDescription: String? = nil) -> CocoaError {
98+
CocoaError(Code(fileErrno: errno, reading: reading), url: url, underlying: POSIXError(errno: errno), variant: variant, source: source, destination: destination, debugDescription: debugDescription)
9999
}
100100
}
101101

@@ -144,18 +144,18 @@ extension CocoaError.Code {
144144
}
145145

146146
extension CocoaError {
147-
static func errorWithFilePath(_ path: PathOrURL, win32 dwError: DWORD, reading: Bool) -> CocoaError {
147+
static func errorWithFilePath(_ path: PathOrURL, win32 dwError: DWORD, reading: Bool, debugDescription: String? = nil) -> CocoaError {
148148
switch path {
149149
case let .path(path):
150-
return CocoaError(.init(win32: dwError, reading: reading, emptyPath: path.isEmpty), path: path, underlying: Win32Error(dwError))
150+
return CocoaError(.init(win32: dwError, reading: reading, emptyPath: path.isEmpty), path: path, underlying: Win32Error(dwError), debugDescription: debugDescription)
151151
case let .url(url):
152152
let pathStr = url.withUnsafeFileSystemRepresentation { String(cString: $0!) }
153-
return CocoaError(.init(win32: dwError, reading: reading, emptyPath: pathStr.isEmpty), path: pathStr, url: url, underlying: Win32Error(dwError))
153+
return CocoaError(.init(win32: dwError, reading: reading, emptyPath: pathStr.isEmpty), path: pathStr, url: url, underlying: Win32Error(dwError), debugDescription: debugDescription)
154154
}
155155
}
156156

157-
static func errorWithFilePath(_ path: String? = nil, win32 dwError: DWORD, reading: Bool, variant: String? = nil, source: String? = nil, destination: String? = nil) -> CocoaError {
158-
return CocoaError(.init(win32: dwError, reading: reading, emptyPath: path?.isEmpty), path: path, underlying: Win32Error(dwError), variant: variant, source: source, destination: destination)
157+
static func errorWithFilePath(_ path: String? = nil, win32 dwError: DWORD, reading: Bool, variant: String? = nil, source: String? = nil, destination: String? = nil, debugDescription: String? = nil) -> CocoaError {
158+
return CocoaError(.init(win32: dwError, reading: reading, emptyPath: path?.isEmpty), path: path, underlying: Win32Error(dwError), variant: variant, source: source, destination: destination, debugDescription: debugDescription)
159159
}
160160
}
161161
#endif
@@ -190,7 +190,8 @@ extension CocoaError {
190190
underlying: (some Error)? = Optional<CocoaError>.none,
191191
variant: String? = nil,
192192
source: String? = nil,
193-
destination: String? = nil
193+
destination: String? = nil,
194+
debugDescription: String? = nil
194195
) {
195196
self.init(
196197
code,
@@ -199,7 +200,8 @@ extension CocoaError {
199200
underlying: underlying,
200201
variant: variant,
201202
source: source,
202-
destination: destination
203+
destination: destination,
204+
debugDescription: debugDescription
203205
)
204206
}
205207

@@ -209,7 +211,8 @@ extension CocoaError {
209211
underlying: (some Error)? = Optional<CocoaError>.none,
210212
variant: String? = nil,
211213
source: String? = nil,
212-
destination: String? = nil
214+
destination: String? = nil,
215+
debugDescription: String? = nil
213216
) {
214217
self.init(
215218
code,
@@ -218,7 +221,8 @@ extension CocoaError {
218221
underlying: underlying,
219222
variant: variant,
220223
source: source,
221-
destination: destination
224+
destination: destination,
225+
debugDescription: debugDescription
222226
)
223227
}
224228

@@ -229,10 +233,11 @@ extension CocoaError {
229233
underlying: (some Error)? = Optional<CocoaError>.none,
230234
variant: String? = nil,
231235
source: String? = nil,
232-
destination: String? = nil
236+
destination: String? = nil,
237+
debugDescription: String? = nil
233238
) {
234239
#if FOUNDATION_FRAMEWORK
235-
self.init(_uncheckedNSError: NSError._cocoaError(withCode: code.rawValue, path: path, url: url, underlying: underlying, variant: variant, source: source, destination: destination) as NSError)
240+
self.init(_uncheckedNSError: NSError._cocoaError(withCode: code.rawValue, path: path, url: url, underlying: underlying, variant: variant, source: source, destination: destination, debugDescription: debugDescription) as NSError)
236241
#else
237242
var userInfo: [String : Any] = [:]
238243
if let path {
@@ -253,6 +258,9 @@ extension CocoaError {
253258
if let variant {
254259
userInfo[NSUserStringVariantErrorKey] = [variant]
255260
}
261+
if let debugDescription {
262+
userInfo[NSDebugDescriptionErrorKey] = debugDescription
263+
}
256264

257265
self.init(code, userInfo: userInfo)
258266
#endif

Sources/FoundationEssentials/NotificationCenter/AsyncMessage+AsyncSequence.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ extension NotificationCenter {
3434
of subject: Message.Subject,
3535
for identifier: Identifier,
3636
bufferSize limit: Int = 10
37-
) -> some AsyncSequence<Message, Never> where Identifier.MessageType == Message, Message.Subject: AnyObject {
37+
) -> some AsyncSequence<Message, Never> & Sendable where Identifier.MessageType == Message, Message.Subject: AnyObject {
3838
return AsyncMessageSequence<Message>(self, subject, limit)
3939
}
4040

@@ -48,7 +48,7 @@ extension NotificationCenter {
4848
of subject: Message.Subject.Type,
4949
for identifier: Identifier,
5050
bufferSize limit: Int = 10
51-
) -> some AsyncSequence<Message, Never> where Identifier.MessageType == Message {
51+
) -> some AsyncSequence<Message, Never> & Sendable where Identifier.MessageType == Message {
5252
return AsyncMessageSequence<Message>(self, nil, limit)
5353
}
5454

@@ -62,7 +62,7 @@ extension NotificationCenter {
6262
of subject: Message.Subject? = nil,
6363
for messageType: Message.Type,
6464
bufferSize limit: Int = 10
65-
) -> some AsyncSequence<Message, Never> where Message.Subject: AnyObject {
65+
) -> some AsyncSequence<Message, Never> & Sendable where Message.Subject: AnyObject {
6666
return AsyncMessageSequence<Message>(self, subject, limit)
6767
}
6868
}

Sources/FoundationEssentials/Predicate/KeyPath+Inspection.swift

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ extension UInt32 {
1919
private static var COMPUTED_COMPONENT_PAYLOAD_ARGUMENTS_MASK: UInt32 { 0x0008_0000 }
2020
private static var COMPUTED_COMPONENT_PAYLOAD_SETTABLE_MASK: UInt32 { 0x0040_0000 }
2121

22+
private static var STORED_COMPONENT_PAYLOAD_MAXIMUM_INLINE_OFFSET: UInt32 { 0x007F_FFFC }
23+
2224
fileprivate var _keyPathHeader_bufferSize: Int {
2325
Int(self & Self.KEYPATH_HEADER_BUFFER_SIZE_MASK)
2426
}
@@ -31,6 +33,11 @@ extension UInt32 {
3133
self & Self.COMPONENT_HEADER_PAYLOAD_MASK
3234
}
3335

36+
fileprivate var _keyPathComponentHeader_storedIsInline: Bool {
37+
// If the payload value is greater than the maximum inline offset then it is one of the out-of-line sentinel values
38+
_keyPathComponentHeader_payload <= Self.STORED_COMPONENT_PAYLOAD_MAXIMUM_INLINE_OFFSET
39+
}
40+
3441
fileprivate var _keyPathComponentHeader_computedHasArguments: Bool {
3542
(_keyPathComponentHeader_payload & Self.COMPUTED_COMPONENT_PAYLOAD_ARGUMENTS_MASK) != 0
3643
}
@@ -40,14 +47,10 @@ extension UInt32 {
4047
}
4148
}
4249

43-
private func _keyPathOffset<T>(_ root: T.Type, _ keyPath: AnyKeyPath) -> Int? {
44-
MemoryLayout<T>.offset(of: keyPath as! PartialKeyPath<T>)
45-
}
46-
4750
extension AnyKeyPath {
4851
private static var WORD_SIZE: Int { MemoryLayout<Int>.size }
4952

50-
func _validateForPredicateUsage(restrictArguments: Bool = false) {
53+
func _validateForPredicateUsage(restrictArguments: Bool = true) {
5154
var ptr = unsafeBitCast(self, to: UnsafeRawPointer.self)
5255
ptr = ptr.advanced(by: Self.WORD_SIZE * 3) // skip isa, type metadata, and KVC string pointers
5356
let header = ptr.load(as: UInt32.self)
@@ -57,11 +60,10 @@ extension AnyKeyPath {
5760
case 1: // struct/tuple/self stored property
5861
fallthrough
5962
case 3: // class stored property
60-
// Key paths to stored properties are only single-component if MemoryLayout.offset(of:) returns an offset
61-
func project<T>(_: T.Type) -> Bool {
62-
_keyPathOffset(T.self, self) == nil
63-
}
64-
if _openExistential(Self.rootType, do: project) {
63+
// Stored property components are either just the payload, or the payload plus 32 bits if the offset is not stored in-line
64+
// Note: we cannot use MemoryLayout.offset(of:) here because not all single-component keypaths have direct offsets (for example, stored properties in final classes)
65+
let size = (firstComponentHeader._keyPathComponentHeader_storedIsInline) ? MemoryLayout<UInt32>.size : MemoryLayout<UInt64>.size
66+
if header._keyPathHeader_bufferSize > size {
6567
fatalError("Predicate does not support keypaths with multiple components")
6668
}
6769
case 2: // computed

0 commit comments

Comments
 (0)