Skip to content

Commit ae77d6f

Browse files
committed
AST: Replace one-off predicates with SubstitutionMap::getRecursiveProperties()
1 parent e27f195 commit ae77d6f

15 files changed

+46
-89
lines changed

include/swift/AST/SubstitutionMap.h

+2-13
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ namespace swift {
3434

3535
class GenericEnvironment;
3636
class GenericParamList;
37+
class RecursiveTypeProperties;
3738
class SubstitutableType;
3839
typedef CanTypeWrapper<GenericTypeParamType> CanGenericTypeParamType;
3940

@@ -150,19 +151,7 @@ class SubstitutionMap {
150151
/// parameters.
151152
ArrayRef<Type> getInnermostReplacementTypes() const;
152153

153-
/// Query whether any replacement types in the map contain archetypes.
154-
bool hasArchetypes() const;
155-
156-
/// Query whether any replacement types in the map contain an opened
157-
/// existential or opened element.
158-
bool hasLocalArchetypes() const;
159-
160-
/// Query whether any replacement types in the map contain an opaque
161-
/// return type.
162-
bool hasOpaqueArchetypes() const;
163-
164-
/// Query whether any replacement types in the map contain dynamic Self.
165-
bool hasDynamicSelf() const;
154+
RecursiveTypeProperties getRecursiveProperties() const;
166155

167156
/// Whether the replacement types are all canonical.
168157
bool isCanonical() const;

include/swift/AST/Types.h

+6-3
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,11 @@ class RecursiveTypeProperties {
246246
/// they have a type variable originator.
247247
bool isSolverAllocated() const { return Bits & SolverAllocated; }
248248

249+
/// Determine whether the type involves a primary, pack or local archetype.
250+
bool hasArchetype() const {
251+
return hasPrimaryArchetype() || hasLocalArchetype();
252+
}
253+
249254
/// Does a type with these properties structurally contain a local
250255
/// archetype?
251256
bool hasLocalArchetype() const {
@@ -720,10 +725,8 @@ class alignas(1 << TypeAlignInBits) TypeBase
720725
}
721726

722727
/// Determine whether the type involves a primary, pack or local archetype.
723-
///
724-
/// FIXME: Replace all remaining callers with a more precise check.
725728
bool hasArchetype() const {
726-
return hasPrimaryArchetype() || hasLocalArchetype();
729+
return getRecursiveProperties().hasArchetype();
727730
}
728731

729732
/// Determine whether the type involves an opened existential archetype.

include/swift/SIL/SILCloner.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -520,13 +520,13 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
520520

521521
SubstitutionMap remapSubstitutionMap(SubstitutionMap Subs) {
522522
// If we have local archetypes to substitute, do so now.
523-
if (Subs.hasLocalArchetypes() || Functor.SubsMap)
523+
if (Subs.getRecursiveProperties().hasLocalArchetype() || Functor.SubsMap)
524524
Subs = Subs.subst(Functor, Functor);
525525

526526
if (asImpl().shouldSubstOpaqueArchetypes()) {
527527
auto context = getBuilder().getTypeExpansionContext();
528528

529-
if (!Subs.hasOpaqueArchetypes() ||
529+
if (!Subs.getRecursiveProperties().hasOpaqueArchetype() ||
530530
!context.shouldLookThroughOpaqueTypeArchetypes())
531531
return Subs;
532532

include/swift/SIL/TypeSubstCloner.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
366366
if (!RemappedSig || !OriginalEnvironment)
367367
return ParentFunction;
368368

369-
if (SubsMap.hasArchetypes())
369+
if (SubsMap.getRecursiveProperties().hasPrimaryArchetype())
370370
SubsMap = SubsMap.mapReplacementTypesOutOfContext();
371371

372372
// One abstract function in the debug info can only have one set of variables
@@ -379,7 +379,7 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
379379
// Note that mapReplacementTypesOutOfContext() can't do anything for
380380
// opened existentials, and since archetypes can't be mangled, ignore
381381
// this case for now.
382-
if (SubsMap.hasArchetypes())
382+
if (SubsMap.getRecursiveProperties().hasLocalArchetype())
383383
return ParentFunction;
384384

385385
// Clone the function with the substituted type for the debug info.

lib/AST/ASTContext.cpp

+6-22
Original file line numberDiff line numberDiff line change
@@ -3322,9 +3322,7 @@ TypeAliasType *TypeAliasType::get(TypeAliasDecl *typealias, Type parent,
33223322
auto properties = underlying->getRecursiveProperties();
33233323
if (parent)
33243324
properties |= parent->getRecursiveProperties();
3325-
3326-
for (auto substGP : substitutions.getReplacementTypes())
3327-
properties |= substGP->getRecursiveProperties();
3325+
properties |= substitutions.getRecursiveProperties();
33283326

33293327
// Figure out which arena this type will go into.
33303328
auto &ctx = underlying->getASTContext();
@@ -4936,7 +4934,7 @@ SILFunctionType::SILFunctionType(
49364934
}
49374935

49384936
if (genericSig && patternSubs) {
4939-
assert(!patternSubs.hasArchetypes()
4937+
assert(!patternSubs.getRecursiveProperties().hasArchetype()
49404938
&& "pattern substitutions should not contain context archetypes");
49414939
}
49424940
}
@@ -5093,9 +5091,7 @@ CanSILFunctionType SILFunctionType::get(
50935091
}
50945092

50955093
auto outerSubs = genericSig ? invocationSubs : patternSubs;
5096-
for (auto replacement : outerSubs.getReplacementTypes()) {
5097-
properties |= replacement->getRecursiveProperties();
5098-
}
5094+
properties |= outerSubs.getRecursiveProperties();
50995095

51005096
auto fnType =
51015097
new (mem) SILFunctionType(genericSig, ext, coroutineKind, callee,
@@ -5282,15 +5278,9 @@ DependentMemberType *DependentMemberType::get(Type base,
52825278
/// Compute the recursive type properties of an opaque type archetype.
52835279
static RecursiveTypeProperties getOpaqueTypeArchetypeProperties(
52845280
SubstitutionMap subs) {
5285-
// An opaque type isn't contextually dependent like other archetypes, so
5286-
// by itself, it doesn't impose the "Has Archetype" recursive property,
5287-
// but the substituted types might. A disjoint "Has Opaque Archetype" tracks
5288-
// the presence of opaque archetypes.
52895281
RecursiveTypeProperties properties =
52905282
RecursiveTypeProperties::HasOpaqueArchetype;
5291-
for (auto type : subs.getReplacementTypes()) {
5292-
properties |= type->getRecursiveProperties();
5293-
}
5283+
properties |= subs.getRecursiveProperties();
52945284
return properties;
52955285
}
52965286

@@ -5317,17 +5307,11 @@ Type OpaqueTypeArchetypeType::get(
53175307
return env->getOrCreateArchetypeFromInterfaceType(interfaceType);
53185308
}
53195309

5320-
/// Compute the recursive type properties of an opaque type archetype.
5310+
/// Compute the recursive type properties of an opened existential archetype.
53215311
static RecursiveTypeProperties getOpenedArchetypeProperties(SubstitutionMap subs) {
5322-
// An opaque type isn't contextually dependent like other archetypes, so
5323-
// by itself, it doesn't impose the "Has Archetype" recursive property,
5324-
// but the substituted types might. A disjoint "Has Opaque Archetype" tracks
5325-
// the presence of opaque archetypes.
53265312
RecursiveTypeProperties properties =
53275313
RecursiveTypeProperties::HasOpenedExistential;
5328-
for (auto type : subs.getReplacementTypes()) {
5329-
properties |= type->getRecursiveProperties();
5330-
}
5314+
properties |= subs.getRecursiveProperties();
53315315
return properties;
53325316
}
53335317

lib/AST/SubstitutionMap.cpp

+5-30
Original file line numberDiff line numberDiff line change
@@ -102,36 +102,11 @@ bool SubstitutionMap::hasAnySubstitutableParams() const {
102102
return !genericSig->areAllParamsConcrete();
103103
}
104104

105-
bool SubstitutionMap::hasArchetypes() const {
106-
for (Type replacementTy : getReplacementTypes()) {
107-
if (replacementTy->hasArchetype())
108-
return true;
109-
}
110-
return false;
111-
}
112-
113-
bool SubstitutionMap::hasLocalArchetypes() const {
114-
for (Type replacementTy : getReplacementTypes()) {
115-
if (replacementTy->hasLocalArchetype())
116-
return true;
117-
}
118-
return false;
119-
}
120-
121-
bool SubstitutionMap::hasOpaqueArchetypes() const {
122-
for (Type replacementTy : getReplacementTypes()) {
123-
if (replacementTy->hasOpaqueArchetype())
124-
return true;
125-
}
126-
return false;
127-
}
128-
129-
bool SubstitutionMap::hasDynamicSelf() const {
130-
for (Type replacementTy : getReplacementTypes()) {
131-
if (replacementTy->hasDynamicSelfType())
132-
return true;
133-
}
134-
return false;
105+
RecursiveTypeProperties SubstitutionMap::getRecursiveProperties() const {
106+
RecursiveTypeProperties properties;
107+
for (auto replacementTy : getReplacementTypes())
108+
properties |= replacementTy->getRecursiveProperties();
109+
return properties;
135110
}
136111

137112
bool SubstitutionMap::isCanonical() const {

lib/SILGen/SILGenExpr.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -4215,11 +4215,12 @@ SILGenModule::emitKeyPathComponentForDecl(SILLocation loc,
42154215
// Map the substitutions out of context.
42164216
if (!subs.empty()) {
42174217
externalSubs = subs;
4218-
// If any of the substitutions involve local archetypes, then the
4218+
// If any of the substitutions involve primary archetypes, then the
42194219
// key path pattern needs to capture the generic context, and we need
42204220
// to map the pattern substitutions out of this context.
4221-
if (externalSubs.hasArchetypes()) {
4221+
if (externalSubs.getRecursiveProperties().hasArchetype()) {
42224222
needsGenericContext = true;
4223+
// FIXME: This doesn't do anything for local archetypes!
42234224
externalSubs = externalSubs.mapReplacementTypesOutOfContext();
42244225
}
42254226
}

lib/SILOptimizer/IPO/CapturePropagation.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ CanSILFunctionType getPartialApplyInterfaceResultType(PartialApplyInst *PAI) {
256256
// return signature.
257257
auto FTy = PAI->getType().castTo<SILFunctionType>();
258258
assert(!PAI->hasSubstitutions() ||
259-
!PAI->getSubstitutionMap().hasArchetypes());
259+
!PAI->getSubstitutionMap().getRecursiveProperties().hasArchetype());
260260
FTy = cast<SILFunctionType>(
261261
FTy->mapTypeOutOfContext()->getCanonicalType());
262262
auto NewFTy = FTy;
@@ -512,7 +512,8 @@ bool CapturePropagation::optimizePartialApply(PartialApplyInst *PAI) {
512512
if (SubstF->isExternalDeclaration())
513513
return false;
514514

515-
if (PAI->hasSubstitutions() && PAI->getSubstitutionMap().hasArchetypes()) {
515+
if (PAI->hasSubstitutions() &&
516+
PAI->getSubstitutionMap().getRecursiveProperties().hasArchetype()) {
516517
LLVM_DEBUG(llvm::dbgs()
517518
<< "CapturePropagation: cannot handle partial specialization "
518519
"of partial_apply:\n";

lib/SILOptimizer/IPO/CrossModuleOptimization.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ class InstructionVisitor : public SILCloner<InstructionVisitor> {
164164
}
165165

166166
SubstitutionMap remapSubstitutionMap(SubstitutionMap Subs) {
167-
if (Subs.hasLocalArchetypes())
167+
if (Subs.getRecursiveProperties().hasLocalArchetype())
168168
Subs = Subs.subst(Functor, Functor);
169169

170170
CMS.makeSubstUsableFromInline(Subs);

lib/SILOptimizer/IPO/UsePrespecialized.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,12 @@ bool UsePrespecialized::replaceByPrespecialized(SILFunction &F) {
8585

8686
SubstitutionMap Subs = AI.getSubstitutionMap();
8787

88-
// Bail if any generic type parameters are unbound.
88+
// Bail if the replacement types depend on the callee's generic
89+
// environment.
90+
//
8991
// TODO: Remove this limitation once public partial specializations
9092
// are supported and can be provided by other modules.
91-
if (Subs.hasArchetypes())
93+
if (Subs.getRecursiveProperties().hasArchetype())
9294
continue;
9395

9496
ReabstractionInfo ReInfo(M.getSwiftModule(), M.isWholeModule(), AI,

lib/SILOptimizer/Transforms/PerformanceInliner.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -858,7 +858,7 @@ static std::optional<bool> shouldInlineGeneric(FullApplySite AI,
858858
// If all substitutions are concrete, then there is no need to perform the
859859
// generic inlining. Let the generic specializer create a specialized
860860
// function and then decide if it is beneficial to inline it.
861-
if (!AI.getSubstitutionMap().hasArchetypes())
861+
if (!AI.getSubstitutionMap().getRecursiveProperties().hasArchetype())
862862
return false;
863863

864864
if (Callee->getLoweredFunctionType()->getCoroutineKind() !=

lib/SILOptimizer/Utils/Generics.cpp

+7-5
Original file line numberDiff line numberDiff line change
@@ -473,16 +473,18 @@ bool ReabstractionInfo::prepareAndCheck(ApplySite Apply, SILFunction *Callee,
473473
// Get the original substitution map.
474474
CalleeParamSubMap = ParamSubs;
475475

476+
auto Props = CalleeParamSubMap.getRecursiveProperties();
477+
476478
using namespace OptRemark;
477479
// We do not support partial specialization.
478-
if (!EnablePartialSpecialization && CalleeParamSubMap.hasArchetypes()) {
480+
if (!EnablePartialSpecialization && Props.hasArchetype()) {
479481
LLVM_DEBUG(llvm::dbgs() <<" Partial specialization is not supported.\n");
480482
LLVM_DEBUG(ParamSubs.dump(llvm::dbgs()));
481483
return false;
482484
}
483485

484486
// Perform some checks to see if we need to bail.
485-
if (CalleeParamSubMap.hasDynamicSelf()) {
487+
if (Props.hasDynamicSelf()) {
486488
REMARK_OR_DEBUG(ORE, [&]() {
487489
return RemarkMissed("DynamicSelf", *Apply.getInstruction())
488490
<< IndentDebug(4) << "Cannot specialize with dynamic self";
@@ -709,11 +711,11 @@ bool ReabstractionInfo::canBeSpecialized() const {
709711
}
710712

711713
bool ReabstractionInfo::isFullSpecialization() const {
712-
return !getCalleeParamSubstitutionMap().hasArchetypes();
714+
return !getCalleeParamSubstitutionMap().getRecursiveProperties().hasArchetype();
713715
}
714716

715717
bool ReabstractionInfo::isPartialSpecialization() const {
716-
return getCalleeParamSubstitutionMap().hasArchetypes();
718+
return getCalleeParamSubstitutionMap().getRecursiveProperties().hasArchetype();
717719
}
718720

719721
void ReabstractionInfo::createSubstitutedAndSpecializedTypes() {
@@ -2819,7 +2821,7 @@ static bool createPrespecialized(StringRef UnspecializedName,
28192821
/// @_semantics("prespecialize.X") attributes.
28202822
static bool createPrespecializations(ApplySite Apply, SILFunction *ProxyFunc,
28212823
SILOptFunctionBuilder &FuncBuilder) {
2822-
if (Apply.getSubstitutionMap().hasArchetypes())
2824+
if (Apply.getSubstitutionMap().getRecursiveProperties().hasArchetype())
28232825
return false;
28242826

28252827
SILModule &M = FuncBuilder.getModule();

lib/Sema/CodeSynthesis.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -768,7 +768,7 @@ createDesignatedInitOverride(ClassDecl *classDecl,
768768
auto genericSig = ctx.getOverrideGenericSignature(
769769
superclassDecl, classDecl, superclassCtorSig, genericParams);
770770

771-
assert(!subMap.hasArchetypes());
771+
assert(!subMap.getRecursiveProperties().hasArchetype());
772772

773773
if (superclassCtorSig) {
774774
auto *genericEnv = genericSig.getGenericEnvironment();

lib/Sema/MiscDiagnostics.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -3693,7 +3693,7 @@ class OpaqueUnderlyingTypeChecker : public ASTWalker {
36933693
return Action::Stop();
36943694
}
36953695

3696-
if (subMap.hasDynamicSelf()) {
3696+
if (subMap.getRecursiveProperties().hasDynamicSelf()) {
36973697
Ctx.Diags.diagnose(E->getLoc(),
36983698
diag::opaque_type_cannot_contain_dynamic_self);
36993699
HasInvalidReturn = true;

lib/Serialization/Serialization.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -1800,9 +1800,9 @@ void Serializer::writeLocalNormalProtocolConformance(
18001800
// Map archetypes to type parameters, since we always substitute them
18011801
// away. Note that in a merge-modules pass, we're serializing conformances
18021802
// that we deserialized, so they will already have their replacement types
1803-
// in terms of interface types; hence the hasArchetypes() check is
1803+
// in terms of interface types; hence the hasPrimaryArchetype() check is
18041804
// necessary for correctness, not just as a fast path.
1805-
if (subs.hasArchetypes())
1805+
if (subs.getRecursiveProperties().hasPrimaryArchetype())
18061806
subs = subs.mapReplacementTypesOutOfContext();
18071807

18081808
data.push_back(addSubstitutionMapRef(subs));

0 commit comments

Comments
 (0)