Skip to content

Commit 5ab94a6

Browse files
committed
AST: Add "re-sugaring" to GenericEnvironment
Sugared GenericTypeParamTypes point to GenericTypeParamDecls, allowing the name of the parameter as written by the user to be recovered. Canonical GenericTypeParamTypes on the other hand only store a depth and index, without referencing the original declaration. When printing SIL, we wish to output the original generic parameter names, even though SIL only uses canonical types. Previously, we used to accomplish this by mapping the generic parameter to an archetype and printing the name of the archetype. This was not adequate if multiple generic parameters mapped to the same archetype, or if a generic parameter was mapped to a concrete type. The new approach preserves the original sugared types in the GenericEnvironment, adding a new GenericEnvironment::getSugaredType() method. There are also some other assorted simplifications made possible by this. Unfortunately this makes GenericEnvironments use a bit more memory, however I have more improvements coming that will offset the gains, in addition to making substitution lists smaller also.
1 parent 785b4eb commit 5ab94a6

20 files changed

+198
-158
lines changed

include/swift/AST/ArchetypeBuilder.h

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -254,21 +254,11 @@ class ArchetypeBuilder {
254254
GenericEnvironment *genericEnv,
255255
bool treatRequirementsAsExplicit = false);
256256

257-
/// \brief Get a generic signature based on the provided complete list
258-
/// of generic parameter types.
259-
///
260-
/// \returns a generic signature built from the provided list of
261-
/// generic parameter types.
262-
GenericSignature *
263-
getGenericSignature(ArrayRef<GenericTypeParamType *> genericParamsTypes);
257+
/// \brief Build the generic signature.
258+
GenericSignature *getGenericSignature();
264259

265-
/// \brief Get a generic context based on the complete list of generic
266-
/// parameter types.
267-
///
268-
/// \returns a generic context built from the provided list of
269-
/// generic parameter types.
270-
GenericEnvironment *getGenericEnvironment(
271-
ArrayRef<GenericTypeParamType *> genericParamsTypes);
260+
/// \brief Build the generic environment.
261+
GenericEnvironment *getGenericEnvironment();
272262

273263
/// Infer requirements from the given type, recursively.
274264
///

