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