Skip to content

Commit c3aea5b

Browse files
authored
Merge pull request #6007 from DougGregor/lazier-archetypes
2 parents 698d25c + 188d218 commit c3aea5b

File tree

14 files changed

+318
-230
lines changed

14 files changed

+318
-230
lines changed

include/swift/AST/ASTContext.h

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -762,8 +762,13 @@ class ASTContext {
762762

763763
/// Retrieve or create the stored archetype builder for the given
764764
/// canonical generic signature and module.
765-
std::pair<ArchetypeBuilder *, GenericEnvironment *>
766-
getOrCreateArchetypeBuilder(CanGenericSignature sig, ModuleDecl *mod);
765+
ArchetypeBuilder *getOrCreateArchetypeBuilder(CanGenericSignature sig,
766+
ModuleDecl *mod);
767+
768+
/// Retrieve or create the canonical generic environment of a canonical
769+
/// archetype builder.
770+
GenericEnvironment *getOrCreateCanonicalGenericEnvironment(
771+
ArchetypeBuilder *builder);
767772

768773
/// Retrieve the inherited name set for the given class.
769774
const InheritedNameSet *getAllPropertyNames(ClassDecl *classDecl,
@@ -796,26 +801,6 @@ class ASTContext {
796801
DeclContext *gpContext,
797802
ArrayRef<Substitution> Subs) const;
798803

799-
/// Retrieve the archetype builder and potential archetype
800-
/// corresponding to the given archetype type.
801-
///
802-
/// This facility is only used by the archetype builder when forming
803-
/// archetypes.a
804-
std::pair<ArchetypeBuilder *, ArchetypeBuilder::PotentialArchetype *>
805-
getLazyArchetype(const ArchetypeType *archetype);
806-
807-
/// Register information for a lazily-constructed archetype.
808-
void registerLazyArchetype(
809-
const ArchetypeType *archetype,
810-
ArchetypeBuilder &builder,
811-
ArchetypeBuilder::PotentialArchetype *potentialArchetype);
812-
813-
/// Unregister information about the given lazily-constructed archetype.
814-
void unregisterLazyArchetype(const ArchetypeType *archetype);
815-
816-
friend class ArchetypeType;
817-
friend class ArchetypeBuilder::PotentialArchetype;
818-
819804
/// Provide context-level uniquing for SIL lowered type layouts.
820805
friend SILLayout;
821806
llvm::FoldingSet<SILLayout> *&getSILLayouts();

include/swift/AST/GenericEnvironment.h

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include "swift/AST/SubstitutionMap.h"
2121
#include "swift/AST/GenericParamKey.h"
2222
#include "swift/AST/GenericSignature.h"
23+
#include "llvm/ADT/ArrayRef.h"
24+
#include "llvm/Support/TrailingObjects.h"
2325

2426
namespace swift {
2527

@@ -31,14 +33,57 @@ class SILType;
3133

3234
/// Describes the mapping between archetypes and interface types for the
3335
/// generic parameters of a DeclContext.
34-
class alignas(1 << DeclAlignInBits) GenericEnvironment final {
36+
class alignas(1 << DeclAlignInBits) GenericEnvironment final
37+
: private llvm::TrailingObjects<GenericEnvironment, Type> {
3538
GenericSignature *Signature;
39+
ArchetypeBuilder *Builder;
3640
TypeSubstitutionMap ArchetypeToInterfaceMap;
37-
TypeSubstitutionMap InterfaceToArchetypeMap;
41+
42+
friend TrailingObjects;
43+
44+
size_t numTrailingObjects(OverloadToken<Type>) const {
45+
return Signature->getGenericParams().size();
46+
}
47+
48+
/// Retrieve the array containing the context types associated with the
49+
/// generic parameters, stored in parallel with the generic parameters of the
50+
/// generic signature.
51+
MutableArrayRef<Type> getContextTypes() {
52+
return MutableArrayRef<Type>(getTrailingObjects<Type>(),
53+
Signature->getGenericParams().size());
54+
}
55+
56+
/// Retrieve the array containing the context types associated with the
57+
/// generic parameters, stored in parallel with the generic parameters of the
58+
/// generic signature.
59+
ArrayRef<Type> getContextTypes() const {
60+
return ArrayRef<Type>(getTrailingObjects<Type>(),
61+
Signature->getGenericParams().size());
62+
}
3863

3964
GenericEnvironment(GenericSignature *signature,
65+
ArchetypeBuilder *builder,
4066
TypeSubstitutionMap interfaceToArchetypeMap);
4167

68+
friend class ArchetypeType;
69+
friend class ArchetypeBuilder;
70+
71+
ArchetypeBuilder *getArchetypeBuilder() const { return Builder; }
72+
void clearArchetypeBuilder() { Builder = nullptr; }
73+
74+
/// Query function suitable for use as a \c TypeSubstitutionFn that queries
75+
/// the mapping of interface types to archetypes.
76+
class QueryInterfaceTypeSubstitutions {
77+
const GenericEnvironment *self;
78+
79+
public:
80+
QueryInterfaceTypeSubstitutions(const GenericEnvironment *self)
81+
: self(self) { }
82+
83+
Type operator()(SubstitutableType *type) const;
84+
};
85+
friend class QueryInterfaceTypeSubstitutions;
86+
4287
public:
4388
GenericSignature *getGenericSignature() const {
4489
return Signature;
@@ -53,15 +98,14 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final {
5398
bool containsPrimaryArchetype(ArchetypeType *archetype) const;
5499

55100
static
56-
GenericEnvironment *get(ASTContext &ctx,
57-
GenericSignature *signature,
101+
GenericEnvironment *get(GenericSignature *signature,
58102
TypeSubstitutionMap interfaceToArchetypeMap);
59103

60104
/// Create a new, "incomplete" generic environment that will be populated
61105
/// by calls to \c addMapping().
62106
static
63-
GenericEnvironment *getIncomplete(ASTContext &ctx,
64-
GenericSignature *signature);
107+
GenericEnvironment *getIncomplete(GenericSignature *signature,
108+
ArchetypeBuilder *builder);
65109

66110
/// Add a mapping of a generic parameter to a specific type (which may be
67111
/// an archetype)
@@ -76,9 +120,11 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final {
76120
void *operator new(size_t Bytes) = delete;
77121
void operator delete(void *Data) = delete;
78122

79-
/// Only allow allocation of GenericEnvironments using the allocator
80-
/// in ASTContext.
81-
void *operator new(size_t bytes, const ASTContext &ctx);
123+
/// Only allow placement new.
124+
void *operator new(size_t Bytes, void *Mem) {
125+
assert(Mem);
126+
return Mem;
127+
}
82128

83129
/// Map a contextual type to an interface type.
84130
Type mapTypeOutOfContext(ModuleDecl *M, Type type) const;

include/swift/AST/GenericSignature.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ class alignas(1 << TypeAlignInBits) GenericSignature final
7777
/// Retrieve the archetype builder for the given generic signature.
7878
ArchetypeBuilder *getArchetypeBuilder(ModuleDecl &mod);
7979

80+
friend class ArchetypeType;
81+
8082
public:
8183
/// Create a new generic signature with the given type parameters and
8284
/// requirements.
@@ -129,6 +131,13 @@ class alignas(1 << TypeAlignInBits) GenericSignature final
129131
using LookupConformanceFn =
130132
llvm::function_ref<ProtocolConformanceRef(CanType, Type, ProtocolType *)>;
131133

134+
/// Build an array of substitutions from an interface type substitution map,
135+
/// using the given function to look up conformances.
136+
void getSubstitutions(ModuleDecl &mod,
137+
TypeSubstitutionFn substitution,
138+
LookupConformanceFn lookupConformance,
139+
SmallVectorImpl<Substitution> &result) const;
140+
132141
/// Build an array of substitutions from an interface type substitution map,
133142
/// using the given function to look up conformances.
134143
void getSubstitutions(ModuleDecl &mod,

include/swift/AST/Type.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "llvm/ADT/DenseMap.h"
2121
#include "llvm/ADT/DenseMapInfo.h"
22+
#include "llvm/ADT/STLExtras.h"
2223
#include "swift/Basic/LLVM.h"
2324
#include "swift/AST/PrintOptions.h"
2425
#include "swift/AST/TypeAlignments.h"
@@ -52,6 +53,20 @@ class TypeWalker;
5253
/// replacements.
5354
typedef llvm::DenseMap<SubstitutableType *, Type> TypeSubstitutionMap;
5455

56+
/// Function used to provide substitutions.
57+
///
58+
/// \returns A null \c Type to indicate that there is no substitution for
59+
/// this substitutable type; otherwise, the replacement type.
60+
typedef llvm::function_ref<Type(SubstitutableType *)> TypeSubstitutionFn;
61+
62+
/// A function object suitable for use as a \c TypeSubstitutionFn that
63+
/// queries an underlying \c TypeSubstitutionMap.
64+
struct QueryTypeSubstitutionMap {
65+
const TypeSubstitutionMap &substitutions;
66+
67+
Type operator()(SubstitutableType *type) const;
68+
};
69+
5570
/// Flags that can be passed when substituting into a type.
5671
enum class SubstFlags {
5772
/// If a type cannot be produced because some member type is
@@ -187,6 +202,21 @@ class Type {
187202
Type subst(const SubstitutionMap &substitutions,
188203
SubstOptions options = None) const;
189204

205+
/// Replace references to substitutable types with new, concrete types and
206+
/// return the substituted result.
207+
///
208+
/// \param module The module to use for conformance lookups.
209+
///
210+
/// \param substitutions A function mapping from substitutable types to their
211+
/// replacements.
212+
///
213+
/// \param options Options that affect the substitutions.
214+
///
215+
/// \returns the substituted type, or a null type if an error occurred.
216+
Type subst(ModuleDecl *module,
217+
TypeSubstitutionFn substitutions,
218+
SubstOptions options = None) const;
219+
190220
bool isPrivateStdlibType(bool whitelistProtocols=true) const;
191221

192222
void dump() const;

include/swift/AST/Types.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3874,12 +3874,6 @@ class ArchetypeType final : public SubstitutableType,
38743874
/// \brief Retrieve the superclass of this type, if such a requirement exists.
38753875
Type getSuperclass() const { return Superclass; }
38763876

3877-
/// \brief Set the superclass of this type.
3878-
///
3879-
/// This can only be performed in very narrow cases where the archetype is
3880-
/// being lazily constructed.
3881-
void setSuperclass(Type superclass) { Superclass = superclass; }
3882-
38833877
/// \brief Return true if the archetype has any requirements at all.
38843878
bool hasRequirements() const {
38853879
return !getConformsTo().empty() || getSuperclass();

lib/AST/ASTContext.cpp

Lines changed: 44 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -207,19 +207,16 @@ struct ASTContext::Implementation {
207207
llvm::DenseMap<Decl *, std::pair<LazyMemberLoader *, uint64_t>>
208208
ConformanceLoaders;
209209

210-
/// Mapping from archetypes with lazily-resolved nested types to the
211-
/// archetype builder and potential archetype corresponding to that
212-
/// archetype.
213-
llvm::DenseMap<const ArchetypeType *,
214-
std::pair<ArchetypeBuilder *,
215-
ArchetypeBuilder::PotentialArchetype *>>
216-
LazyArchetypes;
217-
218-
/// \brief Stored archetype builders and their corresponding (canonical)
219-
/// generic environments.
210+
/// Stored archetype builders for canonical generic signatures.
220211
llvm::DenseMap<std::pair<GenericSignature *, ModuleDecl *>,
221-
std::pair<std::unique_ptr<ArchetypeBuilder>,
222-
GenericEnvironment *>> ArchetypeBuilders;
212+
std::unique_ptr<ArchetypeBuilder>>
213+
ArchetypeBuilders;
214+
215+
/// Canonical generic environments for canonical generic signatures.
216+
///
217+
/// The keys are the archetype builders in \c ArchetypeBuilders.
218+
llvm::DenseMap<ArchetypeBuilder *, GenericEnvironment *>
219+
CanonicalGenericEnvironments;
223220

224221
/// The set of property names that show up in the defining module of a
225222
/// class.
@@ -1254,25 +1251,36 @@ void ASTContext::getVisibleTopLevelClangModules(
12541251
collectAllModules(Modules);
12551252
}
12561253

1257-
std::pair<ArchetypeBuilder *, GenericEnvironment *>
1258-
ASTContext::getOrCreateArchetypeBuilder(CanGenericSignature sig,
1259-
ModuleDecl *mod) {
1254+
ArchetypeBuilder *ASTContext::getOrCreateArchetypeBuilder(
1255+
CanGenericSignature sig,
1256+
ModuleDecl *mod) {
12601257
// Check whether we already have an archetype builder for this
12611258
// signature and module.
12621259
auto known = Impl.ArchetypeBuilders.find({sig, mod});
12631260
if (known != Impl.ArchetypeBuilders.end())
1264-
return { known->second.first.get(), known->second.second };
1261+
return known->second.get();
12651262

12661263
// Create a new archetype builder with the given signature.
12671264
auto builder = new ArchetypeBuilder(*mod);
12681265
builder->addGenericSignature(sig, nullptr);
1269-
1270-
// Store this archetype builder and its generic environment.
1271-
auto genericEnv = builder->getGenericEnvironment(sig);
1272-
Impl.ArchetypeBuilders[{sig, mod}]
1273-
= { std::unique_ptr<ArchetypeBuilder>(builder), genericEnv };
12741266

1275-
return { builder, genericEnv };
1267+
// Store this archetype builder (no generic environment yet).
1268+
Impl.ArchetypeBuilders[{sig, mod}] =
1269+
std::unique_ptr<ArchetypeBuilder>(builder);
1270+
1271+
return builder;
1272+
}
1273+
1274+
GenericEnvironment *ASTContext::getOrCreateCanonicalGenericEnvironment(
1275+
ArchetypeBuilder *builder) {
1276+
auto known = Impl.CanonicalGenericEnvironments.find(builder);
1277+
if (known != Impl.CanonicalGenericEnvironments.find(builder))
1278+
return known->second;
1279+
1280+
auto sig = builder->getGenericSignature();
1281+
auto env = builder->getGenericEnvironment(sig);
1282+
Impl.CanonicalGenericEnvironments[builder] = env;
1283+
return env;
12761284
}
12771285

12781286
Module *
@@ -3551,22 +3559,30 @@ GenericSignature *GenericSignature::get(ArrayRef<GenericTypeParamType *> params,
35513559
}
35523560

35533561
GenericEnvironment *
3554-
GenericEnvironment::get(ASTContext &ctx,
3555-
GenericSignature *signature,
3562+
GenericEnvironment::get(GenericSignature *signature,
35563563
TypeSubstitutionMap interfaceToArchetypeMap) {
35573564
assert(!interfaceToArchetypeMap.empty());
35583565
assert(interfaceToArchetypeMap.size() == signature->getGenericParams().size()
35593566
&& "incorrect number of parameters");
35603567

3568+
ASTContext &ctx = signature->getASTContext();
35613569

3562-
return new (ctx) GenericEnvironment(signature, interfaceToArchetypeMap);
3570+
// Allocate and construct the new environment.
3571+
size_t bytes = totalSizeToAlloc<Type>(signature->getGenericParams().size());
3572+
void *mem = ctx.Allocate(bytes, alignof(GenericEnvironment));
3573+
return new (mem) GenericEnvironment(signature, nullptr,
3574+
interfaceToArchetypeMap);
35633575
}
35643576

35653577
GenericEnvironment *GenericEnvironment::getIncomplete(
3566-
ASTContext &ctx,
3567-
GenericSignature *signature) {
3578+
GenericSignature *signature,
3579+
ArchetypeBuilder *builder) {
35683580
TypeSubstitutionMap empty;
3569-
return new (ctx) GenericEnvironment(signature, empty);
3581+
auto &ctx = signature->getASTContext();
3582+
// Allocate and construct the new environment.
3583+
size_t bytes = totalSizeToAlloc<Type>(signature->getGenericParams().size());
3584+
void *mem = ctx.Allocate(bytes, alignof(GenericEnvironment));
3585+
return new (mem) GenericEnvironment(signature, builder, empty);
35703586
}
35713587

35723588
void DeclName::CompoundDeclName::Profile(llvm::FoldingSetNodeID &id,
@@ -3886,27 +3902,6 @@ Type ASTContext::getBridgedToObjC(const DeclContext *dc, Type type,
38863902
return Type();
38873903
}
38883904

3889-
std::pair<ArchetypeBuilder *, ArchetypeBuilder::PotentialArchetype *>
3890-
ASTContext::getLazyArchetype(const ArchetypeType *archetype) {
3891-
auto known = Impl.LazyArchetypes.find(archetype);
3892-
assert(known != Impl.LazyArchetypes.end());
3893-
return known->second;
3894-
}
3895-
3896-
void ASTContext::registerLazyArchetype(
3897-
const ArchetypeType *archetype,
3898-
ArchetypeBuilder &builder,
3899-
ArchetypeBuilder::PotentialArchetype *potentialArchetype) {
3900-
assert(Impl.LazyArchetypes.count(archetype) == 0);
3901-
Impl.LazyArchetypes[archetype] = { &builder, potentialArchetype };
3902-
}
3903-
3904-
void ASTContext::unregisterLazyArchetype(const ArchetypeType *archetype) {
3905-
auto known = Impl.LazyArchetypes.find(archetype);
3906-
assert(known != Impl.LazyArchetypes.end());
3907-
Impl.LazyArchetypes.erase(known);
3908-
}
3909-
39103905
const InheritedNameSet *ASTContext::getAllPropertyNames(ClassDecl *classDecl,
39113906
bool forInstance) {
39123907
// If this class was defined in Objective-C, perform the lookup based on

0 commit comments

Comments
 (0)