@@ -2497,6 +2497,51 @@ static bool _dynamicCastStructToStruct(OpaqueValue *destination,
2497
2497
return result;
2498
2498
}
2499
2499
2500
+ static bool _dynamicCastTupleToTuple (OpaqueValue *destination,
2501
+ OpaqueValue *source,
2502
+ const TupleTypeMetadata *sourceType,
2503
+ const TupleTypeMetadata *targetType,
2504
+ DynamicCastFlags flags) {
2505
+ assert (sourceType != targetType &&
2506
+ " Caller should handle exact tuple matches" );
2507
+
2508
+
2509
+ // Simple case: number of elements mismatches.
2510
+ if (sourceType->NumElements != targetType->NumElements )
2511
+ return _fail (source, sourceType, targetType, flags);
2512
+
2513
+ // Check that the elements line up.
2514
+ const char *sourceLabels = sourceType->Labels ;
2515
+ const char *targetLabels = targetType->Labels ;
2516
+ for (unsigned i = 0 , n = sourceType->NumElements ; i != n; ++i) {
2517
+ // Check the label, if there is one.
2518
+ if (sourceLabels && targetLabels && sourceLabels != targetLabels) {
2519
+ const char *sourceSpace = strchr (sourceLabels, ' ' );
2520
+ const char *targetSpace = strchr (targetLabels, ' ' );
2521
+
2522
+ // If both have labels, and the labels mismatch, we fail.
2523
+ if (sourceSpace && sourceSpace != sourceLabels &&
2524
+ targetSpace && targetSpace != targetLabels) {
2525
+ unsigned sourceLen = sourceSpace - sourceLabels;
2526
+ unsigned targetLen = targetSpace - targetLabels;
2527
+ if (sourceLen != targetLen ||
2528
+ strncmp (sourceLabels, targetLabels, sourceLen) != 0 )
2529
+ return _fail (source, sourceType, targetType, flags);
2530
+ }
2531
+
2532
+ sourceLabels = sourceSpace ? sourceSpace + 1 : nullptr ;
2533
+ targetLabels = targetSpace ? targetSpace + 1 : nullptr ;
2534
+ }
2535
+
2536
+ // Make sure the types match exactly.
2537
+ // FIXME: we should dynamically cast the elements themselves.
2538
+ if (sourceType->getElement (i).Type != targetType->getElement (i).Type )
2539
+ return _fail (source, sourceType, targetType, flags);
2540
+ }
2541
+
2542
+ return _succeed (destination, source, targetType, flags);
2543
+ }
2544
+
2500
2545
/* *****************************************************************************/
2501
2546
/* ***************************** Main Entrypoint *******************************/
2502
2547
/* *****************************************************************************/
@@ -2718,6 +2763,15 @@ bool swift::swift_dynamicCast(OpaqueValue *dest,
2718
2763
targetType, flags);
2719
2764
}
2720
2765
2766
+ // If both are tuple types, allow the cast to add/remove labels.
2767
+ if (srcType->getKind () == MetadataKind::Tuple &&
2768
+ targetType->getKind () == MetadataKind::Tuple) {
2769
+ return _dynamicCastTupleToTuple (dest, src,
2770
+ cast<TupleTypeMetadata>(srcType),
2771
+ cast<TupleTypeMetadata>(targetType),
2772
+ flags);
2773
+ }
2774
+
2721
2775
// Otherwise, we have a failure.
2722
2776
return _fail (src, srcType, targetType, flags);
2723
2777
}
0 commit comments