Skip to content

[SE-0112] Provide default implementations for CustomNSError requirements #4600

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions stdlib/public/SDK/Foundation/NSError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,37 @@ public protocol CustomNSError : Error {
var errorUserInfo: [String : Any] { get }
}

public extension CustomNSError {
/// Default domain of the error.
static var errorDomain: String {
return String(reflecting: type(of: self))
}

/// The error code within the given domain.
var errorCode: Int {
return _swift_getDefaultErrorCode(self)
}

/// The default user-info dictionary.
var errorUserInfo: [String : Any] {
return [:]
}
}

extension CustomNSError where Self: RawRepresentable, Self.RawValue: SignedInteger {
// The error code of Error with integral raw values is the raw value.
public var errorCode: Int {
return numericCast(self.rawValue)
}
}

extension CustomNSError where Self: RawRepresentable, Self.RawValue: UnsignedInteger {
// The error code of Error with integral raw values is the raw value.
public var errorCode: Int {
return numericCast(self.rawValue)
}
}

public extension Error where Self : CustomNSError {
/// Default implementation for customized NSErrors.
var _domain: String { return Self.errorDomain }
Expand All @@ -129,6 +160,18 @@ public extension Error where Self : CustomNSError {
var _code: Int { return self.errorCode }
}

public extension Error where Self: CustomNSError, Self: RawRepresentable,
Self.RawValue: SignedInteger {
/// Default implementation for customized NSErrors.
var _code: Int { return self.errorCode }
}

public extension Error where Self: CustomNSError, Self: RawRepresentable,
Self.RawValue: UnsignedInteger {
/// Default implementation for customized NSErrors.
var _code: Int { return self.errorCode }
}

public extension Error {
/// Retrieve the localized description for this error.
var localizedDescription: String {
Expand Down
7 changes: 5 additions & 2 deletions stdlib/public/runtime/ErrorObject.mm
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ static Class getSwiftNativeNSErrorClass() {
//public func _stdlib_getErrorDefaultUserInfo<T : Error>(_ x: UnsafePointer<T>) -> AnyObject
SWIFT_CC(swift) SWIFT_RT_ENTRY_VISIBILITY
extern "C" NSDictionary *swift_stdlib_getErrorDefaultUserInfo(
const OpaqueValue *error,
OpaqueValue *error,
const Metadata *T,
const WitnessTable *Error) {
typedef SWIFT_CC(swift)
Expand All @@ -405,7 +405,10 @@ typedef SWIFT_CC(swift)
auto foundationGetDefaultUserInfo = SWIFT_LAZY_CONSTANT(
reinterpret_cast<GetDefaultFn*>
(dlsym(RTLD_DEFAULT, "swift_Foundation_getErrorDefaultUserInfo")));
if (!foundationGetDefaultUserInfo) { return nullptr; }
if (!foundationGetDefaultUserInfo) {
T->vw_destroy(error);
return nullptr;
}

return foundationGetDefaultUserInfo(error, T, Error);
}
Expand Down
26 changes: 26 additions & 0 deletions test/stdlib/ErrorBridged.swift
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,32 @@ ErrorBridgingTests.test("Customizing localization/recovery laziness") {
}
}

enum DefaultCustomizedError1 : CustomNSError {
case bad
case worse
}

enum DefaultCustomizedError2 : Int, CustomNSError {
case bad = 7
case worse = 13
}

enum DefaultCustomizedError3 : UInt, CustomNSError {
case bad = 9
case worse = 115

static var errorDomain: String {
return "customized3"
}
}

ErrorBridgingTests.test("Default-customized via CustomNSError") {
expectEqual(1, (DefaultCustomizedError1.worse as NSError).code)
expectEqual(13, (DefaultCustomizedError2.worse as NSError).code)
expectEqual(115, (DefaultCustomizedError3.worse as NSError).code)
expectEqual("customized3", (DefaultCustomizedError3.worse as NSError).domain)
}

class MyNSError : NSError { }

ErrorBridgingTests.test("NSError subclass identity") {
Expand Down