Skip to content

Commit b75691c

Browse files
committed
ReplaceOpaqueTypesWithUnderlyingTypes: We can't look through opaque archetypes if the underlying type contains a type not accessible from the current context
We can't access types in the same module if they are private: they could be in a different TU. We can't access types from different modules if they are private or internal. Some more information can be gleaned from the resilience expansion: A minimally resilient function can't reference private or internal types. rdar://56093964
1 parent 7032e65 commit b75691c

File tree

7 files changed

+234
-45
lines changed

7 files changed

+234
-45
lines changed

include/swift/AST/Types.h

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4864,17 +4864,33 @@ class OpaqueTypeArchetypeType final : public ArchetypeType,
48644864
BEGIN_CAN_TYPE_WRAPPER(OpaqueTypeArchetypeType, ArchetypeType)
48654865
END_CAN_TYPE_WRAPPER(OpaqueTypeArchetypeType, ArchetypeType)
48664866

4867+
enum OpaqueSubstitutionKind {
4868+
// Don't substitute the opaque type for the underlying type.
4869+
DontSubstitute,
4870+
// Substitute without looking at the type and context.
4871+
// Can be done because the underlying type is from a minimally resilient
4872+
// function (therefore must not contain private or internal types).
4873+
AlwaysSubstitute,
4874+
// Substitute in the same module into a maximal resilient context.
4875+
// Can be done if the underlying type is accessible from the context we
4876+
// substitute into. Private types cannot be accesses from a different TU.
4877+
SubstituteSameModuleMaximalResilience,
4878+
// Substitute in a different module from the opaque definining decl. Can only
4879+
// be done if the underlying type is public.
4880+
SubstituteNonResilientModule
4881+
};
4882+
48674883
/// A function object that can be used as a \c TypeSubstitutionFn and
48684884
/// \c LookupConformanceFn for \c Type::subst style APIs to map opaque
48694885
/// archetypes with underlying types visible at a given resilience expansion
48704886
/// to their underlying types.
48714887
class ReplaceOpaqueTypesWithUnderlyingTypes {
48724888
public:
4873-
ModuleDecl *contextModule;
4889+
DeclContext *inContext;
48744890
ResilienceExpansion contextExpansion;
4875-
ReplaceOpaqueTypesWithUnderlyingTypes(ModuleDecl *contextModule,
4891+
ReplaceOpaqueTypesWithUnderlyingTypes(DeclContext *inContext,
48764892
ResilienceExpansion contextExpansion)
4877-
: contextModule(contextModule), contextExpansion(contextExpansion) {}
4893+
: inContext(inContext), contextExpansion(contextExpansion) {}
48784894

48794895
/// TypeSubstitutionFn
48804896
Type operator()(SubstitutableType *maybeOpaqueType) const;
@@ -4884,11 +4900,12 @@ class ReplaceOpaqueTypesWithUnderlyingTypes {
48844900
Type replacementType,
48854901
ProtocolDecl *protocol) const;
48864902

4887-
bool shouldPerformSubstitution(OpaqueTypeDecl *opaque) const;
4903+
OpaqueSubstitutionKind
4904+
shouldPerformSubstitution(OpaqueTypeDecl *opaque) const;
48884905

4889-
static bool shouldPerformSubstitution(OpaqueTypeDecl *opaque,
4890-
ModuleDecl *contextModule,
4891-
ResilienceExpansion contextExpansion);
4906+
static OpaqueSubstitutionKind
4907+
shouldPerformSubstitution(OpaqueTypeDecl *opaque, ModuleDecl *contextModule,
4908+
ResilienceExpansion contextExpansion);
48924909
};
48934910

48944911
/// An archetype that represents the dynamic type of an opened existential.

lib/AST/Type.cpp

Lines changed: 73 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2570,31 +2570,33 @@ getArchetypeAndRootOpaqueArchetype(Type maybeOpaqueType) {
25702570
return std::make_pair(archetype, opaqueRoot);
25712571
}
25722572

2573-
bool ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution(
2573+
OpaqueSubstitutionKind
2574+
ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution(
25742575
OpaqueTypeDecl *opaque) const {
2575-
return shouldPerformSubstitution(opaque, contextModule, contextExpansion);
2576+
return shouldPerformSubstitution(opaque, inContext->getParentModule(),
2577+
contextExpansion);
25762578
}
2577-
2578-
bool ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution(
2579+
OpaqueSubstitutionKind
2580+
ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution(
25792581
OpaqueTypeDecl *opaque, ModuleDecl *contextModule,
25802582
ResilienceExpansion contextExpansion) {
25812583
auto namingDecl = opaque->getNamingDecl();
25822584

25832585
// Don't allow replacement if the naming decl is dynamically replaceable.
25842586
if (namingDecl && namingDecl->isDynamic())
2585-
return false;
2587+
return OpaqueSubstitutionKind::DontSubstitute;
25862588

25872589
// Allow replacement of opaque result types of inlineable function regardless
25882590
// of resilience and in which context.
25892591
if (auto *afd = dyn_cast<AbstractFunctionDecl>(namingDecl)) {
25902592
if (afd->getResilienceExpansion() == ResilienceExpansion::Minimal) {
2591-
return true;
2593+
return OpaqueSubstitutionKind::AlwaysSubstitute;
25922594
}
25932595
} else if (auto *asd = dyn_cast<AbstractStorageDecl>(namingDecl)) {
25942596
auto *getter = asd->getOpaqueAccessor(AccessorKind::Get);
25952597
if (getter &&
25962598
getter->getResilienceExpansion() == ResilienceExpansion::Minimal) {
2597-
return true;
2599+
return OpaqueSubstitutionKind::AlwaysSubstitute;
25982600
}
25992601
}
26002602

@@ -2604,20 +2606,49 @@ bool ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution(
26042606
auto module = namingDecl->getModuleContext();
26052607
if (contextExpansion == ResilienceExpansion::Maximal &&
26062608
module == contextModule)
2607-
return true;
2609+
return OpaqueSubstitutionKind::SubstituteSameModuleMaximalResilience;
26082610

26092611
// 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;
26112616
}
26122617

26132618
static Type
2614-
substOpaqueTypesWithUnderlyingTypes(Type ty, ModuleDecl *contextModule,
2619+
substOpaqueTypesWithUnderlyingTypes(Type ty, DeclContext *inContext,
26152620
ResilienceExpansion contextExpansion) {
2616-
ReplaceOpaqueTypesWithUnderlyingTypes replacer(contextModule,
2617-
contextExpansion);
2621+
ReplaceOpaqueTypesWithUnderlyingTypes replacer(inContext, contextExpansion);
26182622
return ty.subst(replacer, replacer, SubstFlags::SubstituteOpaqueArchetypes);
26192623
}
26202624

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+
26212652
Type ReplaceOpaqueTypesWithUnderlyingTypes::
26222653
operator()(SubstitutableType *maybeOpaqueType) const {
26232654
auto archetypeAndRoot = getArchetypeAndRootOpaqueArchetype(maybeOpaqueType);
@@ -2627,7 +2658,8 @@ operator()(SubstitutableType *maybeOpaqueType) const {
26272658
auto archetype = archetypeAndRoot->first;
26282659
auto opaqueRoot = archetypeAndRoot->second;
26292660

2630-
if (!shouldPerformSubstitution(opaqueRoot->getDecl())) {
2661+
auto substitutionKind = shouldPerformSubstitution(opaqueRoot->getDecl());
2662+
if (substitutionKind == OpaqueSubstitutionKind::DontSubstitute) {
26312663
return maybeOpaqueType;
26322664
}
26332665

@@ -2645,20 +2677,30 @@ operator()(SubstitutableType *maybeOpaqueType) const {
26452677
// for its type arguments.
26462678
auto substTy = partialSubstTy.subst(opaqueRoot->getSubstitutions());
26472679

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+
26482690
// If the type still contains opaque types, recur.
26492691
if (substTy->hasOpaqueArchetype()) {
2650-
return substOpaqueTypesWithUnderlyingTypes(substTy, contextModule,
2692+
return substOpaqueTypesWithUnderlyingTypes(substTy, inContext,
26512693
contextExpansion);
26522694
}
2695+
26532696
return substTy;
26542697
}
26552698

26562699
static ProtocolConformanceRef
26572700
substOpaqueTypesWithUnderlyingTypes(ProtocolConformanceRef ref, Type origType,
2658-
ModuleDecl *contextModule,
2701+
DeclContext *inContext,
26592702
ResilienceExpansion contextExpansion) {
2660-
ReplaceOpaqueTypesWithUnderlyingTypes replacer(contextModule,
2661-
contextExpansion);
2703+
ReplaceOpaqueTypesWithUnderlyingTypes replacer(inContext, contextExpansion);
26622704
return ref.subst(origType, replacer, replacer,
26632705
SubstFlags::SubstituteOpaqueArchetypes);
26642706
}
@@ -2678,7 +2720,8 @@ operator()(CanType maybeOpaqueType, Type replacementType,
26782720
auto archetype = archetypeAndRoot->first;
26792721
auto opaqueRoot = archetypeAndRoot->second;
26802722

2681-
if (!shouldPerformSubstitution(opaqueRoot->getDecl())) {
2723+
auto substitutionKind = shouldPerformSubstitution(opaqueRoot->getDecl());
2724+
if (substitutionKind == OpaqueSubstitutionKind::DontSubstitute) {
26822725
return abstractRef;
26832726
}
26842727

@@ -2698,12 +2741,23 @@ operator()(CanType maybeOpaqueType, Type replacementType,
26982741
// Then apply the substitutions from the root opaque archetype, to specialize
26992742
// for its type arguments.
27002743
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+
27012755
auto substRef =
27022756
partialSubstRef.subst(partialSubstTy, opaqueRoot->getSubstitutions());
27032757

27042758
// If the type still contains opaque types, recur.
27052759
if (substTy->hasOpaqueArchetype()) {
2706-
return substOpaqueTypesWithUnderlyingTypes(substRef, substTy, contextModule,
2760+
return substOpaqueTypesWithUnderlyingTypes(substRef, substTy, inContext,
27072761
contextExpansion);
27082762
}
27092763
return substRef;

lib/IRGen/MetadataRequest.cpp

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -518,9 +518,10 @@ CanType IRGenModule::substOpaqueTypesWithUnderlyingTypes(CanType type) {
518518
if (type->hasOpaqueArchetype()) {
519519
ReplaceOpaqueTypesWithUnderlyingTypes replacer(getSwiftModule(),
520520
ResilienceExpansion::Maximal);
521-
type = type.subst(replacer, replacer,
522-
SubstFlags::SubstituteOpaqueArchetypes)
523-
->getCanonicalType();
521+
auto underlyingTy =
522+
type.subst(replacer, replacer, SubstFlags::SubstituteOpaqueArchetypes)
523+
->getCanonicalType();
524+
return underlyingTy;
524525
}
525526

526527
return type;
@@ -533,8 +534,10 @@ SILType IRGenModule::substOpaqueTypesWithUnderlyingTypes(
533534
if (type.getASTType()->hasOpaqueArchetype()) {
534535
ReplaceOpaqueTypesWithUnderlyingTypes replacer(getSwiftModule(),
535536
ResilienceExpansion::Maximal);
536-
type = type.subst(getSILModule(), replacer, replacer, genericSig,
537-
/*substitute opaque*/ true);
537+
auto underlyingTy =
538+
type.subst(getSILModule(), replacer, replacer, genericSig,
539+
/*substitute opaque*/ true);
540+
return underlyingTy;
538541
}
539542

540543
return type;
@@ -548,11 +551,12 @@ IRGenModule::substOpaqueTypesWithUnderlyingTypes(CanType type,
548551
if (type->hasOpaqueArchetype()) {
549552
ReplaceOpaqueTypesWithUnderlyingTypes replacer(getSwiftModule(),
550553
ResilienceExpansion::Maximal);
551-
conformance = conformance.subst(type, replacer, replacer,
552-
SubstFlags::SubstituteOpaqueArchetypes);
553-
type = type.subst(replacer, replacer,
554-
SubstFlags::SubstituteOpaqueArchetypes)
555-
->getCanonicalType();
554+
auto substConformance = conformance.subst(
555+
type, replacer, replacer, SubstFlags::SubstituteOpaqueArchetypes);
556+
auto underlyingTy =
557+
type.subst(replacer, replacer, SubstFlags::SubstituteOpaqueArchetypes)
558+
->getCanonicalType();
559+
return std::make_pair(underlyingTy, substConformance);
556560
}
557561

558562
return std::make_pair(type, conformance);

lib/SIL/SILFunctionType.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2804,9 +2804,11 @@ static bool areABICompatibleParamsOrReturns(SILType a, SILType b,
28042804
// Opaque types are compatible with their substitution.
28052805
if (inFunction) {
28062806
auto opaqueTypesSubsituted = aa;
2807+
auto *dc = inFunction->getDeclContext();
2808+
if (!dc)
2809+
dc = inFunction->getModule().getSwiftModule();
28072810
ReplaceOpaqueTypesWithUnderlyingTypes replacer(
2808-
inFunction->getModule().getSwiftModule(),
2809-
inFunction->getResilienceExpansion());
2811+
dc, inFunction->getResilienceExpansion());
28102812
if (aa.getASTType()->hasOpaqueArchetype())
28112813
opaqueTypesSubsituted = aa.subst(inFunction->getModule(), replacer,
28122814
replacer, CanGenericSignature(), true);

lib/SILOptimizer/Transforms/SpecializeOpaqueArchetypes.cpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,22 @@ using namespace swift;
3333

3434
static Type substOpaqueTypesWithUnderlyingTypes(
3535
Type ty, SILFunction *context) {
36+
auto *dc = context->getDeclContext();
37+
if (!dc)
38+
dc = context->getModule().getSwiftModule();
39+
3640
ReplaceOpaqueTypesWithUnderlyingTypes replacer(
37-
context->getModule().getSwiftModule(), context->getResilienceExpansion());
41+
dc, context->getResilienceExpansion());
3842
return ty.subst(replacer, replacer, SubstFlags::SubstituteOpaqueArchetypes);
3943
}
4044

4145
static SubstitutionMap
4246
substOpaqueTypesWithUnderlyingTypes(SubstitutionMap map, SILFunction *context) {
47+
auto *dc = context->getDeclContext();
48+
if (!dc)
49+
dc = context->getModule().getSwiftModule();
4350
ReplaceOpaqueTypesWithUnderlyingTypes replacer(
44-
context->getModule().getSwiftModule(), context->getResilienceExpansion());
51+
dc, context->getResilienceExpansion());
4552
return map.subst(replacer, replacer, SubstFlags::SubstituteOpaqueArchetypes);
4653
}
4754

@@ -324,11 +331,13 @@ class OpaqueSpecializerCloner
324331
SILType &Sty = TypeCache[Ty];
325332
if (Sty)
326333
return Sty;
334+
auto *dc = Original.getDeclContext();
335+
if (!dc)
336+
dc = Original.getModule().getSwiftModule();
327337

328-
// Apply the opaque types substitution.
338+
// Apply the opaque types substitution.
329339
ReplaceOpaqueTypesWithUnderlyingTypes replacer(
330-
Original.getModule().getSwiftModule(),
331-
Original.getResilienceExpansion());
340+
dc, Original.getResilienceExpansion());
332341
Sty = Ty.subst(Original.getModule(), replacer, replacer,
333342
CanGenericSignature(), true);
334343
return Sty;
@@ -342,10 +351,12 @@ class OpaqueSpecializerCloner
342351

343352
ProtocolConformanceRef remapConformance(Type type,
344353
ProtocolConformanceRef conf) {
354+
auto *dc = Original.getDeclContext();
355+
if (!dc)
356+
dc = Original.getModule().getSwiftModule();
345357
// Apply the opaque types substitution.
346358
ReplaceOpaqueTypesWithUnderlyingTypes replacer(
347-
Original.getModule().getSwiftModule(),
348-
Original.getResilienceExpansion());
359+
dc, Original.getResilienceExpansion());
349360
return conf.subst(type, replacer, replacer,
350361
SubstFlags::SubstituteOpaqueArchetypes);
351362
}
@@ -493,6 +504,9 @@ class OpaqueArchetypeSpecializer : public SILFunctionTransform {
493504

494505
return ty.findIf([=](Type type) -> bool {
495506
if (auto opaqueTy = type->getAs<OpaqueTypeArchetypeType>()) {
507+
auto *dc = context->getDeclContext();
508+
if (!dc)
509+
dc = context->getModule().getSwiftModule();
496510
auto opaque = opaqueTy->getDecl();
497511
return ReplaceOpaqueTypesWithUnderlyingTypes::
498512
shouldPerformSubstitution(opaque,

0 commit comments

Comments
 (0)