include/swift/AST/GenericEnvironment.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,15 @@ class GenericTypeParamType;
2828
/// Describes the mapping between archetypes and interface types for the
2929
/// generic parameters of a DeclContext.
3030
class GenericEnvironment final {
31+
SmallVector<GenericTypeParamType *, 4> GenericParams;
3132
TypeSubstitutionMap ArchetypeToInterfaceMap;
3233
TypeSubstitutionMap InterfaceToArchetypeMap;
3334

3435
public:
36+
ArrayRef<GenericTypeParamType *> getGenericParams() const {
37+
return GenericParams;
38+
}
39+
3540
const TypeSubstitutionMap &getArchetypeToInterfaceMap() const {
3641
return ArchetypeToInterfaceMap;
3742
}
@@ -40,10 +45,13 @@ class GenericEnvironment final {
4045
return InterfaceToArchetypeMap;
4146
}
4247

43-
explicit GenericEnvironment(TypeSubstitutionMap interfaceToArchetypeMap);
48+
GenericEnvironment(ArrayRef<GenericTypeParamType *> genericParamTypes,
49+
TypeSubstitutionMap interfaceToArchetypeMap);
4450

45-
static GenericEnvironment *get(ASTContext &ctx,
46-
TypeSubstitutionMap interfaceToArchetypeMap);
51+
static
52+
GenericEnvironment * get(ASTContext &ctx,
53+
ArrayRef<GenericTypeParamType *> genericParamTypes,
54+
TypeSubstitutionMap interfaceToArchetypeMap);
4755

4856
/// Make vanilla new/delete illegal.
4957
void *operator new(size_t Bytes) = delete;
@@ -62,6 +70,9 @@ class GenericEnvironment final {
6270
/// Map a generic parameter type to a contextual type.
6371
Type mapTypeIntoContext(GenericTypeParamType *type) const;
6472

73+
/// Get the sugared form of a generic parameter type.
74+
GenericTypeParamType *getSugaredType(GenericTypeParamType *type) const;
75+
6576
/// Derive a contextual type substitution map from a substitution array.
6677
/// This is just like GenericSignature::getSubstitutionMap(), except
6778
/// with contextual types instead of interface types.

include/swift/Serialization/DeclTypeRecordNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ OTHER(GENERIC_PARAM_LIST, 240)
169169
TRAILING_INFO(GENERIC_PARAM)
170170
TRAILING_INFO(GENERIC_REQUIREMENT)
171171
TRAILING_INFO(GENERIC_ENVIRONMENT)
172+
TRAILING_INFO(SIL_GENERIC_ENVIRONMENT)
172173

173174
OTHER(LOCAL_DISCRIMINATOR, 248)
174175
OTHER(PRIVATE_DISCRIMINATOR, 249)

include/swift/Serialization/ModuleFormat.h

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ const uint16_t VERSION_MAJOR = 0;
5454
/// in source control, you should also update the comment to briefly
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
57-
const uint16_t VERSION_MINOR = 273; // Last change: partial_apply ownership control
57+
const uint16_t VERSION_MINOR = 274; // Last change: SIL generic environment sugar
5858

5959
using DeclID = PointerEmbeddedInt<unsigned, 31>;
6060
using DeclIDField = BCFixed<31>;
@@ -1095,21 +1095,16 @@ namespace decls_block {
10951095
DeclIDField // Typealias
10961096
>;
10971097

1098-
// Subtlety here: GENERIC_ENVIRONMENT is serialized for both Decls and
1099-
// SILFunctions.
1100-
//
1101-
// For Decls, the interface type is non-canonical, so it points back
1102-
// to the GenericParamListDecl. This allows us to use the serialized
1103-
// GENERIC_ENVIRONMENT records to form the GenericSignature, as well.
1104-
// The type is canonicalized when forming the actual GenericEnvironment
1105-
// instance.
1106-
//
1107-
// For SILFunctions, the interface type below is always canonical,
1108-
// since SILFunctions never point back to any original
1109-
// GenericTypeParamDecls.
11101098
using GenericEnvironmentLayout = BCRecordLayout<
11111099
GENERIC_ENVIRONMENT,
1112-
TypeIDField, // interface type
1100+
TypeIDField, // sugared interface type
1101+
TypeIDField // contextual type
1102+
>;
1103+
1104+
using SILGenericEnvironmentLayout = BCRecordLayout<
1105+
SIL_GENERIC_ENVIRONMENT,
1106+
IdentifierIDField, // generic parameter name
1107+
TypeIDField, // canonical interface type
11131108
TypeIDField // contextual type
11141109
>;
11151110

lib/AST/ASTContext.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3567,8 +3567,10 @@ GenericSignature *GenericSignature::get(ArrayRef<GenericTypeParamType *> params,
35673567

35683568
GenericEnvironment *
35693569
GenericEnvironment::get(ASTContext &ctx,
3570+
ArrayRef<GenericTypeParamType *> genericParamTypes,
35703571
TypeSubstitutionMap interfaceToArchetypeMap) {
3571-
return new (ctx) GenericEnvironment(interfaceToArchetypeMap);
3572+
return new (ctx) GenericEnvironment(genericParamTypes,
3573+
interfaceToArchetypeMap);
35723574
}
35733575

35743576
void DeclName::CompoundDeclName::Profile(llvm::FoldingSetNodeID &id,

lib/AST/ASTDumper.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3090,4 +3090,7 @@ void GenericEnvironment::dump() const {
30903090
pair.first->dump();
30913091
pair.second->dump();
30923092
}
3093+
llvm::errs() << "Generic parameters:\n";
3094+
for (auto paramTy : getGenericParams())
3095+
paramTy->dump();
30933096
}

lib/AST/ASTPrinter.cpp

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3418,14 +3418,6 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
34183418
Printer.printTypePre(TypeLoc::withoutLoc(T));
34193419
SWIFT_DEFER { Printer.printTypePost(TypeLoc::withoutLoc(T)); };
34203420

3421-
// If we have an alternate name for this type, use it.
3422-
if (Options.AlternativeTypeNames) {
3423-
auto found = Options.AlternativeTypeNames->find(T.getCanonicalTypeOrNull());
3424-
if (found != Options.AlternativeTypeNames->end()) {
3425-
Printer << found->second.str();
3426-
return;
3427-
}
3428-
}
34293421
super::visit(T);
34303422
}
34313423

@@ -3992,6 +3984,14 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
39923984
Printer << ".";
39933985
}
39943986

3987+
if (Options.AlternativeTypeNames) {
3988+
auto found = Options.AlternativeTypeNames->find(T->getCanonicalType());
3989+
if (found != Options.AlternativeTypeNames->end()) {
3990+
Printer << found->second.str();
3991+
return;
3992+
}
3993+
}
3994+
39953995
if (T->getName().empty())
39963996
Printer << "<anonymous>";
39973997
else {
@@ -4012,9 +4012,21 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
40124012
}
40134013

40144014
void visitGenericTypeParamType(GenericTypeParamType *T) {
4015-
// Substitute a context archetype if we have context generic params.
4016-
if (Options.GenericEnv)
4017-
return visit(Options.GenericEnv->mapTypeIntoContext(T));
4015+
if (T->getDecl() == nullptr) {
4016+
// If we have an alternate name for this type, use it.
4017+
if (Options.AlternativeTypeNames) {
4018+
auto found = Options.AlternativeTypeNames->find(T->getCanonicalType());
4019+
if (found != Options.AlternativeTypeNames->end()) {
4020+
Printer << found->second.str();
4021+
return;
4022+
}
4023+
}
4024+
4025+
// When printing SIL types, use a generic environment to map them from
4026+
// canonical types to sugared types.
4027+
if (Options.GenericEnv)
4028+
T = Options.GenericEnv->getSugaredType(T);
4029+
}
40184030

40194031
auto Name = T->getName();
40204032
if (Name.empty())

lib/AST/ArchetypeBuilder.cpp

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2096,27 +2096,31 @@ static void collectRequirements(ArchetypeBuilder &builder,
20962096
});
20972097
}
20982098

2099-
GenericSignature *ArchetypeBuilder::getGenericSignature(
2100-
ArrayRef<GenericTypeParamType *> genericParamTypes) {
2099+
GenericSignature *ArchetypeBuilder::getGenericSignature() {
21012100
// Collect the requirements placed on the generic parameter types.
2101+
SmallVector<GenericTypeParamType *, 4> genericParamTypes;
2102+
for (auto pair : Impl->PotentialArchetypes) {
2103+
auto paramTy = pair.second->getGenericParam();
2104+
genericParamTypes.push_back(paramTy);
2105+
}
2106+
21022107
SmallVector<Requirement, 4> requirements;
21032108
collectRequirements(*this, genericParamTypes, requirements);
21042109

21052110
auto sig = GenericSignature::get(genericParamTypes, requirements);
21062111
return sig;
21072112
}
21082113

2109-
GenericEnvironment *ArchetypeBuilder::getGenericEnvironment(
2110-
ArrayRef<GenericTypeParamType *> genericParamTypes) {
2114+
GenericEnvironment *ArchetypeBuilder::getGenericEnvironment() {
2115+
SmallVector<GenericTypeParamType *, 4> genericParamTypes;
21112116
TypeSubstitutionMap interfaceToArchetypeMap;
21122117

2113-
for (auto paramTy : genericParamTypes) {
2114-
auto known = Impl->PotentialArchetypes.find(
2115-
GenericTypeParamKey::forType(paramTy));
2116-
assert(known != Impl->PotentialArchetypes.end());
2118+
for (auto pair : Impl->PotentialArchetypes) {
2119+
auto paramTy = pair.second->getGenericParam();
2120+
genericParamTypes.push_back(paramTy);
21172121

2118-
auto archetypeTy = known->second->getType(*this).getAsArchetype();
2119-
auto concreteTy = known->second->getType(*this).getAsConcreteType();
2122+
auto archetypeTy = pair.second->getType(*this).getAsArchetype();
2123+
auto concreteTy = pair.second->getType(*this).getAsConcreteType();
21202124
if (archetypeTy)
21212125
interfaceToArchetypeMap[paramTy] = archetypeTy;
21222126
else if (concreteTy)
@@ -2125,6 +2129,7 @@ GenericEnvironment *ArchetypeBuilder::getGenericEnvironment(
21252129
llvm_unreachable("broken generic parameter");
21262130
}
21272131

2128-
return GenericEnvironment::get(Context, interfaceToArchetypeMap);
2132+
return GenericEnvironment::get(Context, genericParamTypes,
2133+
interfaceToArchetypeMap);
21292134
}
21302135

lib/AST/Builtins.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,8 @@ getBuiltinGenericFunction(Identifier Id,
205205
GenericSignature *Sig =
206206
GenericSignature::get(GenericParamTypes, requirements);
207207
GenericEnvironment *Env =
208-
GenericEnvironment::get(Context, InterfaceToArchetypeMap);
208+
GenericEnvironment::get(Context, GenericParamTypes,
209+
InterfaceToArchetypeMap);
209210

210211
Type InterfaceType = GenericFunctionType::get(Sig, ArgParamType, ResType,
211212
AnyFunctionType::ExtInfo());

lib/AST/GenericEnvironment.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,14 @@
2020
using namespace swift;
2121

2222
GenericEnvironment::GenericEnvironment(
23+
ArrayRef<GenericTypeParamType *> genericParamTypes,
2324
TypeSubstitutionMap interfaceToArchetypeMap) {
2425

2526
assert(!interfaceToArchetypeMap.empty());
2627

28+
for (auto *paramTy : genericParamTypes)
29+
GenericParams.push_back(paramTy);
30+
2731
// Build a mapping in both directions, making sure to canonicalize the
2832
// interface type where it is used as a key, so that substitution can
2933
// find them, and to preserve sugar otherwise, so that
@@ -74,6 +78,15 @@ Type GenericEnvironment::mapTypeIntoContext(GenericTypeParamType *type) const {
7478
return found->second;
7579
}
7680

81+
GenericTypeParamType *GenericEnvironment::getSugaredType(
82+
GenericTypeParamType *type) const {
83+
for (auto *sugaredType : GenericParams)
84+
if (sugaredType->isEqual(type))
85+
return sugaredType;
86+
87+
llvm_unreachable("missing generic parameter");
88+
}
89+
7790
ArrayRef<Substitution>
7891
GenericEnvironment::getForwardingSubstitutions(
7992
ModuleDecl *M, GenericSignature *sig) const {

lib/ClangImporter/ImportDecl.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6861,8 +6861,8 @@ buildGenericSignature(GenericParamList *genericParams,
68616861
param->getDeclaredType()->castTo<GenericTypeParamType>());
68626862
}
68636863

6864-
auto *sig = builder.getGenericSignature(genericParamTypes);
6865-
auto *env = builder.getGenericEnvironment(genericParamTypes);
6864+
auto *sig = builder.getGenericSignature();
6865+
auto *env = builder.getGenericEnvironment();
68666866

68676867
return std::make_pair(sig, env);
68686868
}

lib/SIL/SILPrinter.cpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "swift/SIL/SILVTable.h"
3131
#include "swift/AST/Decl.h"
3232
#include "swift/AST/Expr.h"
33+
#include "swift/AST/GenericEnvironment.h"
3334
#include "swift/AST/Module.h"
3435
#include "swift/AST/PrintOptions.h"
3536
#include "swift/AST/Types.h"
@@ -1835,21 +1836,25 @@ void SILFunction::print(SILPrintContext &PrintCtx) const {
18351836
llvm::SmallString<16> disambiguatedNameBuf;
18361837
unsigned disambiguatedNameCounter = 1;
18371838
for (auto *paramTy : sig->getGenericParams()) {
1838-
auto *archetypeTy = mapTypeIntoContext(paramTy)->getAs<ArchetypeType>();
1839-
if (!archetypeTy)
1840-
continue;
1841-
1842-
Identifier name = archetypeTy->getName();
1839+
auto sugaredTy = env->getSugaredType(paramTy);
1840+
Identifier name = sugaredTy->getName();
18431841
while (!UsedNames.insert(name).second) {
18441842
disambiguatedNameBuf.clear();
18451843
{
18461844
llvm::raw_svector_ostream names(disambiguatedNameBuf);
1847-
names << archetypeTy->getName() << disambiguatedNameCounter++;
1845+
names << sugaredTy->getName() << disambiguatedNameCounter++;
18481846
}
18491847
name = getASTContext().getIdentifier(disambiguatedNameBuf);
18501848
}
1851-
if (name != archetypeTy->getName())
1852-
Aliases[CanType(archetypeTy)] = name;
1849+
if (name != sugaredTy->getName()) {
1850+
Aliases[paramTy->getCanonicalType()] = name;
1851+
1852+
// Also for the archetype
1853+
auto archetypeTy = env->mapTypeIntoContext(paramTy)
1854+
->getAs<ArchetypeType>();
1855+
if (archetypeTy)
1856+
Aliases[archetypeTy->getCanonicalType()] = name;
1857+
}
18531858
}
18541859
}
18551860

lib/SILGen/SILGenDecl.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1780,7 +1780,7 @@ substSelfTypeIntoProtocolRequirementType(SILModule &M,
17801780
if (!allParams.empty()) {
17811781
builder.finalize(SourceLoc());
17821782

1783-
auto *sig = builder.getGenericSignature(allParams);
1783+
auto *sig = builder.getGenericSignature();
17841784

17851785
return cast<GenericFunctionType>(
17861786
GenericFunctionType::get(sig, input, result, reqtTy->getExtInfo())
@@ -1800,6 +1800,7 @@ getSubstitutedGenericEnvironment(SILModule &M,
18001800
return reqtEnv;
18011801
}
18021802

1803+
SmallVector<GenericTypeParamType *, 4> genericParamTypes;
18031804
TypeSubstitutionMap witnessContextParams;
18041805

18051806
auto selfTy = conformance->getProtocol()->getSelfInterfaceType()
@@ -1809,8 +1810,14 @@ getSubstitutedGenericEnvironment(SILModule &M,
18091810
// the conformance (which might not be the same as the generic
18101811
// context of the witness, if the witness is defined in a
18111812
// superclass, concrete extension or protocol extension).
1812-
if (auto *outerEnv = conformance->getGenericEnvironment())
1813+
if (auto *outerEnv = conformance->getGenericEnvironment()) {
18131814
witnessContextParams = outerEnv->getInterfaceToArchetypeMap();
1815+
for (auto *paramTy : outerEnv->getGenericParams())
1816+
genericParamTypes.push_back(paramTy);
1817+
}
1818+
1819+
for (auto *paramTy : reqtEnv->getGenericParams().slice(1))
1820+
genericParamTypes.push_back(paramTy);
18141821

18151822
// Inner generic parameters come from the requirement and
18161823
// also map to the archetypes of the requirement.
@@ -1824,7 +1831,8 @@ getSubstitutedGenericEnvironment(SILModule &M,
18241831
}
18251832

18261833
if (!witnessContextParams.empty())
1827-
return GenericEnvironment::get(M.getASTContext(), witnessContextParams);
1834+
return GenericEnvironment::get(M.getASTContext(), genericParamTypes,
1835+
witnessContextParams);
18281836

18291837
return nullptr;
18301838
}

0 commit comments

Comments
 (0)