我相信Error 可转换为NSError 的能力是硬编码到编译器中的,而实际的桥接是在 Swift 运行时中实现的。
在runtime/ErrorObject.mm,我发现了这条评论:
// This implements the object representation of the standard Error
// type, which represents recoverable errors in the language. This
// implementation is designed to interoperate efficiently with Cocoa libraries
// by:
// - ...
// - allowing a native Swift error to lazily "become" an NSError when
// passed into Cocoa, allowing for cheap Swift to Cocoa interop
还有this function:
/// Take an Error box and turn it into a valid NSError instance.
id
swift::_swift_stdlib_bridgeErrorToNSError(SwiftError *errorObject) {
...
// Otherwise, calculate the domain, code, and user info, and
// initialize the NSError.
auto value = SwiftError::getIndirectValue(&errorObject);
auto type = errorObject->getType();
auto witness = errorObject->getErrorConformance();
NSString *domain = getErrorDomainNSString(value, type, witness);
NSInteger code = getErrorCode(value, type, witness);
NSDictionary *userInfo = getErrorUserInfoNSDictionary(value, type, witness);
...
}
ErrorHandling.rst document 谈到了基本原理:
应该可以将符合Error 的任意Swift 枚举转换为NSError,方法是使用限定类型名称作为域键、枚举器作为错误代码,并将有效负载转换为用户数据。
(文档的某些部分可能已过时。)
并且this is(我认为)类型检查器中至少有一部分是Error 可转换为NSError 的信息被编码(可能还有更多):
// Check whether the type is an existential that contains
// Error. If so, it's bridged to NSError.
if (type->isExistentialWithError()) {
if (auto nsErrorDecl = getNSErrorDecl()) {
// The corresponding value type is Error.
if (bridgedValueType)
*bridgedValueType = getErrorDecl()->getDeclaredInterfaceType();
return nsErrorDecl->getDeclaredInterfaceType();
}
}