Skip to content

Commit 0f4a7d2

Browse files
committed
AST: Remove GenericSignature::getAllDependentTypes()
This was a remnant of the old generics implementation, where all nested types were expanded into an AllArchetypes list. For quite some time, this method no longer returned *all* dependent types, only those with generic requirements on them, and all if its remaining uses were a bit convoluted. - In the generic specialization code, we used this to mangle substitutions for generic parameters that are not subject to a concrete same-type constraint. A new GenericSignature::getSubstitutableParams() function handles this use-case instead. It is similar to getGenericParams(), but only returns generic parameters which require substitution. In the future, SubstitutionLists will only store replacement types for these generic parameters, instead of the list of types that we used to produce from getAllDependentTypes(). - In specialization mangling and speculative devirtualization, we relied on SubstitutionLists having the same size and order as getAllDependentTypes(). It's better to turn the SubstitutionList into a SubstitutionMap instead, and do lookups into the map. - In the SIL parser, we were making a pass over the generic requirements before looking at getAllDependentTypes(); enumeratePairedRequirements() gives the correct information upfront. - In SIL box serialization, we don't serialize the size of the substitution list, since it's available from the generic signature. Add a GenericSignature::getSubstitutionListSize() method, but that will go away soon once SubstitionList serialization only serializes replacement types for generic parameters. - A few remaining uses now call enumeratePairedRequirements() directly.
1 parent 9f62e55 commit 0f4a7d2

File tree

12 files changed

+151
-156
lines changed

12 files changed

+151
-156
lines changed

include/swift/AST/GenericEnvironment.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,8 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
242242

243243
SubstitutionList getForwardingSubstitutions() const;
244244

245+
void dump(raw_ostream &os) const;
246+
245247
void dump() const;
246248
};
247249

include/swift/AST/GenericSignature.h

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -123,13 +123,6 @@ class alignas(1 << TypeAlignInBits) GenericSignature final
123123
return const_cast<GenericSignature *>(this)->getRequirementsBuffer();
124124
}
125125

