@@ -2570,31 +2570,33 @@ getArchetypeAndRootOpaqueArchetype(Type maybeOpaqueType) {
2570
2570
return std::make_pair (archetype, opaqueRoot);
2571
2571
}
2572
2572
2573
- bool ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution (
2573
+ OpaqueSubstitutionKind
2574
+ ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution (
2574
2575
OpaqueTypeDecl *opaque) const {
2575
- return shouldPerformSubstitution (opaque, contextModule, contextExpansion);
2576
+ return shouldPerformSubstitution (opaque, inContext->getParentModule (),
2577
+ contextExpansion);
2576
2578
}
2577
-
2578
- bool ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution (
2579
+ OpaqueSubstitutionKind
2580
+ ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution (
2579
2581
OpaqueTypeDecl *opaque, ModuleDecl *contextModule,
2580
2582
ResilienceExpansion contextExpansion) {
2581
2583
auto namingDecl = opaque->getNamingDecl ();
2582
2584
2583
2585
// Don't allow replacement if the naming decl is dynamically replaceable.
2584
2586
if (namingDecl && namingDecl->isDynamic ())
2585
- return false ;
2587
+ return OpaqueSubstitutionKind::DontSubstitute ;
2586
2588
2587
2589
// Allow replacement of opaque result types of inlineable function regardless
2588
2590
// of resilience and in which context.
2589
2591
if (auto *afd = dyn_cast<AbstractFunctionDecl>(namingDecl)) {
2590
2592
if (afd->getResilienceExpansion () == ResilienceExpansion::Minimal) {
2591
- return true ;
2593
+ return OpaqueSubstitutionKind::AlwaysSubstitute ;
2592
2594
}
2593
2595
} else if (auto *asd = dyn_cast<AbstractStorageDecl>(namingDecl)) {
2594
2596
auto *getter = asd->getOpaqueAccessor (AccessorKind::Get);
2595
2597
if (getter &&
2596
2598
getter->getResilienceExpansion () == ResilienceExpansion::Minimal) {
2597
- return true ;
2599
+ return OpaqueSubstitutionKind::AlwaysSubstitute ;
2598
2600
}
2599
2601
}
2600
2602
@@ -2604,20 +2606,49 @@ bool ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution(
2604
2606
auto module = namingDecl->getModuleContext ();
2605
2607
if (contextExpansion == ResilienceExpansion::Maximal &&
2606
2608
module == contextModule)
2607
- return true ;
2609
+ return OpaqueSubstitutionKind::SubstituteSameModuleMaximalResilience ;
2608
2610
2609
2611
// Allow general replacement from non resilient modules. Otherwise, disallow.
2610
- return !module ->isResilient ();
2612
+ if (module ->isResilient ())
2613
+ return OpaqueSubstitutionKind::DontSubstitute;
2614
+
2615
+ return OpaqueSubstitutionKind::SubstituteNonResilientModule;
2611
2616
}
2612
2617
2613
2618
static Type
2614
- substOpaqueTypesWithUnderlyingTypes (Type ty, ModuleDecl *contextModule ,
2619
+ substOpaqueTypesWithUnderlyingTypes (Type ty, DeclContext *inContext ,
2615
2620
ResilienceExpansion contextExpansion) {
2616
- ReplaceOpaqueTypesWithUnderlyingTypes replacer (contextModule,
2617
- contextExpansion);
2621
+ ReplaceOpaqueTypesWithUnderlyingTypes replacer (inContext, contextExpansion);
2618
2622
return ty.subst (replacer, replacer, SubstFlags::SubstituteOpaqueArchetypes);
2619
2623
}
2620
2624
2625
+ bool canSubstituteTypeInto (Type ty, DeclContext *dc,
2626
+ OpaqueSubstitutionKind kind) {
2627
+ auto nominal = ty->getAnyNominal ();
2628
+ if (!nominal)
2629
+ return true ;
2630
+
2631
+ switch (kind) {
2632
+ case DontSubstitute:
2633
+ return false ;
2634
+
2635
+ case AlwaysSubstitute:
2636
+ return true ;
2637
+
2638
+ case SubstituteSameModuleMaximalResilience:
2639
+ // In the same file any visibility is okay.
2640
+ if (!dc->isModuleContext () &&
2641
+ nominal->getDeclContext ()->getParentSourceFile () ==
2642
+ dc->getParentSourceFile ())
2643
+ return true ;
2644
+ return nominal->getEffectiveAccess () > AccessLevel::FilePrivate;
2645
+
2646
+ case SubstituteNonResilientModule:
2647
+ // Can't access types that are not public from a different module.
2648
+ return nominal->getEffectiveAccess () > AccessLevel::Internal;
2649
+ }
2650
+ }
2651
+
2621
2652
Type ReplaceOpaqueTypesWithUnderlyingTypes::
2622
2653
operator ()(SubstitutableType *maybeOpaqueType) const {
2623
2654
auto archetypeAndRoot = getArchetypeAndRootOpaqueArchetype (maybeOpaqueType);
@@ -2627,7 +2658,8 @@ operator()(SubstitutableType *maybeOpaqueType) const {
2627
2658
auto archetype = archetypeAndRoot->first ;
2628
2659
auto opaqueRoot = archetypeAndRoot->second ;
2629
2660
2630
- if (!shouldPerformSubstitution (opaqueRoot->getDecl ())) {
2661
+ auto substitutionKind = shouldPerformSubstitution (opaqueRoot->getDecl ());
2662
+ if (substitutionKind == OpaqueSubstitutionKind::DontSubstitute) {
2631
2663
return maybeOpaqueType;
2632
2664
}
2633
2665
@@ -2645,20 +2677,30 @@ operator()(SubstitutableType *maybeOpaqueType) const {
2645
2677
// for its type arguments.
2646
2678
auto substTy = partialSubstTy.subst (opaqueRoot->getSubstitutions ());
2647
2679
2680
+ // Check that we are allowed to substitute the underlying type into the
2681
+ // context.
2682
+ auto inContext = this ->inContext ;
2683
+ if (substTy.findIf ([inContext, substitutionKind](Type t) -> bool {
2684
+ if (!canSubstituteTypeInto (t, inContext, substitutionKind))
2685
+ return true ;
2686
+ return false ;
2687
+ }))
2688
+ return maybeOpaqueType;
2689
+
2648
2690
// If the type still contains opaque types, recur.
2649
2691
if (substTy->hasOpaqueArchetype ()) {
2650
- return substOpaqueTypesWithUnderlyingTypes (substTy, contextModule ,
2692
+ return substOpaqueTypesWithUnderlyingTypes (substTy, inContext ,
2651
2693
contextExpansion);
2652
2694
}
2695
+
2653
2696
return substTy;
2654
2697
}
2655
2698
2656
2699
static ProtocolConformanceRef
2657
2700
substOpaqueTypesWithUnderlyingTypes (ProtocolConformanceRef ref, Type origType,
2658
- ModuleDecl *contextModule ,
2701
+ DeclContext *inContext ,
2659
2702
ResilienceExpansion contextExpansion) {
2660
- ReplaceOpaqueTypesWithUnderlyingTypes replacer (contextModule,
2661
- contextExpansion);
2703
+ ReplaceOpaqueTypesWithUnderlyingTypes replacer (inContext, contextExpansion);
2662
2704
return ref.subst (origType, replacer, replacer,
2663
2705
SubstFlags::SubstituteOpaqueArchetypes);
2664
2706
}
@@ -2678,7 +2720,8 @@ operator()(CanType maybeOpaqueType, Type replacementType,
2678
2720
auto archetype = archetypeAndRoot->first ;
2679
2721
auto opaqueRoot = archetypeAndRoot->second ;
2680
2722
2681
- if (!shouldPerformSubstitution (opaqueRoot->getDecl ())) {
2723
+ auto substitutionKind = shouldPerformSubstitution (opaqueRoot->getDecl ());
2724
+ if (substitutionKind == OpaqueSubstitutionKind::DontSubstitute) {
2682
2725
return abstractRef;
2683
2726
}
2684
2727
@@ -2698,12 +2741,23 @@ operator()(CanType maybeOpaqueType, Type replacementType,
2698
2741
// Then apply the substitutions from the root opaque archetype, to specialize
2699
2742
// for its type arguments.
2700
2743
auto substTy = partialSubstTy.subst (opaqueRoot->getSubstitutions ());
2744
+
2745
+ // Check that we are allowed to substitute the underlying type into the
2746
+ // context.
2747
+ auto inContext = this ->inContext ;
2748
+ if (substTy.findIf ([inContext, substitutionKind](Type t) -> bool {
2749
+ if (!canSubstituteTypeInto (t, inContext, substitutionKind))
2750
+ return true ;
2751
+ return false ;
2752
+ }))
2753
+ return abstractRef;
2754
+
2701
2755
auto substRef =
2702
2756
partialSubstRef.subst (partialSubstTy, opaqueRoot->getSubstitutions ());
2703
2757
2704
2758
// If the type still contains opaque types, recur.
2705
2759
if (substTy->hasOpaqueArchetype ()) {
2706
- return substOpaqueTypesWithUnderlyingTypes (substRef, substTy, contextModule ,
2760
+ return substOpaqueTypesWithUnderlyingTypes (substRef, substTy, inContext ,
2707
2761
contextExpansion);
2708
2762
}
2709
2763
return substRef;
0 commit comments