@@ -2601,31 +2601,33 @@ getArchetypeAndRootOpaqueArchetype(Type maybeOpaqueType) {
2601
2601
return std::make_pair (archetype, opaqueRoot);
2602
2602
}
2603
2603
2604
- bool ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution (
2604
+ OpaqueSubstitutionKind
2605
+ ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution (
2605
2606
OpaqueTypeDecl *opaque) const {
2606
- return shouldPerformSubstitution (opaque, contextModule, contextExpansion);
2607
+ return shouldPerformSubstitution (opaque, inContext->getParentModule (),
2608
+ contextExpansion);
2607
2609
}
2608
-
2609
- bool ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution (
2610
+ OpaqueSubstitutionKind
2611
+ ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution (
2610
2612
OpaqueTypeDecl *opaque, ModuleDecl *contextModule,
2611
2613
ResilienceExpansion contextExpansion) {
2612
2614
auto namingDecl = opaque->getNamingDecl ();
2613
2615
2614
2616
// Don't allow replacement if the naming decl is dynamically replaceable.
2615
2617
if (namingDecl && namingDecl->isDynamic ())
2616
- return false ;
2618
+ return OpaqueSubstitutionKind::DontSubstitute ;
2617
2619
2618
2620
// Allow replacement of opaque result types of inlineable function regardless
2619
2621
// of resilience and in which context.
2620
2622
if (auto *afd = dyn_cast<AbstractFunctionDecl>(namingDecl)) {
2621
2623
if (afd->getResilienceExpansion () == ResilienceExpansion::Minimal) {
2622
- return true ;
2624
+ return OpaqueSubstitutionKind::AlwaysSubstitute ;
2623
2625
}
2624
2626
} else if (auto *asd = dyn_cast<AbstractStorageDecl>(namingDecl)) {
2625
2627
auto *getter = asd->getOpaqueAccessor (AccessorKind::Get);
2626
2628
if (getter &&
2627
2629
getter->getResilienceExpansion () == ResilienceExpansion::Minimal) {
2628
- return true ;
2630
+ return OpaqueSubstitutionKind::AlwaysSubstitute ;
2629
2631
}
2630
2632
}
2631
2633
@@ -2635,20 +2637,49 @@ bool ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution(
2635
2637
auto module = namingDecl->getModuleContext ();
2636
2638
if (contextExpansion == ResilienceExpansion::Maximal &&
2637
2639
module == contextModule)
2638
- return true ;
2640
+ return OpaqueSubstitutionKind::SubstituteSameModuleMaximalResilience ;
2639
2641
2640
2642
// Allow general replacement from non resilient modules. Otherwise, disallow.
2641
- return !module ->isResilient ();
2643
+ if (module ->isResilient ())
2644
+ return OpaqueSubstitutionKind::DontSubstitute;
2645
+
2646
+ return OpaqueSubstitutionKind::SubstituteNonResilientModule;
2642
2647
}
2643
2648
2644
2649
static Type
2645
- substOpaqueTypesWithUnderlyingTypes (Type ty, ModuleDecl *contextModule ,
2650
+ substOpaqueTypesWithUnderlyingTypes (Type ty, DeclContext *inContext ,
2646
2651
ResilienceExpansion contextExpansion) {
2647
- ReplaceOpaqueTypesWithUnderlyingTypes replacer (contextModule,
2648
- contextExpansion);
2652
+ ReplaceOpaqueTypesWithUnderlyingTypes replacer (inContext, contextExpansion);
2649
2653
return ty.subst (replacer, replacer, SubstFlags::SubstituteOpaqueArchetypes);
2650
2654
}
2651
2655
2656
+ bool canSubstituteTypeInto (Type ty, DeclContext *dc,
2657
+ OpaqueSubstitutionKind kind) {
2658
+ auto nominal = ty->getAnyNominal ();
2659
+ if (!nominal)
2660
+ return true ;
2661
+
2662
+ switch (kind) {
2663
+ case DontSubstitute:
2664
+ return false ;
2665
+
2666
+ case AlwaysSubstitute:
2667
+ return true ;
2668
+
2669
+ case SubstituteSameModuleMaximalResilience:
2670
+ // In the same file any visibility is okay.
2671
+ if (!dc->isModuleContext () &&
2672
+ nominal->getDeclContext ()->getParentSourceFile () ==
2673
+ dc->getParentSourceFile ())
2674
+ return true ;
2675
+ return nominal->getEffectiveAccess () > AccessLevel::FilePrivate;
2676
+
2677
+ case SubstituteNonResilientModule:
2678
+ // Can't access types that are not public from a different module.
2679
+ return nominal->getEffectiveAccess () > AccessLevel::Internal;
2680
+ }
2681
+ }
2682
+
2652
2683
Type ReplaceOpaqueTypesWithUnderlyingTypes::
2653
2684
operator ()(SubstitutableType *maybeOpaqueType) const {
2654
2685
auto archetypeAndRoot = getArchetypeAndRootOpaqueArchetype (maybeOpaqueType);
@@ -2658,7 +2689,8 @@ operator()(SubstitutableType *maybeOpaqueType) const {
2658
2689
auto archetype = archetypeAndRoot->first ;
2659
2690
auto opaqueRoot = archetypeAndRoot->second ;
2660
2691
2661
- if (!shouldPerformSubstitution (opaqueRoot->getDecl ())) {
2692
+ auto substitutionKind = shouldPerformSubstitution (opaqueRoot->getDecl ());
2693
+ if (substitutionKind == OpaqueSubstitutionKind::DontSubstitute) {
2662
2694
return maybeOpaqueType;
2663
2695
}
2664
2696
@@ -2676,20 +2708,30 @@ operator()(SubstitutableType *maybeOpaqueType) const {
2676
2708
// for its type arguments.
2677
2709
auto substTy = partialSubstTy.subst (opaqueRoot->getSubstitutions ());
2678
2710
2711
+ // Check that we are allowed to substitute the underlying type into the
2712
+ // context.
2713
+ auto inContext = this ->inContext ;
2714
+ if (substTy.findIf ([inContext, substitutionKind](Type t) -> bool {
2715
+ if (!canSubstituteTypeInto (t, inContext, substitutionKind))
2716
+ return true ;
2717
+ return false ;
2718
+ }))
2719
+ return maybeOpaqueType;
2720
+
2679
2721
// If the type still contains opaque types, recur.
2680
2722
if (substTy->hasOpaqueArchetype ()) {
2681
- return substOpaqueTypesWithUnderlyingTypes (substTy, contextModule ,
2723
+ return substOpaqueTypesWithUnderlyingTypes (substTy, inContext ,
2682
2724
contextExpansion);
2683
2725
}
2726
+
2684
2727
return substTy;
2685
2728
}
2686
2729
2687
2730
static ProtocolConformanceRef
2688
2731
substOpaqueTypesWithUnderlyingTypes (ProtocolConformanceRef ref, Type origType,
2689
- ModuleDecl *contextModule ,
2732
+ DeclContext *inContext ,
2690
2733
ResilienceExpansion contextExpansion) {
2691
- ReplaceOpaqueTypesWithUnderlyingTypes replacer (contextModule,
2692
- contextExpansion);
2734
+ ReplaceOpaqueTypesWithUnderlyingTypes replacer (inContext, contextExpansion);
2693
2735
return ref.subst (origType, replacer, replacer,
2694
2736
SubstFlags::SubstituteOpaqueArchetypes);
2695
2737
}
@@ -2709,7 +2751,8 @@ operator()(CanType maybeOpaqueType, Type replacementType,
2709
2751
auto archetype = archetypeAndRoot->first ;
2710
2752
auto opaqueRoot = archetypeAndRoot->second ;
2711
2753
2712
- if (!shouldPerformSubstitution (opaqueRoot->getDecl ())) {
2754
+ auto substitutionKind = shouldPerformSubstitution (opaqueRoot->getDecl ());
2755
+ if (substitutionKind == OpaqueSubstitutionKind::DontSubstitute) {
2713
2756
return abstractRef;
2714
2757
}
2715
2758
@@ -2729,12 +2772,23 @@ operator()(CanType maybeOpaqueType, Type replacementType,
2729
2772
// Then apply the substitutions from the root opaque archetype, to specialize
2730
2773
// for its type arguments.
2731
2774
auto substTy = partialSubstTy.subst (opaqueRoot->getSubstitutions ());
2775
+
2776
+ // Check that we are allowed to substitute the underlying type into the
2777
+ // context.
2778
+ auto inContext = this ->inContext ;
2779
+ if (substTy.findIf ([inContext, substitutionKind](Type t) -> bool {
2780
+ if (!canSubstituteTypeInto (t, inContext, substitutionKind))
2781
+ return true ;
2782
+ return false ;
2783
+ }))
2784
+ return abstractRef;
2785
+
2732
2786
auto substRef =
2733
2787
partialSubstRef.subst (partialSubstTy, opaqueRoot->getSubstitutions ());
2734
2788
2735
2789
// If the type still contains opaque types, recur.
2736
2790
if (substTy->hasOpaqueArchetype ()) {
2737
- return substOpaqueTypesWithUnderlyingTypes (substRef, substTy, contextModule ,
2791
+ return substOpaqueTypesWithUnderlyingTypes (substRef, substTy, inContext ,
2738
2792
contextExpansion);
2739
2793
}
2740
2794
return substRef;
0 commit comments