Skip to content

Commit e202e90

Browse files
authored
Clean up _BridgedNSError and _BridgedStoredNSError (#14682)
Despite their similar names and uses, these protocols no longer share much functionality - the former is used to take @objc enums defined in Swift that conform to Error and expose them as NSErrors, and the latter handles NS_ERROR_ENUM C enums, which get imported into Swift as a wrapper around NSError. We can actually simplify them quite a bit. - Eliminate base protocol __BridgedNSError, which no longer provides any implementation for _BridgedStoredNSError. - Eliminate default implementations that match what the compiler would synthesize. - Adopt recursive constraints and where-clauses on associated types (and update the Clang importer to handle this). - Collapse signed and unsigned default implementations when reasonable. - Fold _BridgedStoredNSError's _nsErrorDomain into the existing public requirement CustomNSError.errorDomain. rdar://problem/35230080
1 parent 1a87a8c commit e202e90

File tree

4 files changed

+54
-96
lines changed

4 files changed

+54
-96
lines changed

include/swift/AST/KnownIdentifiers.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ IDENTIFIER(encodeIfPresent)
5252
IDENTIFIER(Encoder)
5353
IDENTIFIER(encoder)
5454
IDENTIFIER(error)
55+
IDENTIFIER(errorDomain)
5556
IDENTIFIER(forKeyedSubscript)
5657
IDENTIFIER(Foundation)
5758
IDENTIFIER(forKey)

lib/ClangImporter/ImportDecl.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1870,7 +1870,7 @@ static bool addErrorDomain(NominalTypeDecl *swiftDecl,
18701870
// Make the property decl
18711871
auto errorDomainPropertyDecl = new (C) VarDecl(
18721872
/*IsStatic*/isStatic, VarDecl::Specifier::Var, /*IsCaptureList*/false,
1873-
SourceLoc(), C.Id_nsErrorDomain, stringTy, swiftDecl);
1873+
SourceLoc(), C.Id_errorDomain, stringTy, swiftDecl);
18741874
errorDomainPropertyDecl->setInterfaceType(stringTy);
18751875
errorDomainPropertyDecl->setValidationStarted();
18761876
errorDomainPropertyDecl->setAccess(AccessLevel::Public);
@@ -2740,7 +2740,7 @@ namespace {
27402740
errorWrapper->addMember(nsErrorInit);
27412741

27422742
// Add the domain error member.
2743-
// public static var _nsErrorDomain: String { return error-domain }
2743+
// public static var errorDomain: String { return error-domain }
27442744
addErrorDomain(errorWrapper, enumInfo.getErrorDomain(), Impl);
27452745

27462746
// Note: the Code will be added after it's created.
@@ -7777,6 +7777,22 @@ static void finishInheritedConformances(
77777777
}
77787778
}
77797779

7780+
static Type
7781+
recursivelySubstituteBaseType(const NormalProtocolConformance *conformance,
7782+
DependentMemberType *depMemTy) {
7783+
Type origBase = depMemTy->getBase();
7784+
if (auto *depBase = origBase->getAs<DependentMemberType>()) {
7785+
Type substBase = recursivelySubstituteBaseType(conformance, depBase);
7786+
ModuleDecl *module = conformance->getDeclContext()->getParentModule();
7787+
return depMemTy->substBaseType(module, substBase);
7788+
}
7789+
7790+
const ProtocolDecl *proto = conformance->getProtocol();
7791+
assert(origBase->isEqual(proto->getSelfInterfaceType()));
7792+
return conformance->getTypeWitness(depMemTy->getAssocType(),
7793+
/*resolver=*/nullptr);
7794+
}
7795+
77807796
/// Collect conformances for the requirement signature.
77817797
static void finishSignatureConformances(
77827798
NormalProtocolConformance *conformance) {
@@ -7793,9 +7809,7 @@ static void finishSignatureConformances(
77937809
substTy = conformance->getType();
77947810
} else {
77957811
auto *depMemTy = origTy->castTo<DependentMemberType>();
7796-
assert(depMemTy->getBase()->isEqual(proto->getSelfInterfaceType()));
7797-
substTy = conformance->getTypeWitness(depMemTy->getAssocType(),
7798-
/*resolver=*/nullptr);
7812+
substTy = recursivelySubstituteBaseType(conformance, depMemTy);
77997813
}
78007814
auto reqProto = req.getSecondType()->castTo<ProtocolType>()->getDecl();
78017815

stdlib/public/SDK/Foundation/NSError.swift

Lines changed: 33 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -366,93 +366,59 @@ public func _bridgeNSErrorToError<
366366
}
367367
}
368368

