Skip to content

Commit da0099e

Browse files
Merge pull request swiftlang#27666 from aschwaighofer/fix_replace_opaque_types_with_underlying
ReplaceOpaqueTypesWithUnderlyingTypes: We can't look through opaque archetypes if the underlying type contains a type not accessible from the current context
2 parents 2e969d2 + 3ca0859 commit da0099e

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
@@ -4876,17 +4876,33 @@ class OpaqueTypeArchetypeType final : public ArchetypeType,
48764876
BEGIN_CAN_TYPE_WRAPPER(OpaqueTypeArchetypeType, ArchetypeType)
48774877
END_CAN_TYPE_WRAPPER(OpaqueTypeArchetypeType, ArchetypeType)
48784878

4879+
enum OpaqueSubstitutionKind {
4880+
// Don't substitute the opaque type for the underlying type.
4881+
DontSubstitute,
4882+
// Substitute without looking at the type and context.
4883+
// Can be done because the underlying type is from a minimally resilient
4884+
// function (therefore must not contain private or internal types).
4885+
AlwaysSubstitute,
4886+
// Substitute in the same module into a maximal resilient context.
4887+
// Can be done if the underlying type is accessible from the context we
4888+
// substitute into. Private types cannot be accesses from a different TU.
4889+
SubstituteSameModuleMaximalResilience,
4890+
// Substitute in a different module from the opaque definining decl. Can only
4891+
// be done if the underlying type is public.
4892+
SubstituteNonResilientModule
4893+
};
4894+
48794895
/// A function object that can be used as a \c TypeSubstitutionFn and
48804896
/// \c LookupConformanceFn for \c Type::subst style APIs to map opaque
48814897
/// archetypes with underlying types visible at a given resilience expansion
48824898
/// to their underlying types.
48834899
class ReplaceOpaqueTypesWithUnderlyingTypes {
48844900
public:
4885-
ModuleDecl *contextModule;
4901+
DeclContext *inContext;
48864902
ResilienceExpansion contextExpansion;
4887-
ReplaceOpaqueTypesWithUnderlyingTypes(ModuleDecl *contextModule,
4903+
ReplaceOpaqueTypesWithUnderlyingTypes(DeclContext *inContext,
48884904
ResilienceExpansion contextExpansion)
4889-
: contextModule(contextModule), contextExpansion(contextExpansion) {}
4905+
: inContext(inContext), contextExpansion(contextExpansion) {}
48904906

48914907
/// TypeSubstitutionFn
48924908
Type operator()(SubstitutableType *maybeOpaqueType) const;
@@ -4896,11 +4912,12 @@ class ReplaceOpaqueTypesWithUnderlyingTypes {
48964912
Type replacementType,
48974913
ProtocolDecl *protocol) const;
48984914

4899-
bool shouldPerformSubstitution(OpaqueTypeDecl *opaque) const;
4915+
OpaqueSubstitutionKind
4916+
shouldPerformSubstitution(OpaqueTypeDecl *opaque) const;
49004917

4901-
static bool shouldPerformSubstitution(OpaqueTypeDecl *opaque,
4902-
ModuleDecl *contextModule,
4903-
ResilienceExpansion contextExpansion);
4918+
static OpaqueSubstitutionKind
4919+
shouldPerformSubstitution(OpaqueTypeDecl *opaque, ModuleDecl *contextModule,
4920+
ResilienceExpansion contextExpansion);
49044921
};
49054922

49064923
/// 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
@@ -2601,31 +2601,33 @@ getArchetypeAndRootOpaqueArchetype(Type maybeOpaqueType) {
26012601
return std::make_pair(archetype, opaqueRoot);
26022602
}
26032603

2604-
bool ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution(
2604+
OpaqueSubstitutionKind
2605+
ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution(
26052606
OpaqueTypeDecl *opaque) const {
2606-
return shouldPerformSubstitution(opaque, contextModule, contextExpansion);
2607+
return shouldPerformSubstitution(opaque, inContext->getParentModule(),
2608+
contextExpansion);
26072609
}
2608-
2609-
bool ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution(
2610+
OpaqueSubstitutionKind
2611+
ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution(
26102612
OpaqueTypeDecl *opaque, ModuleDecl *contextModule,
26112613
ResilienceExpansion contextExpansion) {
26122614
auto namingDecl = opaque->getNamingDecl();
26132615

26142616
// Don't allow replacement if the naming decl is dynamically replaceable.
26152617
if (namingDecl && namingDecl->isDynamic())
2616-
return false;
2618+
return OpaqueSubstitutionKind::DontSubstitute;
26172619

26182620
// Allow replacement of opaque result types of inlineable function regardless
26192621
// of resilience and in which context.
26202622
if (auto *afd = dyn_cast<AbstractFunctionDecl>(namingDecl)) {
26212623
if (afd->getResilienceExpansion() == ResilienceExpansion::Minimal) {
2622-
return true;
2624+
return OpaqueSubstitutionKind::AlwaysSubstitute;
26232625
}
26242626
} else if (auto *asd = dyn_cast<AbstractStorageDecl>(namingDecl)) {
26252627
auto *getter = asd->getOpaqueAccessor(AccessorKind::Get);
26262628
if (getter &&
26272629
getter->getResilienceExpansion() == ResilienceExpansion::Minimal) {
2628-
return true;
2630+
return OpaqueSubstitutionKind::AlwaysSubstitute;
26292631
}
26302632
}
26312633

@@ -2635,20 +2637,49 @@ bool ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution(
26352637
auto module = namingDecl->getModuleContext();
26362638
if (contextExpansion == ResilienceExpansion::Maximal &&
26372639
module == contextModule)
2638-
return true;
2640+
return OpaqueSubstitutionKind::SubstituteSameModuleMaximalResilience;
26392641

26402642
// 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;
26422647
}
26432648

26442649
static Type
2645-
substOpaqueTypesWithUnderlyingTypes(Type ty, ModuleDecl *contextModule,
2650+
substOpaqueTypesWithUnderlyingTypes(Type ty, DeclContext *inContext,
26462651
ResilienceExpansion contextExpansion) {
2647-
ReplaceOpaqueTypesWithUnderlyingTypes replacer(contextModule,
2648-
contextExpansion);
2652+
ReplaceOpaqueTypesWithUnderlyingTypes replacer(inContext, contextExpansion);
26492653
return ty.subst(replacer, replacer, SubstFlags::SubstituteOpaqueArchetypes);
26502654
}
26512655

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+
26522683
Type ReplaceOpaqueTypesWithUnderlyingTypes::
26532684
operator()(SubstitutableType *maybeOpaqueType) const {
26542685
auto archetypeAndRoot = getArchetypeAndRootOpaqueArchetype(maybeOpaqueType);
@@ -2658,7 +2689,8 @@ operator()(SubstitutableType *maybeOpaqueType) const {
26582689
auto archetype = archetypeAndRoot->first;
26592690
auto opaqueRoot = archetypeAndRoot->second;
26602691

2661-
if (!shouldPerformSubstitution(opaqueRoot->getDecl())) {
2692+
auto substitutionKind = shouldPerformSubstitution(opaqueRoot->getDecl());
2693+
if (substitutionKind == OpaqueSubstitutionKind::DontSubstitute) {
26622694
return maybeOpaqueType;
26632695
}
26642696

@@ -2676,20 +2708,30 @@ operator()(SubstitutableType *maybeOpaqueType) const {
26762708
// for its type arguments.
26772709
auto substTy = partialSubstTy.subst(opaqueRoot->getSubstitutions());
26782710

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+
26792721
// If the type still contains opaque types, recur.
26802722
if (substTy->hasOpaqueArchetype()) {
2681-
return substOpaqueTypesWithUnderlyingTypes(substTy, contextModule,
2723+
return substOpaqueTypesWithUnderlyingTypes(substTy, inContext,
26822724
contextExpansion);
26832725
}
2726+
26842727
return substTy;
26852728
}
26862729

26872730
static ProtocolConformanceRef
26882731
substOpaqueTypesWithUnderlyingTypes(ProtocolConformanceRef ref, Type origType,
2689-
ModuleDecl *contextModule,
2732+
DeclContext *inContext,
26902733
ResilienceExpansion contextExpansion) {
2691-
ReplaceOpaqueTypesWithUnderlyingTypes replacer(contextModule,
2692-
contextExpansion);
2734+
ReplaceOpaqueTypesWithUnderlyingTypes replacer(inContext, contextExpansion);
26932735
return ref.subst(origType, replacer, replacer,
26942736
SubstFlags::SubstituteOpaqueArchetypes);
26952737
}
@@ -2709,7 +2751,8 @@ operator()(CanType maybeOpaqueType, Type replacementType,
27092751
auto archetype = archetypeAndRoot->first;
27102752
auto opaqueRoot = archetypeAndRoot->second;
27112753

2712-
if (!shouldPerformSubstitution(opaqueRoot->getDecl())) {
2754+
auto substitutionKind = shouldPerformSubstitution(opaqueRoot->getDecl());
2755+
if (substitutionKind == OpaqueSubstitutionKind::DontSubstitute) {
27132756
return abstractRef;
27142757
}
27152758

@@ -2729,12 +2772,23 @@ operator()(CanType maybeOpaqueType, Type replacementType,
27292772
// Then apply the substitutions from the root opaque archetype, to specialize
27302773
// for its type arguments.
27312774
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+
27322786
auto substRef =
27332787
partialSubstRef.subst(partialSubstTy, opaqueRoot->getSubstitutions());
27342788

27352789
// If the type still contains opaque types, recur.
27362790
if (substTy->hasOpaqueArchetype()) {
2737-
return substOpaqueTypesWithUnderlyingTypes(substRef, substTy, contextModule,
2791+
return substOpaqueTypesWithUnderlyingTypes(substRef, substTy, inContext,
27382792
contextExpansion);
27392793
}
27402794
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)