@@ -4598,17 +4598,22 @@ EnumImplStrategy *EnumImplStrategy::get(TypeConverter &TC,
4598
4598
std::vector<Element> elementsWithPayload;
4599
4599
std::vector<Element> elementsWithNoPayload;
4600
4600
4601
- // The most general resilience scope that can have knowledge of this
4602
- // enum's layout. If all payload types have a fixed size in this
4603
- // resilience scope, we can make further assumptions to optimize
4604
- // layout.
4605
- ResilienceScope scope = ResilienceScope::Universal;
4606
-
4607
- // TODO: Replace this with 'public or internal with @availability' check
4608
- // once that is in place
4609
- if (theEnum->getFormalAccess () != Accessibility::Public ||
4610
- TC.IGM .isResilient (theEnum, ResilienceScope::Universal))
4611
- scope = ResilienceScope::Component;
4601
+ // Resilient enums are manipulated as opaque values, except we still
4602
+ // make the following assumptions:
4603
+ // 1) Physical case indices won't change
4604
+ // 2) The indirect-ness of cases won't change
4605
+ // 3) Payload types won't change in a non-resilient way
4606
+ bool isResilient = TC.IGM .isResilient (theEnum, ResilienceScope::Component);
4607
+
4608
+ // The most general resilience scope where the enum type is visible.
4609
+ // Case numbering must not depend on any information that is not static
4610
+ // in this resilience scope.
4611
+ ResilienceScope accessScope = TC.IGM .getResilienceScopeForAccess (theEnum);
4612
+
4613
+ // The most general resilience scope where the enum's layout is known.
4614
+ // Fixed-size optimizations can be applied if all payload types are
4615
+ // fixed-size from this resilience scope.
4616
+ ResilienceScope layoutScope = TC.IGM .getResilienceScopeForLayout (theEnum);
4612
4617
4613
4618
for (auto elt : theEnum->getAllElements ()) {
4614
4619
numElements++;
@@ -4638,14 +4643,20 @@ EnumImplStrategy *EnumImplStrategy::get(TypeConverter &TC,
4638
4643
= TC.tryGetCompleteTypeInfo (origArgLoweredTy.getSwiftRValueType ());
4639
4644
assert (origArgTI && " didn't complete type info?!" );
4640
4645
4641
- // If the unsubstituted argument contains a generic parameter type, or if
4642
- // the substituted argument is not universally fixed-size, we need to
4643
- // constrain our layout optimizations to what the runtime can reproduce.
4644
- if (!origArgTI->isFixedSize (scope))
4646
+ // If the unsubstituted argument contains a generic parameter type, or
4647
+ // is not fixed-size in all resilience domains that have knowledge of
4648
+ // this enum's layout, we need to constrain our layout optimizations to
4649
+ // what the runtime can reproduce.
4650
+ if (!isResilient &&
4651
+ !origArgTI->isFixedSize (layoutScope))
4645
4652
alwaysFixedSize = IsNotFixedSize;
4646
4653
4647
- auto loadableOrigArgTI = dyn_cast<LoadableTypeInfo>(origArgTI);
4648
- if (loadableOrigArgTI && loadableOrigArgTI->isKnownEmpty ()) {
4654
+ // If the payload is empty, turn the case into a no-payload case, but
4655
+ // only if case numbering remains unchanged from all resilience domains
4656
+ // that can see the enum.
4657
+ if (origArgTI->isFixedSize (accessScope) &&
4658
+ isa<LoadableTypeInfo>(origArgTI) &&
4659
+ cast<LoadableTypeInfo>(origArgTI)->isKnownEmpty ()) {
4649
4660
elementsWithNoPayload.push_back ({elt, nullptr , nullptr });
4650
4661
} else {
4651
4662
// *Now* apply the substitutions and get the type info for the instance's
@@ -4655,16 +4666,20 @@ EnumImplStrategy *EnumImplStrategy::get(TypeConverter &TC,
4655
4666
auto *substArgTI = &TC.IGM .getTypeInfo (fieldTy);
4656
4667
4657
4668
elementsWithPayload.push_back ({elt, substArgTI, origArgTI});
4658
- if (!substArgTI->isFixedSize ())
4659
- tik = Opaque;
4660
- else if (!substArgTI->isLoadable () && tik > Fixed)
4661
- tik = Fixed;
4662
4669
4663
- // If the substituted argument contains a type that is not universally
4664
- // fixed-size, we need to constrain our layout optimizations to what
4665
- // the runtime can reproduce.
4666
- if (!substArgTI->isFixedSize (scope))
4667
- alwaysFixedSize = IsNotFixedSize;
4670
+ if (!isResilient) {
4671
+ if (!substArgTI->isFixedSize (ResilienceScope::Component))
4672
+ tik = Opaque;
4673
+ else if (!substArgTI->isLoadable () && tik > Fixed)
4674
+ tik = Fixed;
4675
+
4676
+ // If the substituted argument contains a type that is not fixed-size
4677
+ // in all resilience domains that have knowledge of this enum's layout,
4678
+ // we need to constrain our layout optimizations to what the runtime
4679
+ // can reproduce.
4680
+ if (!substArgTI->isFixedSize (layoutScope))
4681
+ alwaysFixedSize = IsNotFixedSize;
4682
+ }
4668
4683
}
4669
4684
}
4670
4685
@@ -4673,12 +4688,7 @@ EnumImplStrategy *EnumImplStrategy::get(TypeConverter &TC,
4673
4688
+ elementsWithNoPayload.size ()
4674
4689
&& " not all elements accounted for" );
4675
4690
4676
- // Resilient enums are manipulated as opaque values, except we still
4677
- // make the following assumptions:
4678
- // 1) Physical case indices won't change
4679
- // 2) The indirect-ness of cases won't change
4680
- // 3) Payload types won't change in a non-resilient way
4681
- if (TC.IGM .isResilient (theEnum, ResilienceScope::Component)) {
4691
+ if (isResilient) {
4682
4692
return new ResilientEnumImplStrategy (TC.IGM ,
4683
4693
numElements,
4684
4694
std::move (elementsWithPayload),
0 commit comments