126-
/// Check if the generic signature makes all generic parameters
127-
/// concrete.
128-
bool areAllParamsConcrete() const {
129-
auto iter = getAllDependentTypes();
130-
return iter.begin() == iter.end();
131-
}
132-
133126
/// Only allow allocation by doing a placement new.
134127
void *operator new(size_t Bytes, void *Mem) {
135128
assert(Mem);
@@ -174,11 +167,6 @@ class alignas(1 << TypeAlignInBits) GenericSignature final
174167
void getSubstitutions(const SubstitutionMap &subMap,
175168
SmallVectorImpl<Substitution> &result) const;
176169

177-
/// Return a range that iterates through all of the types that require
178-
/// substitution, which includes the generic parameter types as well as
179-
/// other dependent types that require additional conformances.
180-
SmallVector<Type, 4> getAllDependentTypes() const;
181-
182170
/// Enumerate all of the dependent types in the type signature that will
183171
/// occur in substitution lists (in order), along with the set of
184172
/// conformance requirements placed on that dependent type.
@@ -191,6 +179,33 @@ class alignas(1 << TypeAlignInBits) GenericSignature final
191179
bool enumeratePairedRequirements(
192180
llvm::function_ref<bool(Type, ArrayRef<Requirement>)> fn) const;
193181

182+
/// Return a vector of all generic parameters that are not subject to
183+
/// a concrete same-type constraint.
184+
SmallVector<GenericTypeParamType *, 2> getSubstitutableParams() const;
185+
186+
/// Check if the generic signature makes all generic parameters
187+
/// concrete.
188+
bool areAllParamsConcrete() const {
189+
return !enumeratePairedRequirements(
190+
[](Type, ArrayRef<Requirement>) -> bool {
191+
return true;
192+
});
193+
}
194+
195+
/// Return the size of a SubstitutionList built from this signature.
196+
///
197+
/// Don't add new calls of this -- the representation of SubstitutionList
198+
/// will be changing soon.
199+
unsigned getSubstitutionListSize() const {
200+
unsigned result = 0;
201+
enumeratePairedRequirements(
202+
[&](Type, ArrayRef<Requirement>) -> bool {
203+
result++;
204+
return false;
205+
});
206+
return result;
207+
}
208+
194209
/// Determines whether this GenericSignature is canonical.
195210
bool isCanonical() const;
196211

lib/AST/ASTDumper.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3117,13 +3117,17 @@ void TypeBase::dump(raw_ostream &os, unsigned indent) const {
31173117
Type(const_cast<TypeBase *>(this)).dump(os, indent);
31183118
}
31193119

3120-
void GenericEnvironment::dump() const {
3121-
llvm::errs() << "Generic environment:\n";
3120+
void GenericEnvironment::dump(raw_ostream &os) const {
3121+
os << "Generic environment:\n";
31223122
for (auto gp : getGenericParams()) {
3123-
gp->dump();
3124-
mapTypeIntoContext(gp)->dump();
3123+
gp->dump(os);
3124+
mapTypeIntoContext(gp)->dump(os);
31253125
}
3126-
llvm::errs() << "Generic parameters:\n";
3126+
os << "Generic parameters:\n";
31273127
for (auto paramTy : getGenericParams())
3128-
paramTy->dump();
3128+
paramTy->dump(os);
3129+
}
3130+
3131+
void GenericEnvironment::dump() const {
3132+
dump(llvm::errs());
31293133
}

lib/AST/GenericEnvironment.cpp

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -395,25 +395,27 @@ SubstitutionMap GenericEnvironment::
395395
getSubstitutionMap(SubstitutionList subs) const {
396396
SubstitutionMap result;
397397

398-
for (auto depTy : getGenericSignature()->getAllDependentTypes()) {
399-
400-
// Map the interface type to a context type.
401-
auto contextTy = depTy.subst(QueryInterfaceTypeSubstitutions(this),
402-
MakeAbstractConformanceForGenericType());
398+
getGenericSignature()->enumeratePairedRequirements(
399+
[&](Type depTy, ArrayRef<Requirement> reqts) -> bool {
400+
// Map the interface type to a context type.
401+
auto contextTy = depTy.subst(QueryInterfaceTypeSubstitutions(this),
402+
MakeAbstractConformanceForGenericType());
403403

404-
auto sub = subs.front();
405-
subs = subs.slice(1);
404+
auto sub = subs.front();
405+
subs = subs.slice(1);
406406

407-
// Record the replacement type and its conformances.
408-
if (auto *archetype = contextTy->getAs<ArchetypeType>()) {
409-
result.addSubstitution(CanArchetypeType(archetype), sub.getReplacement());
410-
for (auto conformance : sub.getConformances())
411-
result.addConformance(CanType(archetype), conformance);
412-
continue;
413-
}
407+
// Record the replacement type and its conformances.
408+
if (auto *archetype = contextTy->getAs<ArchetypeType>()) {
409+
result.addSubstitution(CanArchetypeType(archetype), sub.getReplacement());
410+
assert(reqts.size() == sub.getConformances().size());
411+
for (auto conformance : sub.getConformances())
412+
result.addConformance(CanType(archetype), conformance);
413+
return false;
414+
}
414415

415-
assert(contextTy->hasError());
416-
}
416+
assert(contextTy->hasError());
417+
return false;
418+
});
417419

418420
assert(subs.empty() && "did not use all substitutions?!");
419421

lib/AST/GenericSignature.cpp

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,20 @@ GenericSignature::getInnermostGenericParams() const {
7878
return params;
7979
}
8080

81+
82+
SmallVector<GenericTypeParamType *, 2>
83+
GenericSignature::getSubstitutableParams() const {
84+
SmallVector<GenericTypeParamType *, 2> result;
85+
86+
enumeratePairedRequirements([&](Type depTy, ArrayRef<Requirement>) -> bool {
87+
if (auto *paramTy = depTy->getAs<GenericTypeParamType>())
88+
result.push_back(paramTy);
89+
return false;
90+
});
91+
92+
return result;
93+
}
94+
8195
std::string GenericSignature::gatherGenericParamBindingsText(
8296
ArrayRef<Type> types, TypeSubstitutionFn substitutions) const {
8397
llvm::SmallPtrSet<GenericTypeParamType *, 2> knownGenericParams;
@@ -375,21 +389,21 @@ SubstitutionMap
375389
GenericSignature::getSubstitutionMap(SubstitutionList subs) const {
376390
SubstitutionMap result;
377391

378-
// An empty parameter list gives an empty map.
379-
if (subs.empty())
380-
assert(getGenericParams().empty() || areAllParamsConcrete());
392+
enumeratePairedRequirements(
393+
[&](Type depTy, ArrayRef<Requirement> reqts) -> bool {
394+
auto sub = subs.front();
395+
subs = subs.slice(1);
381396

382-
for (auto depTy : getAllDependentTypes()) {
383-
auto sub = subs.front();
384-
subs = subs.slice(1);
397+
auto canTy = depTy->getCanonicalType();
398+
if (isa<SubstitutableType>(canTy))
399+
result.addSubstitution(cast<SubstitutableType>(canTy),
400+
sub.getReplacement());
401+
assert(reqts.size() == sub.getConformances().size());
402+
for (auto conformance : sub.getConformances())
403+
result.addConformance(canTy, conformance);
385404

386-
auto canTy = depTy->getCanonicalType();
387-
if (isa<SubstitutableType>(canTy))
388-
result.addSubstitution(cast<SubstitutableType>(canTy),
389-
sub.getReplacement());
390-
for (auto conformance : sub.getConformances())
391-
result.addConformance(canTy, conformance);
392-
}
405+
return false;
406+
});
393407

394408
assert(subs.empty() && "did not use all substitutions?!");
395409
populateParentMap(result);
@@ -430,16 +444,6 @@ getSubstitutionMap(TypeSubstitutionFn subs,
430444
return subMap;
431445
}
432446

433-
SmallVector<Type, 4> GenericSignature::getAllDependentTypes() const {
434-
SmallVector<Type, 4> result;
435-
enumeratePairedRequirements([&](Type type, ArrayRef<Requirement>) {
436-
result.push_back(type);
437-
return false;
438-
});
439-
440-
return result;
441-
}
442-
443447
void GenericSignature::
444448
getSubstitutions(const TypeSubstitutionMap &subs,
445449
GenericSignature::LookupConformanceFn lookupConformance,

lib/Parse/ParseSIL.cpp

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1448,41 +1448,41 @@ bool getApplySubstitutionsFromParsed(
14481448

14491449
auto loc = parses[0].loc;
14501450

1451-
// Collect conformance requirements in a convenient form.
1452-
llvm::DenseMap<TypeBase *, SmallVector<ProtocolDecl *, 2>> conformsTo;
1453-
for (auto reqt : env->getGenericSignature()->getRequirements()) {
1454-
if (reqt.getKind() == RequirementKind::Conformance) {
1455-
auto canTy = reqt.getFirstType()->getCanonicalType();
1456-
auto nominal = reqt.getSecondType()->getAnyNominal();
1457-
conformsTo[canTy.getPointer()].push_back(cast<ProtocolDecl>(nominal));
1458-
}
1459-
}
1460-
14611451
// The replacement is for the corresponding dependent type by ordering.
1462-
for (auto depTy : env->getGenericSignature()->getAllDependentTypes()) {
1452+
auto result = env->getGenericSignature()->enumeratePairedRequirements(
1453+
[&](Type depTy, ArrayRef<Requirement> reqts) -> bool {
1454+
if (parses.empty()) {
1455+
SP.P.diagnose(loc, diag::sil_missing_substitutions);
1456+
return true;
1457+
}
1458+
auto parsed = parses.front();
1459+
parses = parses.slice(1);
1460+
1461+
SmallVector<ProtocolConformanceRef, 2> conformances;
1462+
SmallVector<ProtocolDecl *, 2> protocols;
1463+
for (auto reqt : reqts) {
1464+
protocols.push_back(reqt.getSecondType()
1465+
->castTo<ProtocolType>()->getDecl());
1466+
}
14631467

1464-
auto canTy = depTy->getCanonicalType().getPointer();
1468+
if (getConformancesForSubstitution(SP.P, protocols,
1469+
parsed.replacement,
1470+
parsed.loc, conformances))
1471+
return true;
14651472

1466-
if (parses.empty()) {
1467-
SP.P.diagnose(loc, diag::sil_missing_substitutions);
1468-
return true;
1469-
}
1470-
auto parsed = parses.front();
1471-
parses = parses.slice(1);
1473+
subs.push_back({parsed.replacement,
1474+
SP.P.Context.AllocateCopy(conformances)});
1475+
return false;
1476+
});
14721477

1473-
SmallVector<ProtocolConformanceRef, 2> conformances;
1474-
if (getConformancesForSubstitution(SP.P, conformsTo[canTy],
1475-
parsed.replacement,
1476-
parsed.loc, conformances))
1477-
return true;
1478+
if (result)
1479+
return true;
14781480

1479-
subs.push_back({parsed.replacement,
1480-
SP.P.Context.AllocateCopy(conformances)});
1481-
}
14821481
if (!parses.empty()) {
14831482
SP.P.diagnose(loc, diag::sil_too_many_substitutions);
14841483
return true;
14851484
}
1485+
14861486
return false;
14871487
}
14881488

lib/SIL/Mangle.cpp

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "swift/AST/Mangle.h"
2222
#include "swift/AST/Module.h"
2323
#include "swift/AST/ProtocolConformance.h"
24+
#include "swift/AST/SubstitutionMap.h"
2425
#include "swift/Basic/Punycode.h"
2526
#include "swift/SIL/SILArgument.h"
2627
#include "swift/SIL/SILType.h"
@@ -44,33 +45,21 @@ using namespace Mangle;
4445
// Generic Specialization
4546
//===----------------------------------------------------------------------===//
4647

47-
static void mangleSubstitution(Mangler &M, Substitution Sub) {
48-
M.mangleType(Sub.getReplacement()->getCanonicalType(), 0);
49-
for (auto C : Sub.getConformances()) {
50-
if (C.isAbstract())
51-
return;
52-
M.mangleProtocolConformance(C.getConcrete());
53-
}
54-
}
55-
5648
void GenericSpecializationMangler::mangleSpecialization() {
5749
Mangler &M = getMangler();
5850
// This is a full specialization.
5951
SILFunctionType *FTy = Function->getLoweredFunctionType();
6052
CanGenericSignature Sig = FTy->getGenericSignature();
61-
62-
unsigned idx = 0;
63-
for (Type DepType : Sig->getAllDependentTypes()) {
64-
// It is sufficient to only mangle the substitutions of the "primary"
65-
// dependent types. As all other dependent types are just derived from the
66-
// primary types, this will give us unique symbol names.
67-
if (DepType->is<GenericTypeParamType>()) {
68-
mangleSubstitution(M, Subs[idx]);
69-
M.append('_');
53+
auto SubMap = Sig->getSubstitutionMap(Subs);
54+
for (Type DepType : Sig->getSubstitutableParams()) {
55+
M.mangleType(DepType.subst(SubMap)->getCanonicalType(), 0);
56+
for (auto C : SubMap.getConformances(DepType->getCanonicalType())) {
57+
if (C.isAbstract())
58+
return;
59+
M.mangleProtocolConformance(C.getConcrete());
7060
}
71-
++idx;
61+
M.append('_');
7262
}
73-
assert(idx == Subs.size() && "subs not parallel to dependent types");
7463
}
7564

7665
void PartialSpecializationMangler::mangleSpecialization() {

0 commit comments

Comments
 (0)