@@ -2670,8 +2670,10 @@ ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution(
2670
2670
2671
2671
static Type
2672
2672
substOpaqueTypesWithUnderlyingTypes (Type ty, const DeclContext *inContext,
2673
- ResilienceExpansion contextExpansion) {
2674
- ReplaceOpaqueTypesWithUnderlyingTypes replacer (inContext, contextExpansion);
2673
+ ResilienceExpansion contextExpansion,
2674
+ bool isWholeModuleContext) {
2675
+ ReplaceOpaqueTypesWithUnderlyingTypes replacer (inContext, contextExpansion,
2676
+ isWholeModuleContext);
2675
2677
return ty.subst (replacer, replacer, SubstFlags::SubstituteOpaqueArchetypes);
2676
2678
}
2677
2679
@@ -2682,7 +2684,8 @@ substOpaqueTypesWithUnderlyingTypes(Type ty, const DeclContext *inContext,
2682
2684
// / will be accessible. It's not intended to enforce any rules about what
2683
2685
// / opaque substitutions are or are not allowed.
2684
2686
static bool canSubstituteTypeInto (Type ty, const DeclContext *dc,
2685
- OpaqueSubstitutionKind kind) {
2687
+ OpaqueSubstitutionKind kind,
2688
+ bool isContextWholeModule) {
2686
2689
auto nominal = ty->getAnyNominal ();
2687
2690
if (!nominal)
2688
2691
return true ;
@@ -2695,6 +2698,10 @@ static bool canSubstituteTypeInto(Type ty, const DeclContext *dc,
2695
2698
return true ;
2696
2699
2697
2700
case OpaqueSubstitutionKind::SubstituteSameModuleMaximalResilience:
2701
+ // In whole module compilation private types are okay.
2702
+ if (isContextWholeModule)
2703
+ return true ;
2704
+
2698
2705
// In the same file any visibility is okay.
2699
2706
if (!dc->isModuleContext () &&
2700
2707
nominal->getDeclContext ()->getParentSourceFile () ==
@@ -2739,27 +2746,39 @@ operator()(SubstitutableType *maybeOpaqueType) const {
2739
2746
// Check that we are allowed to substitute the underlying type into the
2740
2747
// context.
2741
2748
auto inContext = this ->inContext ;
2742
- if (substTy.findIf ([inContext, substitutionKind](Type t) -> bool {
2743
- if (!canSubstituteTypeInto (t, inContext, substitutionKind))
2744
- return true ;
2745
- return false ;
2746
- }))
2749
+ auto isContextWholeModule = this ->isContextWholeModule ;
2750
+ if (substTy.findIf (
2751
+ [inContext, substitutionKind, isContextWholeModule](Type t) -> bool {
2752
+ if (!canSubstituteTypeInto (t, inContext, substitutionKind,
2753
+ isContextWholeModule))
2754
+ return true ;
2755
+ return false ;
2756
+ }))
2747
2757
return maybeOpaqueType;
2748
2758
2749
2759
// If the type still contains opaque types, recur.
2750
2760
if (substTy->hasOpaqueArchetype ()) {
2751
- return substOpaqueTypesWithUnderlyingTypes (substTy, inContext,
2752
- contextExpansion);
2761
+ return :: substOpaqueTypesWithUnderlyingTypes (
2762
+ substTy, inContext, contextExpansion, isContextWholeModule );
2753
2763
}
2754
2764
2755
2765
return substTy;
2756
2766
}
2757
2767
2758
- static ProtocolConformanceRef
2759
- substOpaqueTypesWithUnderlyingTypes (ProtocolConformanceRef ref, Type origType,
2760
- const DeclContext *inContext,
2761
- ResilienceExpansion contextExpansion) {
2762
- ReplaceOpaqueTypesWithUnderlyingTypes replacer (inContext, contextExpansion);
2768
+ static ProtocolConformanceRef substOpaqueTypesWithUnderlyingTypes (
2769
+ ProtocolConformanceRef ref, Type origType, const DeclContext *inContext,
2770
+ ResilienceExpansion contextExpansion, bool isWholeModuleContext) {
2771
+ ReplaceOpaqueTypesWithUnderlyingTypes replacer (inContext, contextExpansion,
2772
+ isWholeModuleContext);
2773
+ return ref.subst (origType, replacer, replacer,
2774
+ SubstFlags::SubstituteOpaqueArchetypes);
2775
+ }
2776
+
2777
+ ProtocolConformanceRef swift::substOpaqueTypesWithUnderlyingTypes (
2778
+ ProtocolConformanceRef ref, Type origType, TypeExpansionContext context) {
2779
+ ReplaceOpaqueTypesWithUnderlyingTypes replacer (
2780
+ context.getContext (), context.getResilienceExpansion (),
2781
+ context.isWholeModuleContext ());
2763
2782
return ref.subst (origType, replacer, replacer,
2764
2783
SubstFlags::SubstituteOpaqueArchetypes);
2765
2784
}
@@ -2804,20 +2823,23 @@ operator()(CanType maybeOpaqueType, Type replacementType,
2804
2823
// Check that we are allowed to substitute the underlying type into the
2805
2824
// context.
2806
2825
auto inContext = this ->inContext ;
2807
- if (substTy.findIf ([inContext, substitutionKind](Type t) -> bool {
2808
- if (!canSubstituteTypeInto (t, inContext, substitutionKind))
2809
- return true ;
2810
- return false ;
2811
- }))
2826
+ auto isContextWholeModule = this ->isContextWholeModule ;
2827
+ if (substTy.findIf (
2828
+ [inContext, substitutionKind, isContextWholeModule](Type t) -> bool {
2829
+ if (!canSubstituteTypeInto (t, inContext, substitutionKind,
2830
+ isContextWholeModule))
2831
+ return true ;
2832
+ return false ;
2833
+ }))
2812
2834
return abstractRef;
2813
2835
2814
2836
auto substRef =
2815
2837
partialSubstRef.subst (partialSubstTy, opaqueRoot->getSubstitutions ());
2816
2838
2817
2839
// If the type still contains opaque types, recur.
2818
2840
if (substTy->hasOpaqueArchetype ()) {
2819
- return substOpaqueTypesWithUnderlyingTypes (substRef, substTy, inContext,
2820
- contextExpansion);
2841
+ return :: substOpaqueTypesWithUnderlyingTypes (
2842
+ substRef, substTy, inContext, contextExpansion, isContextWholeModule );
2821
2843
}
2822
2844
return substRef;
2823
2845
}
@@ -3436,6 +3458,11 @@ static Type substType(Type derivedType,
3436
3458
3437
3459
// If we have a substitution for this type, use it.
3438
3460
if (auto known = substitutions (substOrig)) {
3461
+ if (options.contains (SubstFlags::SubstituteOpaqueArchetypes) &&
3462
+ isa<OpaqueTypeArchetypeType>(substOrig) &&
3463
+ known->getCanonicalType () == substOrig->getCanonicalType ())
3464
+ return None; // Recursively process the substitutions of the opaque type
3465
+ // archetype.
3439
3466
return known;
3440
3467
}
3441
3468
@@ -4612,3 +4639,42 @@ Type TypeBase::openAnyExistentialType(OpenedArchetypeType *&opened) {
4612
4639
opened = OpenedArchetypeType::get (this );
4613
4640
return opened;
4614
4641
}
4642
+
4643
+ bool TypeBase::hasOpaqueArchetypePropertiesOrCases () {
4644
+ if (hasOpaqueArchetype ())
4645
+ return true ;
4646
+
4647
+ if (auto *structDecl = getStructOrBoundGenericStruct ()) {
4648
+ for (auto *field : structDecl->getStoredProperties ()) {
4649
+ auto fieldTy = field->getInterfaceType ();
4650
+ if (fieldTy->getCanonicalType ()->hasOpaqueArchetypePropertiesOrCases ())
4651
+ return true ;
4652
+ }
4653
+ }
4654
+
4655
+ if (auto *enumDecl = getEnumOrBoundGenericEnum ()) {
4656
+ for (auto *elt : enumDecl->getAllElements ()) {
4657
+ auto eltType = elt->getInterfaceType ();
4658
+ if (eltType->getCanonicalType ()->hasOpaqueArchetypePropertiesOrCases ())
4659
+ return true ;
4660
+ }
4661
+ }
4662
+ return false ;
4663
+ }
4664
+
4665
+ CanType swift::substOpaqueTypesWithUnderlyingTypes (CanType ty,
4666
+ TypeExpansionContext context,
4667
+ bool allowLoweredTypes) {
4668
+ if (!context.shouldLookThroughOpaqueTypeArchetypes () ||
4669
+ !ty->hasOpaqueArchetype ())
4670
+ return ty;
4671
+
4672
+ ReplaceOpaqueTypesWithUnderlyingTypes replacer (
4673
+ context.getContext (), context.getResilienceExpansion (),
4674
+ context.isWholeModuleContext ());
4675
+ SubstOptions flags = SubstFlags::SubstituteOpaqueArchetypes;
4676
+ if (allowLoweredTypes)
4677
+ flags =
4678
+ SubstFlags::SubstituteOpaqueArchetypes | SubstFlags::AllowLoweredTypes;
4679
+ return ty.subst (replacer, replacer, flags)->getCanonicalType ();
4680
+ }
0 commit comments