File tree Expand file tree Collapse file tree 4 files changed +55
-1
lines changed Expand file tree Collapse file tree 4 files changed +55
-1
lines changed Original file line number Diff line number Diff line change @@ -752,6 +752,10 @@ class alignas(1 << TypeAlignInBits) TypeBase
752
752
return getRecursiveProperties ().hasOpenedExistential ();
753
753
}
754
754
755
+ // / True if this type is an existential or an archetype which may be an
756
+ // / existential.
757
+ bool canBeExistential ();
758
+
755
759
// / Determine whether the type involves an opened element archetype.
756
760
bool hasElementArchetype () const {
757
761
return getRecursiveProperties ().hasElementArchetype ();
Original file line number Diff line number Diff line change @@ -616,6 +616,29 @@ bool TypeBase::isTypeVariableOrMember() {
616
616
return getDependentMemberRoot ()->is <TypeVariableType>();
617
617
}
618
618
619
+ bool TypeBase::canBeExistential () {
620
+ if (isAnyExistentialType ())
621
+ return true ;
622
+
623
+ Type ty (this );
624
+ // Unwrap (potentially multiple levels of) metatypes.
625
+ while (auto *mt = ty->getAs <MetatypeType>())
626
+ ty = mt->getInstanceType ();
627
+
628
+ if (auto *archeTy = ty->getAs <ArchetypeType>()) {
629
+ // Only if all conformances are self-conforming protocols, the archetype
630
+ // may be an existential.
631
+ for (auto *proto : archeTy->getConformsTo ()) {
632
+ if (!proto->existentialConformsToSelf ())
633
+ return false ;
634
+ }
635
+ // If there are no requirements on the archetype at all (`getConformsTo`
636
+ // is empty), the archetype can still be `Any` and we have to return true.
637
+ return true ;
638
+ }
639
+ return false ;
640
+ }
641
+
619
642
bool TypeBase::isTypeParameter () {
620
643
return getDependentMemberRoot ()->is <GenericTypeParamType>();
621
644
}
Original file line number Diff line number Diff line change @@ -1450,7 +1450,7 @@ static bool optimizeStaticallyKnownProtocolConformance(
1450
1450
auto &Mod = Inst->getModule ();
1451
1451
1452
1452
if (TargetType->isAnyExistentialType () &&
1453
- !SourceType->isAnyExistentialType ()) {
1453
+ !SourceType->canBeExistential ()) {
1454
1454
auto &Ctx = Mod.getASTContext ();
1455
1455
1456
1456
auto *Proto = dyn_cast_or_null<ProtocolDecl>(TargetType->getAnyNominal ());
Original file line number Diff line number Diff line change @@ -1425,6 +1425,33 @@ bb0(%0 : $*Error, %1 : $*E1):
1425
1425
return %2 : $()
1426
1426
}
1427
1427
1428
+ // CHECK-LABEL: sil [ossa] @generic_to_existential_cast
1429
+ // CHECK: init_existential_addr
1430
+ // CHECK: } // end sil function 'generic_to_existential_cast'
1431
+ sil [ossa] @generic_to_existential_cast : $@convention(thin) <T where T : P> (@in_guaranteed T) -> @out any P {
1432
+ bb0(%0: $*any P, %1 : $*T):
1433
+ %29 = alloc_stack $T
1434
+ copy_addr %1 to [init] %29
1435
+ unconditional_checked_cast_addr T in %29 to any P in %0
1436
+ dealloc_stack %29
1437
+ %10 = tuple ()
1438
+ return %10
1439
+ }
1440
+
1441
+ // CHECK-LABEL: sil [ossa] @existential_generic_to_existential_cast
1442
+ // CHECK: unconditional_checked_cast_addr
1443
+ // CHECK: } // end sil function 'existential_generic_to_existential_cast'
1444
+ sil [ossa] @existential_generic_to_existential_cast : $@convention(thin) <T where T : Error> (@in_guaranteed T) -> @owned any Error {
1445
+ bb0(%0 : $*T):
1446
+ %29 = alloc_stack $T
1447
+ copy_addr %0 to [init] %29
1448
+ %31 = alloc_stack $any Error
1449
+ unconditional_checked_cast_addr T in %29 to any Error in %31
1450
+ %33 = load [take] %31
1451
+ dealloc_stack %31
1452
+ dealloc_stack %29
1453
+ return %33
1454
+ }
1428
1455
// Test constant folding of Builtin.globalStringTablePointer.
1429
1456
1430
1457
// CHECK-LABEL: sil @replace_global_string_table_pointer
You can’t perform that action at this time.
0 commit comments