Skip to content

Commit 29876fd

Browse files
authored
Merge pull request #80137 from eeckstein/fix-cast-optimizer
CastOptimizer: fix optimization of casts from non-existentials to existentials
2 parents c044360 + 2126401 commit 29876fd

File tree

4 files changed

+55
-1
lines changed

4 files changed

+55
-1
lines changed

include/swift/AST/Types.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,10 @@ class alignas(1 << TypeAlignInBits) TypeBase
752752
return getRecursiveProperties().hasOpenedExistential();
753753
}
754754

755+
/// True if this type is an existential or an archetype which may be an
756+
/// existential.
757+
bool canBeExistential();
758+
755759
/// Determine whether the type involves an opened element archetype.
756760
bool hasElementArchetype() const {
757761
return getRecursiveProperties().hasElementArchetype();

lib/AST/Type.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,29 @@ bool TypeBase::isTypeVariableOrMember() {
616616
return getDependentMemberRoot()->is<TypeVariableType>();
617617
}
618618

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+
619642
bool TypeBase::isTypeParameter() {
620643
return getDependentMemberRoot()->is<GenericTypeParamType>();
621644
}

lib/SILOptimizer/Utils/CastOptimizer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1450,7 +1450,7 @@ static bool optimizeStaticallyKnownProtocolConformance(
14501450
auto &Mod = Inst->getModule();
14511451

14521452
if (TargetType->isAnyExistentialType() &&
1453-
!SourceType->isAnyExistentialType()) {
1453+
!SourceType->canBeExistential()) {
14541454
auto &Ctx = Mod.getASTContext();
14551455

14561456
auto *Proto = dyn_cast_or_null<ProtocolDecl>(TargetType->getAnyNominal());

test/SILOptimizer/constant_propagation.sil

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1425,6 +1425,33 @@ bb0(%0 : $*Error, %1 : $*E1):
14251425
return %2 : $()
14261426
}
14271427

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+
}
14281455
// Test constant folding of Builtin.globalStringTablePointer.
14291456

14301457
// CHECK-LABEL: sil @replace_global_string_table_pointer

0 commit comments

Comments
 (0)