@@ -250,6 +250,59 @@ static bool canDynamicallyBeOptionalType(CanType type) {
250
250
&& !type.isAnyClassReferenceType ();
251
251
}
252
252
253
+ // / Given two class types, check whether there's a hierarchy relationship
254
+ // / between them.
255
+ static DynamicCastFeasibility
256
+ classifyClassHierarchyCast (CanType source, CanType target) {
257
+ // Upcast: if the target type statically matches a type in the
258
+ // source type's hierarchy, this is a static upcast and the cast
259
+ // will always succeed.
260
+ if (target->isExactSuperclassOf (source, nullptr ))
261
+ return DynamicCastFeasibility::WillSucceed;
262
+
263
+ // Upcast: if the target type might dynamically match a type in the
264
+ // source type's hierarchy, this might be an upcast, in which
265
+ // case the cast might succeed.
266
+ if (target->isBindableToSuperclassOf (source, nullptr ))
267
+ return DynamicCastFeasibility::MaySucceed;
268
+
269
+ // Downcast: if the source type might dynamically match a type in the
270
+ // target type's hierarchy, this might be a downcast, in which case
271
+ // the cast might succeed. Note that this also covers the case where
272
+ // the source type statically matches a type in the target type's
273
+ // hierarchy; since it's a downcast, the cast still at best might succeed.
274
+ if (source->isBindableToSuperclassOf (target, nullptr ))
275
+ return DynamicCastFeasibility::MaySucceed;
276
+
277
+ // Otherwise, the classes are unrelated and the cast will fail (at least
278
+ // on these grounds).
279
+ return DynamicCastFeasibility::WillFail;
280
+ }
281
+
282
+ static CanType getNSBridgedClassOfCFClass (Module *M, CanType type) {
283
+ if (auto classDecl = type->getClassOrBoundGenericClass ()) {
284
+ if (classDecl->getForeignClassKind () == ClassDecl::ForeignKind::CFType) {
285
+ if (auto bridgedAttr =
286
+ classDecl->getAttrs ().getAttribute <ObjCBridgedAttr>()) {
287
+ auto bridgedClass = bridgedAttr->getObjCClass ();
288
+ // TODO: this should handle generic classes properly.
289
+ if (!bridgedClass->isGenericContext ()) {
290
+ return bridgedClass->getDeclaredInterfaceType ()->getCanonicalType ();
291
+ }
292
+ }
293
+ }
294
+ }
295
+ return CanType ();
296
+ }
297
+
298
+ static bool isCFBridgingConversion (Module *M, SILType sourceType,
299
+ SILType targetType) {
300
+ return (sourceType.getSwiftRValueType () ==
301
+ getNSBridgedClassOfCFClass (M, targetType.getSwiftRValueType ()) ||
302
+ targetType.getSwiftRValueType () ==
303
+ getNSBridgedClassOfCFClass (M, sourceType.getSwiftRValueType ()));
304
+ }
305
+
253
306
// / Try to classify the dynamic-cast relationship between two types.
254
307
DynamicCastFeasibility
255
308
swift::classifyDynamicCast (Module *M,
@@ -311,6 +364,30 @@ swift::classifyDynamicCast(Module *M,
311
364
return DynamicCastFeasibility::MaySucceed;
312
365
}
313
366
367
+ // Casts from AnyHashable.
368
+ if (auto sourceStruct = dyn_cast<StructType>(source)) {
369
+ if (sourceStruct->getDecl () == M->getASTContext ().getAnyHashableDecl ()) {
370
+ if (auto hashable = getHashableExistentialType (M)) {
371
+ // Succeeds if Hashable can be cast to the target type.
372
+ return classifyDynamicCastFromProtocol (M, hashable, target,
373
+ isWholeModuleOpts);
374
+ }
375
+ }
376
+ }
377
+
378
+ // Casts to AnyHashable.
379
+ if (auto targetStruct = dyn_cast<StructType>(target)) {
380
+ if (targetStruct->getDecl () == M->getASTContext ().getAnyHashableDecl ()) {
381
+ // Succeeds if the source type can be dynamically cast to Hashable.
382
+ // Hashable is not actually a legal existential type right now, but
383
+ // the check doesn't care about that.
384
+ if (auto hashable = getHashableExistentialType (M)) {
385
+ return classifyDynamicCastToProtocol (source, hashable,
386
+ isWholeModuleOpts);
387
+ }
388
+ }
389
+ }
390
+
314
391
// Metatype casts.
315
392
if (auto sourceMetatype = dyn_cast<AnyMetatypeType>(source)) {
316
393
auto targetMetatype = dyn_cast<AnyMetatypeType>(target);
@@ -369,7 +446,7 @@ swift::classifyDynamicCast(Module *M,
369
446
// cast.
370
447
if (source.getClassOrBoundGenericClass () &&
371
448
target.getClassOrBoundGenericClass ())
372
- return classifyDynamicCast (M, source, target, false , isWholeModuleOpts );
449
+ return classifyClassHierarchyCast ( source, target);
373
450
374
451
// Different structs cannot be cast to each other.
375
452
if (source.getStructOrBoundGenericStruct () &&
@@ -386,7 +463,7 @@ swift::classifyDynamicCast(Module *M,
386
463
// If we don't know any better, assume that the cast may succeed.
387
464
return DynamicCastFeasibility::MaySucceed;
388
465
}
389
-
466
+
390
467
// Function casts.
391
468
if (auto sourceFunction = dyn_cast<FunctionType>(source)) {
392
469
if (auto targetFunction = dyn_cast<FunctionType>(target)) {
@@ -457,16 +534,25 @@ swift::classifyDynamicCast(Module *M,
457
534
}
458
535
}
459
536
537
+ // Try a hierarchy cast. If that isn't failure, we can report it.
538
+ auto hierarchyResult = classifyClassHierarchyCast (source, target);
539
+ if (hierarchyResult != DynamicCastFeasibility::WillFail)
540
+ return hierarchyResult;
460
541
461
- if (target->isExactSuperclassOf (source, nullptr ))
462
- return DynamicCastFeasibility::WillSucceed;
463
- if (target->isBindableToSuperclassOf (source, nullptr ))
464
- return DynamicCastFeasibility::MaySucceed;
465
- if (source->isBindableToSuperclassOf (target, nullptr ))
466
- return DynamicCastFeasibility::MaySucceed;
542
+ // As a backup, consider whether either type is a CF class type
543
+ // with an NS bridged equivalent.
544
+ CanType bridgedSource = getNSBridgedClassOfCFClass (M, source);
545
+ CanType bridgedTarget = getNSBridgedClassOfCFClass (M, target);
467
546
468
- // FIXME: bridged types, e.g. CF <-> NS (but not for metatypes).
469
- return DynamicCastFeasibility::WillFail;
547
+ // If neither type qualifies, we're done.
548
+ if (!bridgedSource && !bridgedTarget)
549
+ return DynamicCastFeasibility::WillFail;
550
+
551
+ // Otherwise, map over to the bridged types and try to answer the
552
+ // question there.
553
+ if (bridgedSource) source = bridgedSource;
554
+ if (bridgedTarget) target = bridgedTarget;
555
+ return classifyDynamicCast (M, source, target, false , isWholeModuleOpts);
470
556
}
471
557
472
558
// Casts from a class into a non-class can never succeed if the target must
@@ -599,30 +685,6 @@ swift::classifyDynamicCast(Module *M,
599
685
}
600
686
}
601
687
602
- // Casts from AnyHashable.
603
- if (auto sourceStruct = dyn_cast<StructType>(source)) {
604
- if (sourceStruct->getDecl () == M->getASTContext ().getAnyHashableDecl ()) {
605
- if (auto hashable = getHashableExistentialType (M)) {
606
- // Succeeds if Hashable can be cast to the target type.
607
- return classifyDynamicCastFromProtocol (M, hashable, target,
608
- isWholeModuleOpts);
609
- }
610
- }
611
- }
612
-
613
- // Casts to AnyHashable.
614
- if (auto targetStruct = dyn_cast<StructType>(target)) {
615
- if (targetStruct->getDecl () == M->getASTContext ().getAnyHashableDecl ()) {
616
- // Succeeds if the source type can be dynamically cast to Hashable.
617
- // Hashable is not actually a legal existential type right now, but
618
- // the check doesn't care about that.
619
- if (auto hashable = getHashableExistentialType (M)) {
620
- return classifyDynamicCastToProtocol (source, hashable,
621
- isWholeModuleOpts);
622
- }
623
- }
624
- }
625
-
626
688
return DynamicCastFeasibility::WillFail;
627
689
}
628
690
@@ -685,9 +747,11 @@ namespace {
685
747
SILModule &M;
686
748
ASTContext &Ctx;
687
749
SILLocation Loc;
750
+ Module *SwiftModule;
688
751
public:
689
752
CastEmitter (SILBuilder &B, Module *swiftModule, SILLocation loc)
690
- : B(B), M(B.getModule()), Ctx(M.getASTContext()), Loc(loc) {}
753
+ : B(B), M(B.getModule()), Ctx(M.getASTContext()), Loc(loc),
754
+ SwiftModule (swiftModule) {}
691
755
692
756
Source emitTopLevel (Source source, Target target) {
693
757
unsigned sourceOptDepth = getOptionalDepth (source.FormalType );
@@ -768,8 +832,8 @@ namespace {
768
832
}
769
833
assert (!target.FormalType .getAnyOptionalObjectType ());
770
834
771
- // The only other thing we return WillSucceed for currently is
772
- // an upcast.
835
+ // The only other things we return WillSucceed for currently is
836
+ // an upcast or CF/NS toll-free-bridging conversion .
773
837
// FIXME: Upcasts between existential metatypes are not handled yet.
774
838
// We should generate for it:
775
839
// %openedSrcMetatype = open_existential srcMetatype
@@ -781,7 +845,12 @@ namespace {
781
845
} else {
782
846
value = getOwnedScalar (source, srcTL);
783
847
}
784
- value = B.createUpcast (Loc, value, target.LoweredType .getObjectType ());
848
+ auto targetTy = target.LoweredType ;
849
+ if (isCFBridgingConversion (SwiftModule, targetTy, value->getType ())) {
850
+ value = B.createUncheckedRefCast (Loc, value, targetTy.getObjectType ());
851
+ } else {
852
+ value = B.createUpcast (Loc, value, targetTy.getObjectType ());
853
+ }
785
854
return putOwnedScalar (value, target);
786
855
}
787
856
0 commit comments