Skip to content

Commit ff6cdeb

Browse files
authored
Merge pull request #73625 from slavapestov/sil-cloner-local-archetypes-fix
Redo handling of local archetypes in SILCloner
2 parents face056 + 2a82dda commit ff6cdeb

File tree

10 files changed

+207
-121
lines changed

10 files changed

+207
-121
lines changed

include/swift/AST/SubstitutionMap.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,13 @@ class SubstitutionMap {
170170
bool hasArchetypes() const;
171171

172172
/// Query whether any replacement types in the map contain an opened
173-
/// existential.
173+
/// existential or opened element.
174174
bool hasLocalArchetypes() const;
175175

176+
/// Query whether any replacement types in the map contain an opaque
177+
/// return type.
178+
bool hasOpaqueArchetypes() const;
179+
176180
/// Query whether any replacement types in the map contain dynamic Self.
177181
bool hasDynamicSelf() const;
178182

include/swift/AST/Type.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -87,15 +87,6 @@ struct QueryTypeSubstitutionMap {
8787
Type operator()(SubstitutableType *type) const;
8888
};
8989

90-
/// A function object suitable for use as a \c TypeSubstitutionFn that
91-
/// queries an underlying \c TypeSubstitutionMap, or returns the original type
92-
/// if no match was found.
93-
struct QueryTypeSubstitutionMapOrIdentity {
94-
const TypeSubstitutionMap &substitutions;
95-
96-
Type operator()(SubstitutableType *type) const;
97-
};
98-
9990
/// Function used to resolve conformances.
10091
using GenericFunction = auto(CanType dependentType,
10192
Type conformingReplacementType,

include/swift/SIL/SILCloner.h

Lines changed: 87 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,35 @@
2929

3030
namespace swift {
3131

32+
struct SubstitutionMapWithLocalArchetypes {
33+
std::optional<SubstitutionMap> SubsMap;
34+
TypeSubstitutionMap LocalArchetypeSubs;
35+
36+
SubstitutionMapWithLocalArchetypes() {}
37+
SubstitutionMapWithLocalArchetypes(SubstitutionMap subs) : SubsMap(subs) {}
38+
39+
Type operator()(SubstitutableType *type) {
40+
if (isa<LocalArchetypeType>(type))
41+
return QueryTypeSubstitutionMap{LocalArchetypeSubs}(type);
42+
43+
if (SubsMap)
44+
return Type(type).subst(*SubsMap);
45+
46+
return Type(type);
47+
}
48+
49+
ProtocolConformanceRef operator()(CanType origType,
50+
Type substType,
51+
ProtocolDecl *proto) {
52+
if (isa<LocalArchetypeType>(origType))
53+
return proto->getParentModule()->lookupConformance(substType, proto);
54+
if (SubsMap)
55+
return SubsMap->lookupConformance(origType, proto);
56+
57+
return ProtocolConformanceRef(proto);
58+
}
59+
};
60+
3261
/// SILCloner - Abstract SIL visitor which knows how to clone instructions and
3362
/// whose behavior can be customized by subclasses via the CRTP. This is meant
3463
/// to be subclassed to implement inlining, function specialization, and other
@@ -49,7 +78,7 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
4978

5079
SILBuilder Builder;
5180
DominanceInfo *DomTree = nullptr;
52-
TypeSubstitutionMap LocalArchetypeSubs;
81+
SubstitutionMapWithLocalArchetypes Functor;
5382

5483
// The old-to-new value map.
5584
llvm::DenseMap<SILValue, SILValue> ValueMap;
@@ -78,7 +107,8 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
78107
explicit SILCloner(SILFunction &F, DominanceInfo *DT = nullptr)
79108
: Builder(F), DomTree(DT) {}
80109

81-
explicit SILCloner(SILGlobalVariable *GlobVar) : Builder(GlobVar) {}
110+
explicit SILCloner(SILGlobalVariable *GlobVar)
111+
: Builder(GlobVar) {}
82112

83113
void clearClonerState() {
84114
ValueMap.clear();
@@ -167,7 +197,7 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
167197
/// Register a re-mapping for local archetypes such as opened existentials.
168198
void registerLocalArchetypeRemapping(ArchetypeType *From,
169199
ArchetypeType *To) {
170-
auto result = LocalArchetypeSubs.insert(
200+
auto result = Functor.LocalArchetypeSubs.insert(
171201
std::make_pair(CanArchetypeType(From), CanType(To)));
172202
assert(result.second);
173203
(void)result;
@@ -189,62 +219,31 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
189219
}
190220

191221
SubstitutionMap getOpSubstitutionMap(SubstitutionMap Subs) {
192-
// If we have local archetypes to substitute, check whether that's
193-
// relevant to this particular substitution.
194-
if (!LocalArchetypeSubs.empty()) {
195-
if (Subs.hasLocalArchetypes()) {
196-
// If we found a type containing a local archetype, substitute
197-
// open existentials throughout the substitution map.
198-
Subs = Subs.subst(QueryTypeSubstitutionMapOrIdentity{LocalArchetypeSubs},
199-
MakeAbstractConformanceForGenericType());
222+
auto substSubs = asImpl().remapSubstitutionMap(Subs)
223+
.getCanonical(/*canonicalizeSignature*/false);
224+
225+
#ifndef NDEBUG
226+
for (auto substConf : substSubs.getConformances()) {
227+
if (substConf.isInvalid()) {
228+
llvm::errs() << "Invalid conformance in SIL cloner:\n";
229+
if (Functor.SubsMap)
230+
Functor.SubsMap->dump(llvm::errs());
231+
llvm::errs() << "\nsubstitution map:\n";
232+
Subs.dump(llvm::errs());
233+
llvm::errs() << "\n";
234+
abort();
200235
}
201236
}
237+
#endif
202238

203-
return asImpl().remapSubstitutionMap(Subs)
204-
.getCanonical(/*canonicalizeSignature*/false);
239+
return substSubs;
205240
}
206241

207-
SILType getTypeInClonedContext(SILType Ty) {
208-
auto objectTy = Ty.getASTType();
209-
// Do not substitute local archetypes, if we do not have any.
210-
if (!objectTy->hasLocalArchetype())
211-
return Ty;
212-
// Do not substitute local archetypes, if it is not required.
213-
// This is often the case when cloning basic blocks inside the same
214-
// function.
215-
if (LocalArchetypeSubs.empty())
216-
return Ty;
217-
218-
// Substitute local archetypes, if we have any.
219-
return Ty.subst(
220-
Builder.getModule(),
221-
QueryTypeSubstitutionMapOrIdentity{LocalArchetypeSubs},
222-
MakeAbstractConformanceForGenericType(),
223-
CanGenericSignature());
224-
}
225242
SILType getOpType(SILType Ty) {
226-
Ty = getTypeInClonedContext(Ty);
227243
return asImpl().remapType(Ty);
228244
}
229245

230-
CanType getASTTypeInClonedContext(Type ty) {
231-
// Do not substitute local archetypes, if we do not have any.
232-
if (!ty->hasLocalArchetype())
233-
return ty->getCanonicalType();
234-
// Do not substitute local archetypes, if it is not required.
235-
// This is often the case when cloning basic blocks inside the same
236-
// function.
237-
if (LocalArchetypeSubs.empty())
238-
return ty->getCanonicalType();
239-
240-
return ty.subst(
241-
QueryTypeSubstitutionMapOrIdentity{LocalArchetypeSubs},
242-
MakeAbstractConformanceForGenericType()
243-
)->getCanonicalType();
244-
}
245-
246246
CanType getOpASTType(CanType ty) {
247-
ty = getASTTypeInClonedContext(ty);
248247
return asImpl().remapASTType(ty);
249248
}
250249

@@ -352,17 +351,22 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
352351

353352
ProtocolConformanceRef getOpConformance(Type ty,
354353
ProtocolConformanceRef conformance) {
355-
// If we have local archetypes to substitute, do so now.
356-
if (ty->hasLocalArchetype() && !LocalArchetypeSubs.empty()) {
357-
conformance =
358-
conformance.subst(ty,
359-
QueryTypeSubstitutionMapOrIdentity{
360-
LocalArchetypeSubs},
361-
MakeAbstractConformanceForGenericType());
354+
auto substConf = asImpl().remapConformance(ty, conformance);
355+
356+
#ifndef NDEBUG
357+
if (substConf.isInvalid()) {
358+
llvm::errs() << "Invalid conformance in SIL cloner:\n";
359+
if (Functor.SubsMap)
360+
Functor.SubsMap->dump(llvm::errs());
361+
llvm::errs() << "\nconformance:\n";
362+
conformance.dump(llvm::errs());
363+
llvm::errs() << "original type:\n";
364+
ty.dump(llvm::errs());
365+
abort();
362366
}
367+
#endif
363368

364-
return asImpl().remapConformance(getASTTypeInClonedContext(ty),
365-
conformance);
369+
return substConf;
366370
}
367371

368372
ArrayRef<ProtocolConformanceRef>
@@ -445,16 +449,31 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
445449
SILLocation remapLocation(SILLocation Loc) { return Loc; }
446450
const SILDebugScope *remapScope(const SILDebugScope *DS) { return DS; }
447451
SILType remapType(SILType Ty) {
448-
return Ty;
449-
}
452+
// Substitute local archetypes, if we have any.
453+
if (Ty.hasLocalArchetype()) {
454+
Ty = Ty.subst(Builder.getModule(), Functor, Functor,
455+
CanGenericSignature());
456+
}
450457

451-
CanType remapASTType(CanType Ty) {
452458
return Ty;
453459
}
454460

461+
CanType remapASTType(CanType ty) {
462+
// Substitute local archetypes, if we have any.
463+
if (ty->hasLocalArchetype())
464+
ty = ty.subst(Functor, Functor)->getCanonicalType();
465+
466+
return ty;
467+
}
468+
455469
ProtocolConformanceRef remapConformance(Type Ty, ProtocolConformanceRef C) {
470+
// If we have local archetypes to substitute, do so now.
471+
if (Ty->hasLocalArchetype())
472+
C = C.subst(Ty, Functor, Functor);
473+
456474
return C;
457475
}
476+
458477
/// Get the value that takes the place of the given `Value` within the cloned
459478
/// region. The given value must already have been mapped by this cloner.
460479
SILValue getMappedValue(SILValue Value);
@@ -464,7 +483,13 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
464483
SILBasicBlock *remapBasicBlock(SILBasicBlock *BB);
465484
void postProcess(SILInstruction *Orig, SILInstruction *Cloned);
466485

467-
SubstitutionMap remapSubstitutionMap(SubstitutionMap Subs) { return Subs; }
486+
SubstitutionMap remapSubstitutionMap(SubstitutionMap Subs) {
487+
// If we have local archetypes to substitute, do so now.
488+
if (Subs.hasLocalArchetypes())
489+
Subs = Subs.subst(Functor, Functor);
490+
491+
return Subs;
492+
}
468493

469494
/// This is called by either of the top-level visitors, cloneReachableBlocks
470495
/// or cloneSILFunction, after all other visitors are have been called.

include/swift/SIL/TypeSubstCloner.h

Lines changed: 52 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -143,13 +143,12 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
143143
using SILClonerWithScopes<ImplClass>::getBuilder;
144144
using SILClonerWithScopes<ImplClass>::getOpLocation;
145145
using SILClonerWithScopes<ImplClass>::getOpValue;
146-
using SILClonerWithScopes<ImplClass>::getASTTypeInClonedContext;
147146
using SILClonerWithScopes<ImplClass>::getOpASTType;
148-
using SILClonerWithScopes<ImplClass>::getTypeInClonedContext;
149147
using SILClonerWithScopes<ImplClass>::getOpType;
150148
using SILClonerWithScopes<ImplClass>::getOpBasicBlock;
151149
using SILClonerWithScopes<ImplClass>::recordClonedInstruction;
152150
using SILClonerWithScopes<ImplClass>::recordFoldedValue;
151+
using SILClonerWithScopes<ImplClass>::Functor;
153152

154153
TypeSubstCloner(SILFunction &To,
155154
SILFunction &From,
@@ -161,18 +160,34 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
161160
SubsMap(ApplySubs),
162161
Original(From),
163162
Inlining(Inlining) {
163+
Functor.SubsMap = ApplySubs;
164+
165+
#ifndef NDEBUG
166+
for (auto substConf : ApplySubs.getConformances()) {
167+
if (substConf.isInvalid()) {
168+
llvm::errs() << "Invalid conformance in SIL cloner:\n";
169+
ApplySubs.dump(llvm::errs());
170+
abort();
171+
}
172+
}
173+
#endif
174+
164175
}
165176

166177
protected:
167178
SILType remapType(SILType Ty) {
168179
SILType &Sty = TypeCache[Ty];
169180
if (!Sty) {
170-
Sty = Ty.subst(Original.getModule(), SubsMap);
171-
if (!Sty.getASTType()->hasOpaqueArchetype() ||
172-
!getBuilder()
173-
.getTypeExpansionContext()
174-
.shouldLookThroughOpaqueTypeArchetypes())
181+
Sty = Ty;
182+
183+
Sty = Sty.subst(getBuilder().getModule(), Functor, Functor);
184+
185+
auto context = getBuilder().getTypeExpansionContext();
186+
187+
if (!Sty.hasOpaqueArchetype() ||
188+
!context.shouldLookThroughOpaqueTypeArchetypes())
175189
return Sty;
190+
176191
// Remap types containing opaque result types in the current context.
177192
Sty = getBuilder().getTypeLowering(Sty).getLoweredType().getCategoryType(
178193
Sty.getCategory());
@@ -181,33 +196,47 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
181196
}
182197

183198
CanType remapASTType(CanType ty) {
184-
auto substTy = ty.subst(SubsMap)->getCanonicalType();
199+
auto substTy = ty.subst(Functor, Functor)->getCanonicalType();
200+
201+
auto context = getBuilder().getTypeExpansionContext();
202+
185203
if (!substTy->hasOpaqueArchetype() ||
186-
!getBuilder().getTypeExpansionContext()
187-
.shouldLookThroughOpaqueTypeArchetypes())
204+
!context.shouldLookThroughOpaqueTypeArchetypes())
188205
return substTy;
206+
189207
// Remap types containing opaque result types in the current context.
190-
return substOpaqueTypesWithUnderlyingTypes(
191-
substTy,
192-
TypeExpansionContext(getBuilder().getFunction()),
193-
/*allowLoweredTypes=*/false);
208+
return substOpaqueTypesWithUnderlyingTypes(substTy, context,
209+
/*allowLoweredTypes=*/false);
194210
}
195211

196212
ProtocolConformanceRef remapConformance(Type ty,
197213
ProtocolConformanceRef conf) {
198-
auto conformance = conf.subst(ty, SubsMap);
199-
auto substTy = ty.subst(SubsMap)->getCanonicalType();
214+
auto substTy = ty.subst(Functor, Functor)->getCanonicalType();
215+
auto substConf = conf.subst(ty, Functor, Functor);
216+
200217
auto context = getBuilder().getTypeExpansionContext();
201-
if (substTy->hasOpaqueArchetype() &&
202-
context.shouldLookThroughOpaqueTypeArchetypes()) {
203-
conformance =
204-
substOpaqueTypesWithUnderlyingTypes(conformance, substTy, context);
205-
}
206-
return conformance;
218+
219+
if (!substTy->hasOpaqueArchetype() ||
220+
!context.shouldLookThroughOpaqueTypeArchetypes())
221+
return substConf;
222+
223+
return substOpaqueTypesWithUnderlyingTypes(substConf, substTy, context);
207224
}
208225

209226
SubstitutionMap remapSubstitutionMap(SubstitutionMap Subs) {
210-
return Subs.subst(SubsMap);
227+
Subs = Subs.subst(Functor, Functor);
228+
229+
auto context = getBuilder().getTypeExpansionContext();
230+
231+
if (!Subs.hasOpaqueArchetypes() ||
232+
!context.shouldLookThroughOpaqueTypeArchetypes())
233+
return Subs;
234+
235+
ReplaceOpaqueTypesWithUnderlyingTypes replacer(
236+
context.getContext(), context.getResilienceExpansion(),
237+
context.isWholeModuleContext());
238+
return Subs.subst(replacer, replacer,
239+
SubstFlags::SubstituteOpaqueArchetypes);
211240
}
212241

213242
void visitApplyInst(ApplyInst *Inst) {

lib/AST/SubstitutionMap.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,14 @@ bool SubstitutionMap::hasLocalArchetypes() const {
140140
return false;
141141
}
142142

143+
bool SubstitutionMap::hasOpaqueArchetypes() const {
144+
for (Type replacementTy : getReplacementTypesBuffer()) {
145+
if (replacementTy && replacementTy->hasOpaqueArchetype())
146+
return true;
147+
}
148+
return false;
149+
}
150+
143151
bool SubstitutionMap::hasDynamicSelf() const {
144152
for (Type replacementTy : getReplacementTypesBuffer()) {
145153
if (replacementTy && replacementTy->hasDynamicSelfType())

0 commit comments

Comments
 (0)