Skip to content

Commit 0dc16d8

Browse files
authored
Merge pull request #7969 from slavapestov/subst-cleanup
More SubstitutionList => SubstitutionMap cleanups
2 parents 5b48acf + de2f5f7 commit 0dc16d8

19 files changed

+340
-344
lines changed

include/swift/AST/ASTContext.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -683,19 +683,38 @@ class ASTContext {
683683
takeDelayedConformanceDiags(NormalProtocolConformance *conformance);
684684

685685
/// \brief Produce a specialized conformance, which takes a generic
686-
/// conformance and substitutes
686+
/// conformance and substitutions written in terms of the generic
687+
/// conformance's signature.
687688
///
688689
/// \param type The type for which we are retrieving the conformance.
689690
///
690691
/// \param generic The generic conformance.
691692
///
692693
/// \param substitutions The set of substitutions required to produce the
693-
/// specialized conformance from the generic conformance.
694+
/// specialized conformance from the generic conformance. This list is
695+
/// copied so passing a temporary is permitted.
694696
SpecializedProtocolConformance *
695697
getSpecializedConformance(Type type,
696698
ProtocolConformance *generic,
697699
SubstitutionList substitutions);
698700

701+
/// \brief Produce a specialized conformance, which takes a generic
702+
/// conformance and substitutions written in terms of the generic
703+
/// conformance's signature.
704+
///
705+
/// \param type The type for which we are retrieving the conformance.
706+
///
707+
/// \param generic The generic conformance.
708+
///
709+
/// \param substitutions The set of substitutions required to produce the
710+
/// specialized conformance from the generic conformance. The keys must
711+
/// be generic parameters, not archetypes, so for example passing in
712+
/// TypeBase::getContextSubstitutionMap() is OK.
713+
SpecializedProtocolConformance *
714+
getSpecializedConformance(Type type,
715+
ProtocolConformance *generic,
716+
const SubstitutionMap &substitutions);
717+
699718
/// \brief Produce an inherited conformance, for subclasses of a type
700719
/// that already conforms to a protocol.
701720
///

include/swift/AST/ProtocolConformance.h

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -279,18 +279,15 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance {
279279

280280
/// Get the property declaration for a behavior conformance, if this is one.
281281
AbstractStorageDecl *getBehaviorDecl() const;
282-
283-
void dump() const;
284-
void dump(llvm::raw_ostream &out, unsigned indent = 0) const;
285282

286-
private:
287-
friend class Substitution;
288283
/// Substitute the conforming type and produce a ProtocolConformance that
289284
/// applies to the substituted type.
290-
ProtocolConformance *subst(ModuleDecl *module,
291-
Type substType,
285+
ProtocolConformance *subst(Type substType,
292286
TypeSubstitutionFn subs,
293287
LookupConformanceFn conformances) const;
288+
289+
void dump() const;
290+
void dump(llvm::raw_ostream &out, unsigned indent = 0) const;
294291
};
295292

296293
/// Normal protocol conformance, which involves mapping each of the protocol

include/swift/AST/ProtocolConformanceRef.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,11 @@ class ProtocolConformanceRef {
9191
/// conformance represents.
9292
ProtocolConformanceRef getInherited(ProtocolDecl *parent) const;
9393

94+
/// Apply a substitution to the conforming type.
95+
ProtocolConformanceRef subst(Type origType,
96+
TypeSubstitutionFn subs,
97+
LookupConformanceFn conformances) const;
98+
9499
void dump() const;
95100
void dump(llvm::raw_ostream &out, unsigned indent = 0) const;
96101

include/swift/AST/Substitution.h

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,6 @@ class Substitution {
5454
const PrintOptions &PO = PrintOptions()) const;
5555
void dump() const;
5656
void dump(llvm::raw_ostream &os, unsigned indent = 0) const;
57-
58-
/// Apply a substitution to this substitution's replacement type and
59-
/// conformances.
60-
Substitution subst(ModuleDecl *module,
61-
const SubstitutionMap &subMap) const;
62-
Substitution subst(ModuleDecl *module,
63-
TypeSubstitutionFn subs,
64-
LookupConformanceFn conformances) const;
65-
66-
private:
67-
friend class ProtocolConformance;
6857
};
6958

7059
} // end namespace swift

include/swift/AST/SubstitutionMap.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,19 +80,29 @@ class SubstitutionMap {
8080
CanType type, ProtocolDecl *proto,
8181
llvm::SmallPtrSetImpl<CanType> *visitedParents = nullptr) const;
8282

83-
/// Retrieve the conformances for the given type.
84-
ArrayRef<ProtocolConformanceRef> getConformances(CanType type) const;
85-
8683
bool empty() const {
8784
return subMap.empty();
8885
}
8986

9087
/// Query whether any replacement types in the map contain archetypes.
9188
bool hasArchetypes() const;
9289

90+
/// Query whether any replacement types in the map contain an opened
91+
/// existential.
92+
bool hasOpenedExistential() const;
93+
9394
/// Query whether any replacement type sin the map contain dynamic Self.
9495
bool hasDynamicSelf() const;
9596

97+
/// Apply a substitution to all replacement types in the map. Does not
98+
/// change keys.
99+
SubstitutionMap subst(const SubstitutionMap &subMap) const;
100+
101+
/// Apply a substitution to all replacement types in the map. Does not
102+
/// change keys.
103+
SubstitutionMap subst(TypeSubstitutionFn subs,
104+
LookupConformanceFn conformances) const;
105+
96106
/// Create a substitution map for a protocol conformance.
97107
static SubstitutionMap
98108
getProtocolSubstitutions(ProtocolDecl *protocol,

include/swift/SIL/SILCloner.h

Lines changed: 78 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#ifndef SWIFT_SIL_SILCLONER_H
1818
#define SWIFT_SIL_SILCLONER_H
1919

20+
#include "swift/AST/ProtocolConformance.h"
2021
#include "swift/SIL/SILOpenedArchetypesTracker.h"
2122
#include "swift/SIL/SILBuilder.h"
2223
#include "swift/SIL/SILDebugScope.h"
@@ -94,7 +95,7 @@ class SILCloner : protected SILVisitor<ImplClass> {
9495
const SILDebugScope *remapScope(const SILDebugScope *DS) { return DS; }
9596
SILType remapType(SILType Ty) { return Ty; }
9697
CanType remapASTType(CanType Ty) { return Ty; }
97-
ProtocolConformanceRef remapConformance(CanType Ty, ProtocolConformanceRef C){
98+
ProtocolConformanceRef remapConformance(Type Ty, ProtocolConformanceRef C){
9899
return C;
99100
}
100101
SILValue remapValue(SILValue Value);
@@ -108,37 +109,12 @@ class SILCloner : protected SILVisitor<ImplClass> {
108109
const SILDebugScope *getOpScope(const SILDebugScope *DS) {
109110
return asImpl().remapScope(DS);
110111
}
111-
Substitution getOpSubstitution(Substitution sub) {
112-
return asImpl().remapSubstitution(sub);
113-
}
114-
Substitution remapSubstitution(Substitution sub) {
115-
CanType newReplacement =
116-
asImpl().getOpASTType(sub.getReplacement()->getCanonicalType());
117-
118-
return Substitution(newReplacement, sub.getConformances());
119-
}
120-
SubstitutionList getOpSubstitutions(SubstitutionList Subs) {
121-
MutableArrayRef<Substitution> newSubsBuf;
122-
123-
auto copySubs = [&]{
124-
if (!newSubsBuf.empty())
125-
return;
126-
newSubsBuf = getBuilder().getASTContext()
127-
.template Allocate<Substitution>(Subs.size());
128-
memcpy(newSubsBuf.data(), Subs.data(),
129-
sizeof(Substitution) * Subs.size());
130-
Subs = newSubsBuf;
131-
};
132-
133-
for (unsigned i = 0, e = Subs.size(); i < e; ++i) {
134-
Substitution newSub = asImpl().getOpSubstitution(Subs[i]);
135-
if (newSub != Subs[i]) {
136-
copySubs();
137-
newSubsBuf[i] = newSub;
138-
}
112+
SmallVector<Substitution, 4> getOpSubstitutions(SubstitutionList Subs) {
113+
SmallVector<Substitution, 4> NewSubs;
114+
for (auto Sub : Subs) {
115+
NewSubs.push_back(getOpSubstitution(Sub));
139116
}
140-
141-
return Subs;
117+
return NewSubs;
142118
}
143119

144120
SILType getTypeInClonedContext(SILType Ty) {
@@ -152,15 +128,15 @@ class SILCloner : protected SILVisitor<ImplClass> {
152128
return asImpl().remapType(Ty);
153129
}
154130

155-
CanType getASTTypeInClonedContext(CanType ty) {
131+
CanType getASTTypeInClonedContext(Type ty) {
156132
// Do not substitute opened existential types, if we do not have any.
157133
if (!ty->hasOpenedExistential())
158-
return ty;
134+
return ty->getCanonicalType();
159135
// Do not substitute opened existential types, if it is not required.
160136
// This is often the case when cloning basic blocks inside the same
161137
// function.
162138
if (OpenedExistentialSubs.empty())
163-
return ty;
139+
return ty->getCanonicalType();
164140

165141
return ty.transform(
166142
[&](Type t) -> Type {
@@ -181,32 +157,46 @@ class SILCloner : protected SILVisitor<ImplClass> {
181157
return t;
182158
})->getCanonicalType();
183159
}
160+
184161
CanType getOpASTType(CanType ty) {
185162
ty = getASTTypeInClonedContext(ty);
186163
return asImpl().remapASTType(ty);
187164
}
188165

189-
/// Remap an entire set of conformances.
190-
///
191-
/// Returns the passed-in conformances array if none of the elements
192-
/// changed.
193-
ArrayRef<ProtocolConformanceRef> getOpConformances(CanType type,
194-
ArrayRef<ProtocolConformanceRef> oldConformances) {
195-
Substitution sub(type, oldConformances);
196-
Substitution mappedSub = asImpl().remapSubstitution(sub);
197-
ArrayRef<ProtocolConformanceRef> newConformances =
198-
mappedSub.getConformances();
199-
200-
// Use the existing conformances array if possible.
201-
if (oldConformances == newConformances)
202-
return oldConformances;
203-
204-
return type->getASTContext().AllocateCopy(newConformances);
166+
ProtocolConformanceRef getOpConformance(Type ty,
167+
ProtocolConformanceRef conformance) {
168+
auto newConformance =
169+
conformance.subst(ty,
170+
[&](SubstitutableType *t) -> Type {
171+
if (t->isOpenedExistential()) {
172+
auto found = OpenedExistentialSubs.find(
173+
t->castTo<ArchetypeType>());
174+
if (found != OpenedExistentialSubs.end())
175+
return found->second;
176+
return t;
177+
}
178+
return t;
179+
},
180+
MakeAbstractConformanceForGenericType());
181+
return asImpl().remapConformance(getASTTypeInClonedContext(ty),
182+
newConformance);
205183
}
206184

207-
ProtocolConformanceRef getOpConformance(CanType ty,
208-
ProtocolConformanceRef conformance) {
209-
return asImpl().remapConformance(ty, conformance);
185+
ArrayRef<ProtocolConformanceRef>
186+
getOpConformances(Type ty,
187+
ArrayRef<ProtocolConformanceRef> conformances) {
188+
SmallVector<ProtocolConformanceRef, 4> newConformances;
189+
for (auto conformance : conformances)
190+
newConformances.push_back(getOpConformance(ty, conformance));
191+
return ty->getASTContext().AllocateCopy(newConformances);
192+
}
193+
194+
Substitution getOpSubstitution(Substitution sub) {
195+
CanType newReplacement =
196+
getOpASTType(sub.getReplacement()->getCanonicalType());
197+
auto conformances = getOpConformances(sub.getReplacement(),
198+
sub.getConformances());
199+
return Substitution(newReplacement, conformances);
210200
}
211201

212202
SILValue getOpValue(SILValue Value) {
@@ -538,9 +528,10 @@ SILCloner<ImplClass>::visitAllocExistentialBoxInst(
538528
AllocExistentialBoxInst *Inst) {
539529
auto origExistentialType = Inst->getExistentialType();
540530
auto origFormalType = Inst->getFormalConcreteType();
541-
542-
auto conformances =getOpConformances(origFormalType, Inst->getConformances());
543-
531+
532+
auto conformances = getOpConformances(origFormalType,
533+
Inst->getConformances());
534+
544535
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
545536
doPostProcess(Inst,
546537
getBuilder().createAllocExistentialBox(getOpLocation(Inst->getLoc()),
@@ -1447,7 +1438,7 @@ SILCloner<ImplClass>::visitClassMethodInst(ClassMethodInst *Inst) {
14471438
getBuilder().createClassMethod(getOpLocation(Inst->getLoc()),
14481439
getOpValue(Inst->getOperand()),
14491440
Inst->getMember(),
1450-
getOpType(Inst->getType()),
1441+
Inst->getType(),
14511442
Inst->isVolatile()));
14521443
}
14531444

@@ -1459,25 +1450,37 @@ SILCloner<ImplClass>::visitSuperMethodInst(SuperMethodInst *Inst) {
14591450
getBuilder().createSuperMethod(getOpLocation(Inst->getLoc()),
14601451
getOpValue(Inst->getOperand()),
14611452
Inst->getMember(),
1462-
getOpType(Inst->getType()),
1453+
Inst->getType(),
14631454
Inst->isVolatile()));
14641455
}
14651456

14661457
template<typename ImplClass>
14671458
void
14681459
SILCloner<ImplClass>::visitWitnessMethodInst(WitnessMethodInst *Inst) {
1469-
auto conformance =
1470-
getOpConformance(Inst->getLookupType(), Inst->getConformance());
14711460
auto lookupType = Inst->getLookupType();
1461+
auto conformance = getOpConformance(lookupType, Inst->getConformance());
14721462
auto newLookupType = getOpASTType(lookupType);
1463+
1464+
if (conformance.isConcrete()) {
1465+
CanType Ty = conformance.getConcrete()->getType()->getCanonicalType();
1466+
1467+
if (Ty != newLookupType) {
1468+
assert(Ty->isExactSuperclassOf(newLookupType, nullptr) &&
1469+
"Should only create upcasts for sub class.");
1470+
1471+
// We use the super class as the new look up type.
1472+
newLookupType = Ty;
1473+
}
1474+
}
1475+
14731476
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
14741477
doPostProcess(
14751478
Inst,
14761479
getBuilder()
14771480
.createWitnessMethod(
14781481
getOpLocation(Inst->getLoc()),
14791482
newLookupType, conformance,
1480-
Inst->getMember(), getOpType(Inst->getType()),
1483+
Inst->getMember(), Inst->getType(),
14811484
Inst->isVolatile()));
14821485
}
14831486

@@ -1601,7 +1604,10 @@ template<typename ImplClass>
16011604
void
16021605
SILCloner<ImplClass>::visitInitExistentialAddrInst(InitExistentialAddrInst *Inst) {
16031606
CanType origFormalType = Inst->getFormalConcreteType();
1604-
auto conformances =getOpConformances(origFormalType, Inst->getConformances());
1607+
1608+
auto conformances = getOpConformances(origFormalType,
1609+
Inst->getConformances());
1610+
16051611
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
16061612
doPostProcess(Inst,
16071613
getBuilder().createInitExistentialAddr(getOpLocation(Inst->getLoc()),
@@ -1615,8 +1621,10 @@ template <typename ImplClass>
16151621
void SILCloner<ImplClass>::visitInitExistentialOpaqueInst(
16161622
InitExistentialOpaqueInst *Inst) {
16171623
CanType origFormalType = Inst->getFormalConcreteType();
1618-
auto conformances =
1619-
getOpConformances(origFormalType, Inst->getConformances());
1624+
1625+
auto conformances = getOpConformances(origFormalType,
1626+
Inst->getConformances());
1627+
16201628
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
16211629
doPostProcess(Inst,
16221630
getBuilder().createInitExistentialOpaque(
@@ -1629,8 +1637,10 @@ template<typename ImplClass>
16291637
void
16301638
SILCloner<ImplClass>::
16311639
visitInitExistentialMetatypeInst(InitExistentialMetatypeInst *Inst) {
1632-
auto conformances = getOpConformances(Inst->getFormalErasedObjectType(),
1640+
auto origFormalType = Inst->getFormalErasedObjectType();
1641+
auto conformances = getOpConformances(origFormalType,
16331642
Inst->getConformances());
1643+
16341644
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
16351645
doPostProcess(Inst,
16361646
getBuilder().createInitExistentialMetatype(getOpLocation(Inst->getLoc()),
@@ -1644,7 +1654,9 @@ void
16441654
SILCloner<ImplClass>::
16451655
visitInitExistentialRefInst(InitExistentialRefInst *Inst) {
16461656
CanType origFormalType = Inst->getFormalConcreteType();
1647-
auto conformances =getOpConformances(origFormalType, Inst->getConformances());
1657+
auto conformances = getOpConformances(origFormalType,
1658+
Inst->getConformances());
1659+
16481660
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
16491661
doPostProcess(Inst,
16501662
getBuilder().createInitExistentialRef(getOpLocation(Inst->getLoc()),

0 commit comments

Comments
 (0)