@@ -462,47 +462,27 @@ NSInteger getErrorCode(const OpaqueValue *error,
462
462
extern " C" const ProtocolDescriptor PROTOCOL_DESCR_SYM (s5Error);
463
463
464
464
bool
465
- swift::tryDynamicCastNSErrorToValue (OpaqueValue *dest,
466
- OpaqueValue *src,
467
- const Metadata *srcType,
468
- const Metadata *destType,
469
- DynamicCastFlags flags) {
465
+ swift::tryDynamicCastNSErrorObjectToValue (HeapObject *object,
466
+ OpaqueValue *dest,
467
+ const Metadata *destType,
468
+ DynamicCastFlags flags) {
470
469
Class NSErrorClass = getNSErrorClass ();
471
- auto CFErrorTypeID = SWIFT_LAZY_CONSTANT (CFErrorGetTypeID ());
472
470
473
- NSError *srcInstance;
474
-
475
- // Is the input type an NSError?
476
- switch (srcType->getKind ()) {
477
- case MetadataKind::Class :
478
- case MetadataKind::ObjCClassWrapper:
479
- // Native class or ObjC class should be an NSError subclass.
480
- if (![srcType->getObjCClassObject () isSubclassOfClass: NSErrorClass])
481
- return false ;
482
-
483
- srcInstance = *reinterpret_cast <NSError * const *>(src);
484
-
485
- // A _SwiftNativeNSError box can always be unwrapped to cast the value back
486
- // out as an Error existential.
487
- if (!reinterpret_cast <SwiftError*>(srcInstance)->isPureNSError ()) {
488
- auto theErrorProtocol = &PROTOCOL_DESCR_SYM (s5Error);
489
- auto theErrorTy =
490
- swift_getExistentialTypeMetadata (ProtocolClassConstraint::Any,
491
- nullptr , 1 , &theErrorProtocol);
492
- return swift_dynamicCast (dest, src, theErrorTy, destType, flags);
493
- }
494
-
495
- break ;
496
- case MetadataKind::ForeignClass: {
497
- // Foreign class should be CFError.
498
- CFTypeRef srcInstance = *reinterpret_cast <CFTypeRef *>(src);
499
- if (CFGetTypeID (srcInstance) != CFErrorTypeID)
500
- return false ;
501
- break ;
502
- }
503
- // Not a class.
504
- default :
471
+ // The object must be an NSError subclass.
472
+ if (![reinterpret_cast<id >(object) isKindOfClass: NSErrorClass])
505
473
return false ;
474
+
475
+ NSError *srcInstance = reinterpret_cast <NSError *>(object);
476
+
477
+ // A _SwiftNativeNSError box can always be unwrapped to cast the value back
478
+ // out as an Error existential.
479
+ if (!reinterpret_cast <SwiftError*>(srcInstance)->isPureNSError ()) {
480
+ auto theErrorProtocol = &PROTOCOL_DESCR_SYM (s5Error);
481
+ auto theErrorTy =
482
+ swift_getExistentialTypeMetadata (ProtocolClassConstraint::Any,
483
+ nullptr , 1 , &theErrorProtocol);
484
+ return swift_dynamicCast (dest, reinterpret_cast <OpaqueValue *>(&object),
485
+ theErrorTy, destType, flags);
506
486
}
507
487
508
488
// public func Foundation._bridgeNSErrorToError<
@@ -521,19 +501,47 @@ NSInteger getErrorCode(const OpaqueValue *error,
521
501
auto witness = swift_conformsToProtocol (destType,
522
502
TheObjectiveCBridgeableError);
523
503
524
- if (!witness)
525
- return false ;
504
+ if (witness) {
505
+ // If so, attempt the bridge.
506
+ if (bridgeNSErrorToError (srcInstance, dest, destType, witness)) {
507
+ if (flags & DynamicCastFlags::TakeOnSuccess)
508
+ objc_release (srcInstance);
509
+ return true ;
510
+ }
511
+ }
526
512
527
- // If so, attempt the bridge.
528
- SWIFT_CC_PLUSONE_GUARD (objc_retain (srcInstance));
529
- if (bridgeNSErrorToError (srcInstance, dest, destType, witness)) {
530
- if (flags & DynamicCastFlags::TakeOnSuccess)
531
- objc_release (srcInstance);
513
+ // If the destination is just an Error then we can bridge directly.
514
+ auto *destTypeExistential = dyn_cast<ExistentialTypeMetadata>(destType);
515
+ if (destTypeExistential &&
516
+ destTypeExistential->getRepresentation () == ExistentialTypeRepresentation::Error) {
517
+ auto destBoxAddr = reinterpret_cast <NSError **>(dest);
518
+ *destBoxAddr = objc_retain (srcInstance);
532
519
return true ;
533
520
}
521
+
534
522
return false ;
535
523
}
536
524
525
+ bool
526
+ swift::tryDynamicCastNSErrorToValue (OpaqueValue *dest,
527
+ OpaqueValue *src,
528
+ const Metadata *srcType,
529
+ const Metadata *destType,
530
+ DynamicCastFlags flags) {
531
+ // NSError instances must be class instances, anything else automatically fails.
532
+ switch (srcType->getKind ()) {
533
+ case MetadataKind::Class :
534
+ case MetadataKind::ObjCClassWrapper:
535
+ case MetadataKind::ForeignClass:
536
+ return tryDynamicCastNSErrorObjectToValue (*reinterpret_cast <HeapObject **>(src),
537
+ dest, destType, flags);
538
+
539
+ // Not a class.
540
+ default :
541
+ return false ;
542
+ }
543
+ }
544
+
537
545
SwiftError *
538
546
swift::swift_errorRetain (SwiftError *error) {
539
547
// For now, SwiftError is always objc-refcounted.
0 commit comments