Skip to content

Commit 7912b1d

Browse files
committed
AST: Introduce SubstFlags::SubstituteLocalArchetypes
1 parent 6f08e08 commit 7912b1d

File tree

15 files changed

+140
-71
lines changed

15 files changed

+140
-71
lines changed

include/swift/AST/InFlightSubstitution.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,10 @@ class InFlightSubstitution {
138138
return Options.contains(SubstFlags::SubstituteOpaqueArchetypes);
139139
}
140140

141+
bool shouldSubstituteLocalArchetypes() const {
142+
return Options.contains(SubstFlags::SubstituteLocalArchetypes);
143+
}
144+
141145
/// Is the given type invariant to substitution?
142146
bool isInvariant(Type type) const;
143147
};

include/swift/AST/Type.h

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,20 +117,24 @@ class MakeAbstractConformanceForGenericType {
117117

118118
/// Flags that can be passed when substituting into a type.
119119
enum class SubstFlags {
120-
/// Allow substitutions to recurse into SILFunctionTypes.
121-
/// Normally, SILType::subst() should be used for lowered
122-
/// types, however in special cases where the substitution
123-
/// is just changing between contextual and interface type
124-
/// representations, using Type::subst() is allowed.
120+
/// Allow substitutions to recurse into SILFunctionTypes. Normally,
121+
/// SILType::subst() should be used for lowered types, however in special
122+
/// cases where the substitution is just changing between contextual and
123+
/// interface type representations, using Type::subst() is allowed.
125124
AllowLoweredTypes = 0x01,
126125
/// Map member types to their desugared witness type.
127126
DesugarMemberTypes = 0x02,
128-
/// Substitute types involving opaque type archetypes.
127+
/// Allow opaque archetypes to themselves be the subject of substitution,
128+
/// used when erasing them to their underlying types. otherwise, we
129+
/// recursively substitute their substitutions, instead, preserving the
130+
/// opaque archetype.
129131
SubstituteOpaqueArchetypes = 0x04,
132+
/// Allow local archetypes to themselves be the subject of substitution.
133+
SubstituteLocalArchetypes = 0x08,
130134
/// Don't increase pack expansion level for free pack references.
131135
/// Do not introduce new usages of this flag.
132136
/// FIXME: Remove this.
133-
PreservePackExpansionLevel = 0x08,
137+
PreservePackExpansionLevel = 0x10,
134138
};
135139

136140
/// Options for performing substitutions into a type.

include/swift/SIL/SILCloner.h

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -461,8 +461,12 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
461461

462462
SILType remapType(SILType Ty) {
463463
if (Functor.SubsMap || Ty.hasLocalArchetype()) {
464+
SubstOptions options(std::nullopt);
465+
if (!Functor.LocalArchetypeSubs.empty())
466+
options |= SubstFlags::SubstituteLocalArchetypes;
467+
464468
Ty = Ty.subst(Builder.getModule(), Functor, Functor,
465-
CanGenericSignature());
469+
CanGenericSignature(), options);
466470
}
467471

468472
if (asImpl().shouldSubstOpaqueArchetypes()) {
@@ -481,8 +485,13 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
481485
}
482486

483487
CanType remapASTType(CanType ty) {
484-
if (Functor.SubsMap || ty->hasLocalArchetype())
485-
ty = ty.subst(Functor, Functor)->getCanonicalType();
488+
if (Functor.SubsMap || ty->hasLocalArchetype()) {
489+
SubstOptions options(std::nullopt);
490+
if (!Functor.LocalArchetypeSubs.empty())
491+
options |= SubstFlags::SubstituteLocalArchetypes;
492+
493+
ty = ty.subst(Functor, Functor, options)->getCanonicalType();
494+
}
486495

487496
if (asImpl().shouldSubstOpaqueArchetypes()) {
488497
auto context = getBuilder().getTypeExpansionContext();
@@ -501,9 +510,13 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
501510

502511
ProtocolConformanceRef remapConformance(Type Ty, ProtocolConformanceRef C) {
503512
if (Functor.SubsMap || Ty->hasLocalArchetype()) {
504-
C = C.subst(Ty, Functor, Functor);
513+
SubstOptions options(std::nullopt);
514+
if (!Functor.LocalArchetypeSubs.empty())
515+
options |= SubstFlags::SubstituteLocalArchetypes;
516+
517+
C = C.subst(Ty, Functor, Functor, options);
505518
if (asImpl().shouldSubstOpaqueArchetypes())
506-
Ty = Ty.subst(Functor, Functor);
519+
Ty = Ty.subst(Functor, Functor, options);
507520
}
508521

509522
if (asImpl().shouldSubstOpaqueArchetypes()) {
@@ -521,8 +534,13 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
521534

522535
SubstitutionMap remapSubstitutionMap(SubstitutionMap Subs) {
523536
// If we have local archetypes to substitute, do so now.
524-
if (Subs.hasLocalArchetypes() || Functor.SubsMap)
525-
Subs = Subs.subst(Functor, Functor);
537+
if (Subs.hasLocalArchetypes() || Functor.SubsMap) {
538+
SubstOptions options(std::nullopt);
539+
if (!Functor.LocalArchetypeSubs.empty())
540+
options |= SubstFlags::SubstituteLocalArchetypes;
541+
542+
Subs = Subs.subst(Functor, Functor, options);
543+
}
526544

527545
if (asImpl().shouldSubstOpaqueArchetypes()) {
528546
auto context = getBuilder().getTypeExpansionContext();

lib/AST/ASTMangler.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3793,7 +3793,8 @@ void ASTMangler::appendClosureComponents(Type Ty, unsigned discriminator,
37933793

37943794
Ty = Ty.subst(MapLocalArchetypesOutOfContext(Sig, capturedEnvs),
37953795
MakeAbstractConformanceForGenericType(),
3796-
SubstFlags::PreservePackExpansionLevel);
3796+
SubstFlags::PreservePackExpansionLevel |
3797+
SubstFlags::SubstituteLocalArchetypes);
37973798

37983799
appendType(Ty->getCanonicalType(), Sig);
37993800
appendOperator(isImplicit ? "fu" : "fU", Index(discriminator));

lib/AST/GenericEnvironment.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -734,7 +734,8 @@ GenericEnvironment::mapElementTypeIntoPackContext(Type type) const {
734734
},
735735
MakeAbstractConformanceForGenericType(),
736736
SubstFlags::AllowLoweredTypes |
737-
SubstFlags::PreservePackExpansionLevel);
737+
SubstFlags::PreservePackExpansionLevel |
738+
SubstFlags::SubstituteLocalArchetypes);
738739

739740
auto shapeClass = elementEnv->getOpenedElementShapeClass();
740741

lib/AST/TypeSubstitution.cpp

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -472,10 +472,13 @@ InFlightSubstitution::lookupConformance(CanType dependentType,
472472
}
473473

474474
bool InFlightSubstitution::isInvariant(Type derivedType) const {
475-
return !derivedType->hasArchetype()
476-
&& !derivedType->hasTypeParameter()
477-
&& (!shouldSubstituteOpaqueArchetypes()
478-
|| !derivedType->hasOpaqueArchetype());
475+
if (derivedType->hasPrimaryArchetype() || derivedType->hasTypeParameter())
476+
return false;
477+
if (shouldSubstituteLocalArchetypes() && derivedType->hasLocalArchetype())
478+
return false;
479+
if (shouldSubstituteOpaqueArchetypes() && derivedType->hasOpaqueArchetype())
480+
return false;
481+
return true;
479482
}
480483

481484
namespace {
@@ -522,6 +525,12 @@ TypeSubstituter::transform(TypeBase *type, TypePosition position) {
522525
&& isa<OpaqueTypeArchetypeType>(substOrig))
523526
return std::nullopt;
524527

528+
// Local types can't normally be directly substituted unless we
529+
// specifically were asked to substitute them.
530+
if (!IFS.shouldSubstituteLocalArchetypes()
531+
&& isa<LocalArchetypeType>(substOrig))
532+
return std::nullopt;
533+
525534
// If we have a substitution for this type, use it.
526535
if (auto known = IFS.substType(substOrig, level)) {
527536
if (IFS.shouldSubstituteOpaqueArchetypes() &&
@@ -532,15 +541,8 @@ TypeSubstituter::transform(TypeBase *type, TypePosition position) {
532541
return known;
533542
}
534543

535-
if (substOrig->isRoot()) {
536-
// Root opened archetypes are not required to be substituted. Other root
537-
// archetypes must already have been substituted above.
538-
if (isa<LocalArchetypeType>(substOrig)) {
539-
return Type(type);
540-
} else {
541-
return ErrorType::get(type);
542-
}
543-
}
544+
if (substOrig->isRoot())
545+
return ErrorType::get(type);
544546

545547
// For nested archetypes, we can substitute the parent.
546548
Type origParent = substOrig->getParent();

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1969,7 +1969,8 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function,
19691969

19701970
t = t.subst(MapLocalArchetypesOutOfContext(origGenericSig, capturedEnvs),
19711971
MakeAbstractConformanceForGenericType(),
1972-
SubstFlags::PreservePackExpansionLevel);
1972+
SubstFlags::PreservePackExpansionLevel |
1973+
SubstFlags::SubstituteLocalArchetypes);
19731974

19741975
LLVM_DEBUG(llvm::dbgs() << "-- maps to " << t->getCanonicalType() << "\n");
19751976
return t->getCanonicalType();
@@ -2958,7 +2959,8 @@ buildThunkSignature(SILFunction *fn,
29582959
auto thunkInterfaceType = Type(localArchetype).subst(
29592960
mapOutOfContext,
29602961
MakeAbstractConformanceForGenericType(),
2961-
SubstFlags::PreservePackExpansionLevel);
2962+
SubstFlags::PreservePackExpansionLevel |
2963+
SubstFlags::SubstituteLocalArchetypes);
29622964
auto thunkArchetype = genericEnv->mapTypeIntoContext(
29632965
thunkInterfaceType);
29642966
contextLocalArchetypes.insert(std::make_pair(localArchetype,
@@ -3026,25 +3028,27 @@ CanSILFunctionType swift::buildSILFunctionThunkType(
30263028
// Does the thunk type involve a local archetype type?
30273029
SmallVector<CanLocalArchetypeType, 8> localArchetypes;
30283030
auto archetypeVisitor = [&](CanType t) {
3029-
if (auto archetypeTy = dyn_cast<ArchetypeType>(t)) {
3030-
if (auto local = dyn_cast<LocalArchetypeType>(archetypeTy)) {
3031-
auto root = local.getRoot();
3032-
if (llvm::find(localArchetypes, root) == localArchetypes.end())
3033-
localArchetypes.push_back(root);
3034-
}
3031+
if (auto local = dyn_cast<LocalArchetypeType>(t)) {
3032+
auto root = local.getRoot();
3033+
if (llvm::find(localArchetypes, root) == localArchetypes.end())
3034+
localArchetypes.push_back(root);
30353035
}
30363036
};
30373037

3038+
if (expectedType->hasLocalArchetype())
3039+
expectedType.visit(archetypeVisitor);
3040+
if (sourceType->hasLocalArchetype())
3041+
sourceType.visit(archetypeVisitor);
3042+
30383043
// Use the generic signature from the context if the thunk involves
30393044
// generic parameters.
30403045
CanGenericSignature genericSig;
30413046
SubstitutionMap contextSubs;
30423047
llvm::DenseMap<ArchetypeType*, Type> contextLocalArchetypes;
30433048

3044-
if (expectedType->hasArchetype() || sourceType->hasArchetype()) {
3045-
expectedType.visit(archetypeVisitor);
3046-
sourceType.visit(archetypeVisitor);
3047-
3049+
if (!localArchetypes.empty() ||
3050+
expectedType->hasPrimaryArchetype() ||
3051+
sourceType->hasPrimaryArchetype()) {
30483052
genericSig = buildThunkSignature(fn,
30493053
localArchetypes,
30503054
genericEnv,
@@ -3079,13 +3083,16 @@ CanSILFunctionType swift::buildSILFunctionThunkType(
30793083
// opened existential with the new archetype.
30803084
auto substFormalTypeIntoThunkContext =
30813085
[&](CanType t) -> CanType {
3082-
return t.subst(substTypeHelper, substConformanceHelper)
3086+
return t.subst(substTypeHelper, substConformanceHelper,
3087+
SubstFlags::SubstituteLocalArchetypes)
30833088
->getCanonicalType();
30843089
};
30853090
auto substLoweredTypeIntoThunkContext =
30863091
[&](CanSILFunctionType t) -> CanSILFunctionType {
30873092
return SILType::getPrimitiveObjectType(t)
3088-
.subst(fn->getModule(), substTypeHelper, substConformanceHelper)
3093+
.subst(fn->getModule(), substTypeHelper, substConformanceHelper,
3094+
CanGenericSignature(),
3095+
SubstFlags::SubstituteLocalArchetypes)
30893096
.castTo<SILFunctionType>();
30903097
};
30913098

lib/SIL/IR/TypeLowering.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3909,7 +3909,8 @@ getAnyFunctionRefInterfaceType(TypeConverter &TC,
39093909
auto substType = Type(funcType).subst(
39103910
MapLocalArchetypesOutOfContext(sig.baseGenericSig, sig.capturedEnvs),
39113911
MakeAbstractConformanceForGenericType(),
3912-
SubstFlags::PreservePackExpansionLevel);
3912+
SubstFlags::PreservePackExpansionLevel |
3913+
SubstFlags::SubstituteLocalArchetypes);
39133914
funcType = cast<FunctionType>(substType->getCanonicalType());
39143915
}
39153916

@@ -4991,7 +4992,8 @@ TypeConverter::getInterfaceBoxTypeForCapture(ValueDecl *captured,
49914992
mapOutOfContext,
49924993
MakeAbstractConformanceForGenericType(),
49934994
SubstFlags::PreservePackExpansionLevel |
4994-
SubstFlags::AllowLoweredTypes)->getCanonicalType();
4995+
SubstFlags::AllowLoweredTypes |
4996+
SubstFlags::SubstituteLocalArchetypes)->getCanonicalType();
49954997

49964998
// If the type is not dependent at all, we can form a concrete box layout.
49974999
// We don't need to capture the generic environment.

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6314,7 +6314,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
63146314
substTypes,
63156315
LookUpConformanceInModule(),
63166316
CanGenericSignature(),
6317-
SubstFlags::PreservePackExpansionLevel);
6317+
SubstFlags::PreservePackExpansionLevel |
6318+
SubstFlags::SubstituteLocalArchetypes);
63186319
requireSameType(indexedElementSILType, substTargetElementSILType,
63196320
"lanewise-substituted pack element type didn't "
63206321
"match expected element type");

lib/SILGen/ResultPlan.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ mapTypeOutOfOpenedExistentialContext(CanType t) {
145145

146146
return params[index];
147147
},
148-
MakeAbstractConformanceForGenericType());
148+
MakeAbstractConformanceForGenericType(),
149+
SubstFlags::SubstituteLocalArchetypes);
149150

150151
return std::make_pair(mappedTy->getCanonicalType(), mappedSubs);
151152
}

lib/SILOptimizer/IPO/CrossModuleOptimization.cpp

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -134,58 +134,54 @@ class CrossModuleOptimization {
134134
class InstructionVisitor : public SILCloner<InstructionVisitor> {
135135
friend class SILCloner<InstructionVisitor>;
136136
friend class SILInstructionVisitor<InstructionVisitor>;
137+
friend class CrossModuleOptimization;
137138

138139
private:
139140
CrossModuleOptimization &CMS;
140-
SILInstruction *result = nullptr;
141141

142142
public:
143-
InstructionVisitor(SILInstruction *I, CrossModuleOptimization &CMS) :
144-
SILCloner(*I->getFunction()), CMS(CMS) {
145-
Builder.setInsertionPoint(I);
146-
}
143+
InstructionVisitor(SILFunction &F, CrossModuleOptimization &CMS) :
144+
SILCloner(F), CMS(CMS) {}
147145

148146
SILType remapType(SILType Ty) {
149147
if (Ty.hasLocalArchetype()) {
150-
Ty = Ty.subst(getBuilder().getModule(), Functor, Functor,
151-
CanGenericSignature());
148+
Ty = Ty.subst(getBuilder().getModule(),
149+
Functor, Functor, CanGenericSignature(),
150+
SubstFlags::SubstituteLocalArchetypes);
152151
}
153152

154153
CMS.makeTypeUsableFromInline(Ty.getASTType());
155154
return Ty;
156155
}
157156

158157
CanType remapASTType(CanType Ty) {
159-
if (Ty->hasLocalArchetype())
160-
Ty = Ty.subst(Functor, Functor)->getCanonicalType();
158+
if (Ty->hasLocalArchetype()) {
159+
Ty = Ty.subst(Functor, Functor,
160+
SubstFlags::SubstituteLocalArchetypes)->getCanonicalType();
161+
}
161162

162163
CMS.makeTypeUsableFromInline(Ty);
163164
return Ty;
164165
}
165166

166167
SubstitutionMap remapSubstitutionMap(SubstitutionMap Subs) {
167-
if (Subs.hasLocalArchetypes())
168-
Subs = Subs.subst(Functor, Functor);
168+
if (Subs.hasLocalArchetypes()) {
169+
Subs = Subs.subst(Functor, Functor,
170+
SubstFlags::SubstituteLocalArchetypes);
171+
}
169172

170173
CMS.makeSubstUsableFromInline(Subs);
171174
return Subs;
172175
}
173176

174177
void postProcess(SILInstruction *Orig, SILInstruction *Cloned) {
175-
result = Cloned;
176178
SILCloner<InstructionVisitor>::postProcess(Orig, Cloned);
179+
Cloned->eraseFromParent();
177180
}
178181

179182
SILValue getMappedValue(SILValue Value) { return Value; }
180183

181184
SILBasicBlock *remapBasicBlock(SILBasicBlock *BB) { return BB; }
182-
183-
static void makeTypesUsableFromInline(SILInstruction *I,
184-
CrossModuleOptimization &CMS) {
185-
InstructionVisitor visitor(I, CMS);
186-
visitor.visit(I);
187-
visitor.result->eraseFromParent();
188-
}
189185
};
190186

191187
static bool isPackageCMOEnabled(ModuleDecl *mod) {
@@ -721,12 +717,16 @@ void CrossModuleOptimization::serializeFunction(SILFunction *function,
721717
}
722718
function->setSerializedKind(getRightSerializedKind(M));
723719

720+
InstructionVisitor visitor(*function, *this);
724721
for (SILBasicBlock &block : *function) {
725722
for (SILInstruction &inst : block) {
726-
InstructionVisitor::makeTypesUsableFromInline(&inst, *this);
723+
visitor.getBuilder().setInsertionPoint(&inst);
724+
visitor.visit(&inst);
727725
serializeInstruction(&inst, canSerializeFlags);
728726
}
729727
}
728+
729+
M.reclaimUnresolvedLocalArchetypeDefinitions();
730730
}
731731

732732
/// Prepare \p inst for serialization.

0 commit comments

Comments
 (0)