Skip to content

Commit f7455a8

Browse files
committed
Runtime: Archive _SwiftNativeNSErrors as NSErrors.
_SwiftNativeNSError is a runtime-private subclass, and NSError's inherited NSCoding implementation doesn't handle the Swift payload of bridged errors. We can't really archive arbitrary Swift values anyway yet, so just archive bridged NSError subclasses as regular NSErrors. Fixes rdar://problem/23051728.
1 parent 233a2ba commit f7455a8

File tree

2 files changed

+24
-0
lines changed

2 files changed

+24
-0
lines changed

stdlib/public/runtime/ErrorObject.mm

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,12 @@ - (id)copyWithZone:(NSZone *)zone {
9595
return [self retain];
9696
}
9797

98+
- (Class)classForCoder {
99+
// This is a runtime-private subclass. When archiving or unarchiving, do so
100+
// as an NSError.
101+
return [NSError class];
102+
}
103+
98104
@end
99105

100106
Class swift::getNSErrorClass() {

test/1_stdlib/ErrorProtocolBridging.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,24 @@ ErrorProtocolBridgingTests.test("NSCopying") {
6868
}
6969
}
7070

71+
func archiveAndUnarchiveObject<T: NSCoding where T: NSObject>(
72+
_ object: T
73+
) -> T? {
74+
let unarchiver = NSKeyedUnarchiver(forReadingWith:
75+
NSKeyedArchiver.archivedData(withRootObject: object)
76+
)
77+
unarchiver.requiresSecureCoding = true
78+
return unarchiver.decodeObjectOfClass(T.self, forKey: "root")
79+
}
80+
ErrorProtocolBridgingTests.test("NSCoding") {
81+
autoreleasepool {
82+
let orig = EnumError.ReallyBadError as NSError
83+
let unarchived = archiveAndUnarchiveObject(orig)!
84+
expectEqual(orig, unarchived)
85+
expectTrue(unarchived.dynamicType == NSError.self)
86+
}
87+
}
88+
7189
ErrorProtocolBridgingTests.test("NSError-to-enum bridging") {
7290
NoisyErrorLifeCount = 0
7391
NoisyErrorDeathCount = 0

0 commit comments

Comments
 (0)