@@ -462,47 +462,27 @@ NSInteger getErrorCode(const OpaqueValue *error,
462462extern " C" const ProtocolDescriptor PROTOCOL_DESCR_SYM (s5Error);
463463
464464bool
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) {
470469 Class NSErrorClass = getNSErrorClass ();
471- auto CFErrorTypeID = SWIFT_LAZY_CONSTANT (CFErrorGetTypeID ());
472470
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])
505473 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);
506486 }
507487
508488 // public func Foundation._bridgeNSErrorToError<
@@ -521,19 +501,47 @@ NSInteger getErrorCode(const OpaqueValue *error,
521501 auto witness = swift_conformsToProtocol (destType,
522502 TheObjectiveCBridgeableError);
523503
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+ }
526512
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);
532519 return true ;
533520 }
521+
534522 return false ;
535523}
536524
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+
537545SwiftError *
538546swift::swift_errorRetain (SwiftError *error) {
539547 // For now, SwiftError is always objc-refcounted.
0 commit comments