369-
/// Helper protocol for _BridgedNSError, which used to provide
370-
/// default implementations.
371-
public protocol __BridgedNSError : Error {
369+
/// Describes a raw representable type that is bridged to a particular
370+
/// NSError domain.
371+
///
372+
/// This protocol is used primarily to generate the conformance to
373+
/// _ObjectiveCBridgeableError for such an enum defined in Swift.
374+
public protocol _BridgedNSError :
375+
_ObjectiveCBridgeableError, RawRepresentable, Hashable
376+
where Self.RawValue: FixedWidthInteger {
377+
/// The NSError domain to which this type is bridged.
372378
static var _nsErrorDomain: String { get }
373379
}
374380

375-
// Allow two bridged NSError types to be compared.
376-
extension __BridgedNSError
377-
where Self: RawRepresentable, Self.RawValue: SignedInteger {
378-
public static func ==(lhs: Self, rhs: Self) -> Bool {
379-
return lhs.rawValue == rhs.rawValue
380-
}
381+
extension _BridgedNSError {
382+
public var _domain: String { return Self._nsErrorDomain }
381383
}
382384

383-
public extension __BridgedNSError
384-
where Self: RawRepresentable, Self.RawValue: SignedInteger {
385-
public var _domain: String { return Self._nsErrorDomain }
385+
extension _BridgedNSError where Self.RawValue: SignedInteger {
386386
public var _code: Int { return Int(rawValue) }
387387

388-
public init?(rawValue: RawValue) {
389-
self = unsafeBitCast(rawValue, to: Self.self)
390-
}
391-
392388
public init?(_bridgedNSError: NSError) {
393389
if _bridgedNSError.domain != Self._nsErrorDomain {
394390
return nil
395391
}
396392

397-
self.init(rawValue: RawValue(IntMax(_bridgedNSError.code)))
393+
self.init(rawValue: RawValue(_bridgedNSError.code))
398394
}
399395

400396
public var hashValue: Int { return _code }
401397
}
402398

403-
// Allow two bridged NSError types to be compared.
404-
extension __BridgedNSError
405-
where Self: RawRepresentable, Self.RawValue: UnsignedInteger {
406-
public static func ==(lhs: Self, rhs: Self) -> Bool {
407-
return lhs.rawValue == rhs.rawValue
408-
}
409-
}
410-
411-
public extension __BridgedNSError
412-
where Self: RawRepresentable, Self.RawValue: UnsignedInteger {
413-
public var _domain: String { return Self._nsErrorDomain }
399+
extension _BridgedNSError where Self.RawValue: UnsignedInteger {
414400
public var _code: Int {
415401
return Int(bitPattern: UInt(rawValue))
416402
}
417403

418-
public init?(rawValue: RawValue) {
419-
self = unsafeBitCast(rawValue, to: Self.self)
420-
}
421-
422404
public init?(_bridgedNSError: NSError) {
423405
if _bridgedNSError.domain != Self._nsErrorDomain {
424406
return nil
425407
}
426408

427-
self.init(rawValue: RawValue(UIntMax(UInt(_bridgedNSError.code))))
409+
self.init(rawValue: RawValue(UInt(bitPattern: _bridgedNSError.code)))
428410
}
429411

430412
public var hashValue: Int { return _code }
431413
}
432414

433-
/// Describes a raw representable type that is bridged to a particular
434-
/// NSError domain.
435-
///
436-
/// This protocol is used primarily to generate the conformance to
437-
/// _ObjectiveCBridgeableError for such an enum.
438-
public protocol _BridgedNSError : __BridgedNSError,
439-
RawRepresentable,
440-
_ObjectiveCBridgeableError,
441-
Hashable {
442-
/// The NSError domain to which this type is bridged.
443-
static var _nsErrorDomain: String { get }
444-
}
445-
446415
/// Describes a bridged error that stores the underlying NSError, so
447416
/// it can be queried.
448417
public protocol _BridgedStoredNSError :
449-
__BridgedNSError, _ObjectiveCBridgeableError, CustomNSError,
450-
Hashable {
418+
_ObjectiveCBridgeableError, CustomNSError, Hashable {
451419
/// The type of an error code.
452-
associatedtype Code: _ErrorCodeProtocol
453-
454-
/// The error code for the given error.
455-
var code: Code { get }
420+
associatedtype Code: _ErrorCodeProtocol, RawRepresentable
421+
where Code.RawValue: FixedWidthInteger
456422

457423
//// Retrieves the embedded NSError.
458424
var _nsError: NSError { get }
@@ -476,49 +442,30 @@ internal func _stringDictToAnyHashableDict(_ input: [String : Any])
476442
}
477443

478444
/// Various helper implementations for _BridgedStoredNSError
479-
public extension _BridgedStoredNSError
480-
where Code: RawRepresentable, Code.RawValue: SignedInteger {
481-
// FIXME: Generalize to Integer.
445+
extension _BridgedStoredNSError {
482446
public var code: Code {
483447
return Code(rawValue: numericCast(_nsError.code))!
484448
}
485449

486450
/// Initialize an error within this domain with the given ``code``
487451
/// and ``userInfo``.
488452
public init(_ code: Code, userInfo: [String : Any] = [:]) {
489-
self.init(_nsError: NSError(domain: Self._nsErrorDomain,
453+
self.init(_nsError: NSError(domain: Self.errorDomain,
490454
code: numericCast(code.rawValue),
491455
userInfo: _stringDictToAnyHashableDict(userInfo)))
492456
}
493457

494458
/// The user-info dictionary for an error that was bridged from
495459
/// NSError.
496-
var userInfo: [String : Any] { return errorUserInfo }
497-
}
498-
499-
/// Various helper implementations for _BridgedStoredNSError
500-
public extension _BridgedStoredNSError
501-
where Code: RawRepresentable, Code.RawValue: UnsignedInteger {
502-
// FIXME: Generalize to Integer.
503-
public var code: Code {
504-
return Code(rawValue: numericCast(_nsError.code))!
505-
}
506-
507-
/// Initialize an error within this domain with the given ``code``
508-
/// and ``userInfo``.
509-
public init(_ code: Code, userInfo: [String : Any] = [:]) {
510-
self.init(_nsError: NSError(domain: Self._nsErrorDomain,
511-
code: numericCast(code.rawValue),
512-
userInfo: _stringDictToAnyHashableDict(userInfo)))
513-
}
460+
public var userInfo: [String : Any] { return errorUserInfo }
514461
}
515462

516-
/// Implementation of __BridgedNSError for all _BridgedStoredNSErrors.
463+
/// Implementation of _ObjectiveCBridgeableError for all _BridgedStoredNSErrors.
517464
public extension _BridgedStoredNSError {
518-
/// Default implementation of ``init(_bridgedNSError)`` to provide
465+
/// Default implementation of ``init(_bridgedNSError:)`` to provide
519466
/// bridging from NSError.
520467
public init?(_bridgedNSError error: NSError) {
521-
if error.domain != Self._nsErrorDomain {
468+
if error.domain != Self.errorDomain {
522469
return nil
523470
}
524471

@@ -531,7 +478,8 @@ public extension _BridgedStoredNSError {
531478
// FIXME: Would prefer to have a clear "extract an NSError
532479
// directly" operation.
533480

534-
static var errorDomain: String { return _nsErrorDomain }
481+
// Synthesized by the compiler.
482+
// static var errorDomain: String
535483

536484
var errorCode: Int { return _nsError.code }
537485

@@ -555,20 +503,15 @@ public extension _BridgedStoredNSError {
555503
/// Describes the code of an error.
556504
public protocol _ErrorCodeProtocol : Equatable {
557505
/// The corresponding error code.
558-
associatedtype _ErrorType
559-
560-
// FIXME: We want _ErrorType to be _BridgedStoredNSError and have its
561-
// Code match Self, but we cannot express those requirements yet.
506+
associatedtype _ErrorType: _BridgedStoredNSError where _ErrorType.Code == Self
562507
}
563508

564-
extension _ErrorCodeProtocol where Self._ErrorType: _BridgedStoredNSError {
509+
extension _ErrorCodeProtocol {
565510
/// Allow one to match an error code against an arbitrary error.
566511
public static func ~=(match: Self, error: Error) -> Bool {
567512
guard let specificError = error as? Self._ErrorType else { return false }
568513

569-
// FIXME: Work around IRGen crash when we set Code == Code._ErrorType.Code.
570-
let specificCode = specificError.code as! Self
571-
return match == specificCode
514+
return match == specificError.code
572515
}
573516
}
574517

@@ -595,7 +538,7 @@ public struct CocoaError : _BridgedStoredNSError {
595538
self._nsError = error
596539
}
597540

598-
public static var _nsErrorDomain: String { return NSCocoaErrorDomain }
541+
public static var errorDomain: String { return NSCocoaErrorDomain }
599542

600543
/// The error code itself.
601544
public struct Code : RawRepresentable, Hashable, _ErrorCodeProtocol {
@@ -1826,7 +1769,7 @@ public struct URLError : _BridgedStoredNSError {
18261769
self._nsError = error
18271770
}
18281771

1829-
public static var _nsErrorDomain: String { return NSURLErrorDomain }
1772+
public static var errorDomain: String { return NSURLErrorDomain }
18301773

18311774
/// The error code itself.
18321775
public struct Code : RawRepresentable, Hashable, _ErrorCodeProtocol {
@@ -2486,7 +2429,7 @@ public struct POSIXError : _BridgedStoredNSError {
24862429
self._nsError = error
24872430
}
24882431

2489-
public static var _nsErrorDomain: String { return NSPOSIXErrorDomain }
2432+
public static var errorDomain: String { return NSPOSIXErrorDomain }
24902433

24912434
public typealias Code = POSIXErrorCode
24922435
}
@@ -2972,7 +2915,7 @@ public struct MachError : _BridgedStoredNSError {
29722915
self._nsError = error
29732916
}
29742917

2975-
public static var _nsErrorDomain: String { return NSMachErrorDomain }
2918+
public static var errorDomain: String { return NSMachErrorDomain }
29762919

29772920
public typealias Code = MachErrorCode
29782921
}

test/stdlib/Intents.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ if #available(OSX 10.12, iOS 10.0, watchOS 3.2, *) {
2424
}
2525

2626
IntentsTestSuite.test("extension/\(swiftVersion)") {
27-
expectEqual("IntentsErrorDomain", INIntentError._nsErrorDomain)
27+
expectEqual("IntentsErrorDomain", INIntentError.errorDomain)
2828
}
2929
}
3030

0 commit comments

Comments
 (0)