Skip to content

Commit 8ec3a77

Browse files
committed
Add TypeExpansionContext to AST substitution functions
Also add hasOpaqueArchetypePropertiesOrCases() this function will be needed by SIL type lowering to determine whether types containing opaque archetype stored properties or cases should be considered as potentially address types.
1 parent f5fe7c1 commit 8ec3a77

File tree

2 files changed

+116
-28
lines changed

2 files changed

+116
-28
lines changed

include/swift/AST/Types.h

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "swift/AST/SubstitutionMap.h"
2828
#include "swift/AST/Type.h"
2929
#include "swift/AST/TypeAlignments.h"
30+
#include "swift/AST/TypeExpansionContext.h"
3031
#include "swift/Basic/ArrayRefView.h"
3132
#include "swift/Basic/Debug.h"
3233
#include "swift/Basic/InlineBitfield.h"
@@ -582,7 +583,10 @@ class alignas(1 << TypeAlignInBits) TypeBase {
582583
bool hasOpaqueArchetype() const {
583584
return getRecursiveProperties().hasOpaqueArchetype();
584585
}
585-
586+
/// Determine whether the type has any stored properties or enum cases that
587+
/// involve an opaque type.
588+
bool hasOpaqueArchetypePropertiesOrCases();
589+
586590
/// Determine whether the type is an opened existential type.
587591
///
588592
/// To determine whether there is an opened existential type
@@ -3687,6 +3691,17 @@ enum class SILCoroutineKind : uint8_t {
36873691

36883692
class SILFunctionConventions;
36893693

3694+
3695+
CanType substOpaqueTypesWithUnderlyingTypes(CanType type,
3696+
TypeExpansionContext context,
3697+
bool allowLoweredTypes = false);
3698+
ProtocolConformanceRef
3699+
substOpaqueTypesWithUnderlyingTypes(ProtocolConformanceRef ref, Type origType,
3700+
TypeExpansionContext context);
3701+
namespace Lowering {
3702+
class TypeConverter;
3703+
};
3704+
36903705
/// SILFunctionType - The lowered type of a function value, suitable
36913706
/// for use by SIL.
36923707
///
@@ -4205,10 +4220,14 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode,
42054220
SILFunction &context) const;
42064221

42074222
CanSILFunctionType substGenericArgs(SILModule &silModule,
4208-
SubstitutionMap subs);
4223+
SubstitutionMap subs,
4224+
TypeExpansionContext context);
42094225
CanSILFunctionType substGenericArgs(SILModule &silModule,
42104226
TypeSubstitutionFn subs,
4211-
LookupConformanceFn conformances);
4227+
LookupConformanceFn conformances,
4228+
TypeExpansionContext context);
4229+
CanSILFunctionType substituteOpaqueArchetypes(Lowering::TypeConverter &TC,
4230+
TypeExpansionContext context);
42124231

42134232
SILType substInterfaceType(SILModule &M,
42144233
SILType interfaceType) const;
@@ -4963,9 +4982,12 @@ class ReplaceOpaqueTypesWithUnderlyingTypes {
49634982
public:
49644983
const DeclContext *inContext;
49654984
ResilienceExpansion contextExpansion;
4985+
bool isContextWholeModule;
49664986
ReplaceOpaqueTypesWithUnderlyingTypes(const DeclContext *inContext,
4967-
ResilienceExpansion contextExpansion)
4968-
: inContext(inContext), contextExpansion(contextExpansion) {}
4987+
ResilienceExpansion contextExpansion,
4988+
bool isWholeModuleContext)
4989+
: inContext(inContext), contextExpansion(contextExpansion),
4990+
isContextWholeModule(isWholeModuleContext) {}
49694991

49704992
/// TypeSubstitutionFn
49714993
Type operator()(SubstitutableType *maybeOpaqueType) const;
@@ -5752,5 +5774,5 @@ struct DenseMapInfo<swift::BuiltinIntegerWidth> {
57525774
};
57535775

57545776
}
5755-
5777+
57565778
#endif

lib/AST/Type.cpp

Lines changed: 88 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2670,8 +2670,10 @@ ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution(
26702670

26712671
static Type
26722672
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);
26752677
return ty.subst(replacer, replacer, SubstFlags::SubstituteOpaqueArchetypes);
26762678
}
26772679

@@ -2682,7 +2684,8 @@ substOpaqueTypesWithUnderlyingTypes(Type ty, const DeclContext *inContext,
26822684
/// will be accessible. It's not intended to enforce any rules about what
26832685
/// opaque substitutions are or are not allowed.
26842686
static bool canSubstituteTypeInto(Type ty, const DeclContext *dc,
2685-
OpaqueSubstitutionKind kind) {
2687+
OpaqueSubstitutionKind kind,
2688+
bool isContextWholeModule) {
26862689
auto nominal = ty->getAnyNominal();
26872690
if (!nominal)
26882691
return true;
@@ -2695,6 +2698,10 @@ static bool canSubstituteTypeInto(Type ty, const DeclContext *dc,
26952698
return true;
26962699

26972700
case OpaqueSubstitutionKind::SubstituteSameModuleMaximalResilience:
2701+
// In whole module compilation private types are okay.
2702+
if (isContextWholeModule)
2703+
return true;
2704+
26982705
// In the same file any visibility is okay.
26992706
if (!dc->isModuleContext() &&
27002707
nominal->getDeclContext()->getParentSourceFile() ==
@@ -2739,27 +2746,39 @@ operator()(SubstitutableType *maybeOpaqueType) const {
27392746
// Check that we are allowed to substitute the underlying type into the
27402747
// context.
27412748
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+
}))
27472757
return maybeOpaqueType;
27482758

27492759
// If the type still contains opaque types, recur.
27502760
if (substTy->hasOpaqueArchetype()) {
2751-
return substOpaqueTypesWithUnderlyingTypes(substTy, inContext,
2752-
contextExpansion);
2761+
return ::substOpaqueTypesWithUnderlyingTypes(
2762+
substTy, inContext, contextExpansion, isContextWholeModule);
27532763
}
27542764

27552765
return substTy;
27562766
}
27572767

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());
27632782
return ref.subst(origType, replacer, replacer,
27642783
SubstFlags::SubstituteOpaqueArchetypes);
27652784
}
@@ -2804,20 +2823,23 @@ operator()(CanType maybeOpaqueType, Type replacementType,
28042823
// Check that we are allowed to substitute the underlying type into the
28052824
// context.
28062825
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+
}))
28122834
return abstractRef;
28132835

28142836
auto substRef =
28152837
partialSubstRef.subst(partialSubstTy, opaqueRoot->getSubstitutions());
28162838

28172839
// If the type still contains opaque types, recur.
28182840
if (substTy->hasOpaqueArchetype()) {
2819-
return substOpaqueTypesWithUnderlyingTypes(substRef, substTy, inContext,
2820-
contextExpansion);
2841+
return ::substOpaqueTypesWithUnderlyingTypes(
2842+
substRef, substTy, inContext, contextExpansion, isContextWholeModule);
28212843
}
28222844
return substRef;
28232845
}
@@ -3436,6 +3458,11 @@ static Type substType(Type derivedType,
34363458

34373459
// If we have a substitution for this type, use it.
34383460
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.
34393466
return known;
34403467
}
34413468

@@ -4612,3 +4639,42 @@ Type TypeBase::openAnyExistentialType(OpenedArchetypeType *&opened) {
46124639
opened = OpenedArchetypeType::get(this);
46134640
return opened;
46144641
}
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

Comments
 (0)