@@ -1557,6 +1557,50 @@ static bool _dynamicCastToUnknownClassFromExistential(OpaqueValue *dest,
1557
1557
}
1558
1558
}
1559
1559
1560
+ static void unwrapExistential (OpaqueValue *src,
1561
+ const ExistentialTypeMetadata *srcType,
1562
+ OpaqueValue *&srcValue,
1563
+ const Metadata *&srcCapturedType,
1564
+ bool &isOutOfLine,
1565
+ bool &canTake) {
1566
+ switch (srcType->getRepresentation ()) {
1567
+ case ExistentialTypeRepresentation::Class: {
1568
+ auto classContainer =
1569
+ reinterpret_cast <const ClassExistentialContainer*>(src);
1570
+ srcValue = (OpaqueValue*) &classContainer->Value ;
1571
+ void *obj = classContainer->Value ;
1572
+ srcCapturedType = swift_getObjectType (reinterpret_cast <HeapObject*>(obj));
1573
+ isOutOfLine = false ;
1574
+ canTake = true ;
1575
+ break ;
1576
+ }
1577
+ case ExistentialTypeRepresentation::Opaque: {
1578
+ auto opaqueContainer = reinterpret_cast <OpaqueExistentialContainer*>(src);
1579
+ srcCapturedType = opaqueContainer->Type ;
1580
+ srcValue = srcCapturedType->vw_projectBuffer (&opaqueContainer->Buffer );
1581
+ isOutOfLine = (src != srcValue);
1582
+ canTake = true ;
1583
+ break ;
1584
+ }
1585
+ case ExistentialTypeRepresentation::Error: {
1586
+ const SwiftError *errorBox
1587
+ = *reinterpret_cast <const SwiftError * const *>(src);
1588
+
1589
+ srcCapturedType = errorBox->getType ();
1590
+ // A bridged NSError is itself the value.
1591
+ if (errorBox->isPureNSError ())
1592
+ srcValue = src;
1593
+ else
1594
+ srcValue = const_cast <OpaqueValue*>(errorBox->getValue ());
1595
+
1596
+ // The value is out-of-line, but we can't take it, since it may be shared.
1597
+ isOutOfLine = true ;
1598
+ canTake = false ;
1599
+ break ;
1600
+ }
1601
+ }
1602
+ }
1603
+
1560
1604
// / Perform a dynamic cast from an existential type to a
1561
1605
// / non-existential type.
1562
1606
static bool _dynamicCastFromExistential (OpaqueValue *dest,
@@ -1569,42 +1613,8 @@ static bool _dynamicCastFromExistential(OpaqueValue *dest,
1569
1613
bool isOutOfLine;
1570
1614
bool canTake;
1571
1615
1572
- switch (srcType->getRepresentation ()) {
1573
- case ExistentialTypeRepresentation::Class: {
1574
- auto classContainer =
1575
- reinterpret_cast <const ClassExistentialContainer*>(src);
1576
- srcValue = (OpaqueValue*) &classContainer->Value ;
1577
- void *obj = classContainer->Value ;
1578
- srcCapturedType = swift_getObjectType (reinterpret_cast <HeapObject*>(obj));
1579
- isOutOfLine = false ;
1580
- canTake = true ;
1581
- break ;
1582
- }
1583
- case ExistentialTypeRepresentation::Opaque: {
1584
- auto opaqueContainer = reinterpret_cast <OpaqueExistentialContainer*>(src);
1585
- srcCapturedType = opaqueContainer->Type ;
1586
- srcValue = srcCapturedType->vw_projectBuffer (&opaqueContainer->Buffer );
1587
- isOutOfLine = (src != srcValue);
1588
- canTake = true ;
1589
- break ;
1590
- }
1591
- case ExistentialTypeRepresentation::Error: {
1592
- const SwiftError *errorBox
1593
- = *reinterpret_cast <const SwiftError * const *>(src);
1594
-
1595
- srcCapturedType = errorBox->getType ();
1596
- // A bridged NSError is itself the value.
1597
- if (errorBox->isPureNSError ())
1598
- srcValue = src;
1599
- else
1600
- srcValue = const_cast <OpaqueValue*>(errorBox->getValue ());
1601
-
1602
- // The value is out-of-line, but we can't take it, since it may be shared.
1603
- isOutOfLine = true ;
1604
- canTake = false ;
1605
- break ;
1606
- }
1607
- }
1616
+ unwrapExistential (src, srcType,
1617
+ srcValue, srcCapturedType, isOutOfLine, canTake);
1608
1618
1609
1619
auto subFlags = flags;
1610
1620
if (!canTake)
@@ -1622,8 +1632,11 @@ static bool _dynamicCastFromExistential(OpaqueValue *dest,
1622
1632
} else {
1623
1633
// swift_dynamicCast took or destroyed the value as per the original request
1624
1634
// We may still have an opaque existential container to deallocate.
1625
- if (isOutOfLine)
1635
+ if (isOutOfLine) {
1636
+ assert (srcType->getRepresentation ()
1637
+ == ExistentialTypeRepresentation::Opaque);
1626
1638
_maybeDeallocateOpaqueExistential (src, result, flags);
1639
+ }
1627
1640
}
1628
1641
1629
1642
return result;
@@ -2515,16 +2528,48 @@ static bool _dynamicCastClassToValueViaObjCBridgeable(
2515
2528
return success;
2516
2529
}
2517
2530
2518
- SWIFT_CC (swift) SWIFT_RUNTIME_STDLIB_INTERFACE
2519
- extern "C"
2520
- id _swift_bridgeAnythingNonVerbatimToObjectiveC(OpaqueValue *src,
2521
- const Metadata *srcType) {
2531
+ static id bridgeAnythingNonVerbatimToObjectiveC (OpaqueValue *src,
2532
+ const Metadata *srcType,
2533
+ bool consume) {
2522
2534
// We can always bridge objects verbatim.
2523
2535
if (srcType->isAnyClass ()) {
2524
- return *(id*)src;
2536
+ id result;
2537
+ memcpy (&result, src, sizeof (id));
2538
+ if (!consume)
2539
+ swift_unknownRetain (result);
2540
+ return result;
2525
2541
}
2526
2542
2527
- // TODO: Look through existential containers.
2543
+ // Dig through existential types.
2544
+ if (auto srcExistentialTy = dyn_cast<ExistentialTypeMetadata>(srcType)) {
2545
+ OpaqueValue *srcInnerValue;
2546
+ const Metadata *srcInnerType;
2547
+ bool isOutOfLine;
2548
+ bool canTake;
2549
+
2550
+ unwrapExistential (src, srcExistentialTy,
2551
+ srcInnerValue, srcInnerType, isOutOfLine, canTake);
2552
+ auto result = bridgeAnythingNonVerbatimToObjectiveC (srcInnerValue,
2553
+ srcInnerType,
2554
+ consume && canTake);
2555
+ // Clean up the existential, or its remains after taking the value from
2556
+ // it.
2557
+ if (consume) {
2558
+ if (canTake) {
2559
+ if (isOutOfLine) {
2560
+ // Should only be true of opaque existentials.
2561
+ assert (srcExistentialTy->getRepresentation ()
2562
+ == ExistentialTypeRepresentation::Opaque);
2563
+ auto container = reinterpret_cast <OpaqueExistentialContainer*>(src);
2564
+ srcInnerType->vw_deallocateBuffer (&container->Buffer );
2565
+ }
2566
+ } else {
2567
+ // We didn't take the value, so clean up the existential value.
2568
+ srcType->vw_destroy (src);
2569
+ }
2570
+ }
2571
+ return result;
2572
+ }
2528
2573
2529
2574
if (auto srcBridgeWitness = findBridgeWitness (srcType)) {
2530
2575
// Check whether the source is bridged to Objective-C.
@@ -2537,14 +2582,22 @@ id _swift_bridgeAnythingNonVerbatimToObjectiveC(OpaqueValue *src,
2537
2582
auto srcBridgedObject =
2538
2583
srcBridgeWitness->bridgeToObjectiveC (src, srcType, srcBridgeWitness);
2539
2584
2540
- // The source object was passed in +1.
2541
- srcType->vw_destroy (src);
2585
+ // Consume if the source object was passed in +1.
2586
+ if (consume)
2587
+ srcType->vw_destroy (src);
2542
2588
2543
2589
return (id)srcBridgedObject;
2544
2590
}
2545
2591
2546
2592
// TODO: Fall back to boxing here.
2547
- crash (" unimplemented universal bridging conversion" );
2593
+ crash (" unimplemented boxing bridge" );
2594
+ }
2595
+
2596
+ SWIFT_CC (swift) SWIFT_RUNTIME_STDLIB_INTERFACE
2597
+ extern "C"
2598
+ id _swift_bridgeAnythingNonVerbatimToObjectiveC(OpaqueValue *src,
2599
+ const Metadata *srcType) {
2600
+ return bridgeAnythingNonVerbatimToObjectiveC (src, srcType, /* consume*/ true );
2548
2601
}
2549
2602
2550
2603
// ===--- Bridging helpers for the Swift stdlib ----------------------------===//
0 commit comments