Skip to content

Commit 73e2143

Browse files
committed
[SE-0112] Provide default implementations for CustomNSError requirements.
Provide default implementations for all of the CustomNSError requirements: * errorDomain: default to the name of the enum type * errorCode: default to the same thing "_code" gets, e.g., the enum tag or raw value * errorUserInfo: default to empty This makes it significantly easier to customize just one aspect of the NSError view of an error type, e.g., just the user-info dictionary, without having to write boilerplate for the others. This was actually part of SE-0112, but I missed it in the original implementation and we thought it was an amendment. Fixes rdar://problem/23511842.
1 parent 4a24b06 commit 73e2143

File tree

3 files changed

+74
-2
lines changed

3 files changed

+74
-2
lines changed

stdlib/public/SDK/Foundation/NSError.swift

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,37 @@ public protocol CustomNSError : Error {
121121
var errorUserInfo: [String : Any] { get }
122122
}
123123

124+
public extension CustomNSError {
125+
/// Default domain of the error.
126+
static var errorDomain: String {
127+
return String(reflecting: type(of: self))
128+
}
129+
130+
/// The error code within the given domain.
131+
var errorCode: Int {
132+
return _swift_getDefaultErrorCode(self)
133+
}
134+
135+
/// The default user-info dictionary.
136+
var errorUserInfo: [String : Any] {
137+
return [:]
138+
}
139+
}
140+
141+
extension CustomNSError where Self: RawRepresentable, Self.RawValue: SignedInteger {
142+
// The error code of Error with integral raw values is the raw value.
143+
public var errorCode: Int {
144+
return numericCast(self.rawValue)
145+
}
146+
}
147+
148+
extension CustomNSError where Self: RawRepresentable, Self.RawValue: UnsignedInteger {
149+
// The error code of Error with integral raw values is the raw value.
150+
public var errorCode: Int {
151+
return numericCast(self.rawValue)
152+
}
153+
}
154+
124155
public extension Error where Self : CustomNSError {
125156
/// Default implementation for customized NSErrors.
126157
var _domain: String { return Self.errorDomain }
@@ -129,6 +160,18 @@ public extension Error where Self : CustomNSError {
129160
var _code: Int { return self.errorCode }
130161
}
131162

163+
public extension Error where Self: CustomNSError, Self: RawRepresentable,
164+
Self.RawValue: SignedInteger {
165+
/// Default implementation for customized NSErrors.
166+
var _code: Int { return self.errorCode }
167+
}
168+
169+
public extension Error where Self: CustomNSError, Self: RawRepresentable,
170+
Self.RawValue: UnsignedInteger {
171+
/// Default implementation for customized NSErrors.
172+
var _code: Int { return self.errorCode }
173+
}
174+
132175
public extension Error {
133176
/// Retrieve the localized description for this error.
134177
var localizedDescription: String {

stdlib/public/runtime/ErrorObject.mm

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ static Class getSwiftNativeNSErrorClass() {
394394
//public func _stdlib_getErrorDefaultUserInfo<T : Error>(_ x: UnsafePointer<T>) -> AnyObject
395395
SWIFT_CC(swift) SWIFT_RT_ENTRY_VISIBILITY
396396
extern "C" NSDictionary *swift_stdlib_getErrorDefaultUserInfo(
397-
const OpaqueValue *error,
397+
OpaqueValue *error,
398398
const Metadata *T,
399399
const WitnessTable *Error) {
400400
typedef SWIFT_CC(swift)
@@ -405,7 +405,10 @@ typedef SWIFT_CC(swift)
405405
auto foundationGetDefaultUserInfo = SWIFT_LAZY_CONSTANT(
406406
reinterpret_cast<GetDefaultFn*>
407407
(dlsym(RTLD_DEFAULT, "swift_Foundation_getErrorDefaultUserInfo")));
408-
if (!foundationGetDefaultUserInfo) { return nullptr; }
408+
if (!foundationGetDefaultUserInfo) {
409+
T->vw_destroy(error);
410+
return nullptr;
411+
}
409412

410413
return foundationGetDefaultUserInfo(error, T, Error);
411414
}

test/stdlib/ErrorBridged.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,32 @@ ErrorBridgingTests.test("Customizing localization/recovery laziness") {
582582
}
583583
}
584584

585+
enum DefaultCustomizedError1 : CustomNSError {
586+
case bad
587+
case worse
588+
}
589+
590+
enum DefaultCustomizedError2 : Int, CustomNSError {
591+
case bad = 7
592+
case worse = 13
593+
}
594+
595+
enum DefaultCustomizedError3 : UInt, CustomNSError {
596+
case bad = 9
597+
case worse = 115
598+
599+
static var errorDomain: String {
600+
return "customized3"
601+
}
602+
}
603+
604+
ErrorBridgingTests.test("Default-customized via CustomNSError") {
605+
expectEqual(1, (DefaultCustomizedError1.worse as NSError).code)
606+
expectEqual(13, (DefaultCustomizedError2.worse as NSError).code)
607+
expectEqual(115, (DefaultCustomizedError3.worse as NSError).code)
608+
expectEqual("customized3", (DefaultCustomizedError3.worse as NSError).domain)
609+
}
610+
585611
class MyNSError : NSError { }
586612

587613
ErrorBridgingTests.test("NSError subclass identity") {

0 commit comments

Comments
 (0)