Skip to content

Commit c965a3c

Browse files
committed
AST: Replace ASTContext::getOrCreateArchetypeBuilder() with getCanonicalGenericEnvironment()
Instead of keeping around an entire ArchetypeBuilder, it suffices to build a GenericEnvironment instead, and use it for queries by mapping interface types to archetypes.
1 parent f562aca commit c965a3c

File tree

12 files changed

+114
-201
lines changed

12 files changed

+114
-201
lines changed

include/swift/AST/ASTContext.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ namespace swift {
5858
class ExtensionDecl;
5959
class ForeignRepresentationInfo;
6060
class FuncDecl;
61+
class GenericEnvironment;
6162
class InFlightDiagnostic;
6263
class LazyResolver;
6364
class PatternBindingDecl;
@@ -773,10 +774,10 @@ class ASTContext {
773774
/// not necessarily loaded.
774775
void getVisibleTopLevelClangModules(SmallVectorImpl<clang::Module*> &Modules) const;
775776

776-
/// Retrieve or create the stored archetype builder for the given
777+
/// Retrieve or create the canonical GenericEnvironment for the given
777778
/// canonical generic signature and module.
778-
ArchetypeBuilder *getOrCreateArchetypeBuilder(CanGenericSignature sig,
779-
ModuleDecl *mod);
779+
GenericEnvironment *getCanonicalGenericEnvironment(CanGenericSignature sig,
780+
ModuleDecl *mod);
780781

781782
/// Retrieve the inherited name set for the given class.
782783
const InheritedNameSet *getAllPropertyNames(ClassDecl *classDecl,

include/swift/AST/GenericSignature.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,8 @@ class alignas(1 << TypeAlignInBits) GenericSignature final
139139
static ASTContext &getASTContext(ArrayRef<GenericTypeParamType *> params,
140140
ArrayRef<Requirement> requirements);
141141

142-
/// Retrieve the archetype builder for the given generic signature.
143-
ArchetypeBuilder *getArchetypeBuilder(ModuleDecl &mod);
142+
/// Retrieve the canonical generic environment for this generic signature.
143+
GenericEnvironment *getCanonicalGenericEnvironment(ModuleDecl &mod);
144144

145145
public:
146146
/// Create a new generic signature with the given type parameters and
@@ -233,10 +233,9 @@ class alignas(1 << TypeAlignInBits) GenericSignature final
233233
/// Determine the superclass bound on the given dependent type.
234234
Type getSuperclassBound(Type type, ModuleDecl &mod);
235235

236-
using ConformsToArray = SmallVector<ProtocolDecl *, 2>;
237236
/// Determine the set of protocols to which the given dependent type
238237
/// must conform.
239-
ConformsToArray getConformsTo(Type type, ModuleDecl &mod);
238+
ArrayRef<ProtocolDecl *> getConformsTo(Type type, ModuleDecl &mod);
240239

241240
/// Determine whether the given dependent type is equal to a concrete type.
242241
bool isConcreteType(Type type, ModuleDecl &mod);

lib/AST/ASTContext.cpp

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,9 @@ struct ASTContext::Implementation {
215215
ArchetypeBuilder::PotentialArchetype *>>
216216
LazyArchetypes;
217217

218-
/// \brief Stored archetype builders.
218+
/// \brief Stored canonical generic environments.
219219
llvm::DenseMap<std::pair<GenericSignature *, ModuleDecl *>,
220-
std::unique_ptr<ArchetypeBuilder>> ArchetypeBuilders;
220+
GenericEnvironment *> GenericEnvironments;
221221

222222
/// The set of property names that show up in the defining module of a
223223
/// class.
@@ -1268,24 +1268,26 @@ void ASTContext::getVisibleTopLevelClangModules(
12681268
collectAllModules(Modules);
12691269
}
12701270

1271-
ArchetypeBuilder *ASTContext::getOrCreateArchetypeBuilder(
1272-
CanGenericSignature sig,
1273-
ModuleDecl *mod) {
1274-
// Check whether we already have an archetype builder for this
1271+
GenericEnvironment *
1272+
ASTContext::getCanonicalGenericEnvironment(CanGenericSignature sig,
1273+
ModuleDecl *mod) {
1274+
// Check whether we already have a generic environment for this
12751275
// signature and module.
1276-
auto known = Impl.ArchetypeBuilders.find({sig, mod});
1277-
if (known != Impl.ArchetypeBuilders.end())
1278-
return known->second.get();
1276+
auto known = Impl.GenericEnvironments.find({sig, mod});
1277+
if (known != Impl.GenericEnvironments.end())
1278+
return known->second;
12791279

12801280
// Create a new archetype builder with the given signature.
1281-
auto builder = new ArchetypeBuilder(*mod, Diags);
1282-
builder->addGenericSignature(sig, nullptr,
1283-
/*treatRequirementsAsExplicit=*/true);
1284-
1285-
// Store this archetype builder.
1286-
Impl.ArchetypeBuilders[{sig, mod}]
1287-
= std::unique_ptr<ArchetypeBuilder>(builder);
1288-
return builder;
1281+
ArchetypeBuilder builder(*mod, Diags);
1282+
builder.addGenericSignature(sig, nullptr,
1283+
/*treatRequirementsAsExplicit=*/true);
1284+
1285+
// Get the generic environment from the builder.
1286+
auto *env = builder.getGenericEnvironment();
1287+
1288+
// Store this generic environment.
1289+
Impl.GenericEnvironments[{sig, mod}] = env;
1290+
return env;
12891291
}
12901292

12911293
Module *

lib/AST/GenericSignature.cpp

Lines changed: 41 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
//===----------------------------------------------------------------------===//
1616

1717
#include "swift/AST/GenericSignature.h"
18+
#include "swift/AST/GenericEnvironment.h"
1819
#include "swift/AST/ASTContext.h"
1920
#include "swift/AST/Decl.h"
2021
#include "swift/AST/Module.h"
@@ -68,14 +69,15 @@ ASTContext &GenericSignature::getASTContext(
6869
return requirements.front().getFirstType()->getASTContext();
6970
}
7071

71-
ArchetypeBuilder *GenericSignature::getArchetypeBuilder(ModuleDecl &mod) {
72-
// The archetype builder is associated with the canonical signature.
72+
GenericEnvironment *
73+
GenericSignature::getCanonicalGenericEnvironment(ModuleDecl &mod) {
74+
// The generic environment is associated with the canonical signature.
7375
if (!isCanonical())
74-
return getCanonicalSignature()->getArchetypeBuilder(mod);
76+
return getCanonicalSignature()->getCanonicalGenericEnvironment(mod);
7577

7678
// Archetype builders are stored on the ASTContext.
77-
return getASTContext().getOrCreateArchetypeBuilder(CanGenericSignature(this),
78-
&mod);
79+
return getASTContext().getCanonicalGenericEnvironment(
80+
CanGenericSignature(this), &mod);
7981
}
8082

8183
bool GenericSignature::isCanonical() const {
@@ -248,70 +250,37 @@ getSubstitutions(ModuleDecl &mod,
248250
bool GenericSignature::requiresClass(Type type, ModuleDecl &mod) {
249251
if (!type->isTypeParameter()) return false;
250252

251-
auto &builder = *getArchetypeBuilder(mod);
252-
auto pa = builder.resolveArchetype(type);
253-
if (!pa) return false;
254-
255-
pa = pa->getRepresentative();
256-
257-
// If this type was mapped to a concrete type, then there is no
258-
// requirement.
259-
if (pa->isConcreteType()) return false;
260-
261-
// If there is a superclass bound, then obviously it must be a class.
262-
if (pa->getSuperclass()) return true;
263-
264-
// If any of the protocols are class-bound, then it must be a class.
265-
for (auto proto : pa->getConformsTo()) {
266-
if (proto.first->requiresClass()) return true;
267-
}
268-
253+
auto genericEnv = getCanonicalGenericEnvironment(mod);
254+
auto contextTy = genericEnv->mapTypeIntoContext(&mod, type);
255+
if (auto *archetypeTy = contextTy->getAs<ArchetypeType>())
256+
return archetypeTy->requiresClass();
269257
return false;
270258
}
271259

272260
/// Determine the superclass bound on the given dependent type.
273261
Type GenericSignature::getSuperclassBound(Type type, ModuleDecl &mod) {
274262
if (!type->isTypeParameter()) return nullptr;
275263

276-
auto &builder = *getArchetypeBuilder(mod);
277-
auto pa = builder.resolveArchetype(type);
278-
if (!pa) return nullptr;
279-
280-
pa = pa->getRepresentative();
281-
282-
// If this type was mapped to a concrete type, then there is no
283-
// requirement.
284-
if (pa->isConcreteType()) return nullptr;
264+
auto genericEnv = getCanonicalGenericEnvironment(mod);
265+
auto contextTy = genericEnv->mapTypeIntoContext(&mod, type);
266+
if (auto *archetypeTy = contextTy->getAs<ArchetypeType>())
267+
return archetypeTy->getSuperclass();
285268

286-
// Retrieve the superclass bound.
287-
return pa->getSuperclass();
269+
return Type();
288270
}
289271

290272
/// Determine the set of protocols to which the given dependent type
291273
/// must conform.
292-
SmallVector<ProtocolDecl *, 2> GenericSignature::getConformsTo(Type type,
293-
ModuleDecl &mod) {
274+
ArrayRef<ProtocolDecl *> GenericSignature::getConformsTo(Type type,
275+
ModuleDecl &mod) {
294276
if (!type->isTypeParameter()) return { };
295277

296-
auto &builder = *getArchetypeBuilder(mod);
297-
auto pa = builder.resolveArchetype(type);
298-
if (!pa) return { };
278+
auto genericEnv = getCanonicalGenericEnvironment(mod);
279+
auto contextTy = genericEnv->mapTypeIntoContext(&mod, type);
280+
if (auto *archetypeTy = contextTy->getAs<ArchetypeType>())
281+
return archetypeTy->getConformsTo();
299282

300-
pa = pa->getRepresentative();
301-
302-
// If this type was mapped to a concrete type, then there are no
303-
// requirements.
304-
if (pa->isConcreteType()) return { };
305-
306-
// Retrieve the protocols to which this type conforms.
307-
SmallVector<ProtocolDecl *, 2> result;
308-
for (auto proto : pa->getConformsTo())
309-
result.push_back(proto.first);
310-
311-
// Canonicalize the resulting set of protocols.
312-
ProtocolType::canonicalizeProtocols(result);
313-
314-
return result;
283+
return { };
315284
}
316285

317286
/// Determine whether the given dependent type is equal to a concrete type.
@@ -325,29 +294,18 @@ bool GenericSignature::isConcreteType(Type type, ModuleDecl &mod) {
325294
Type GenericSignature::getConcreteType(Type type, ModuleDecl &mod) {
326295
if (!type->isTypeParameter()) return Type();
327296

328-
auto &builder = *getArchetypeBuilder(mod);
329-
auto pa = builder.resolveArchetype(type);
330-
if (!pa) return Type();
331-
332-
pa = pa->getRepresentative();
333-
if (!pa->isConcreteType()) return Type();
297+
auto genericEnv = getCanonicalGenericEnvironment(mod);
298+
auto contextTy = genericEnv->mapTypeIntoContext(&mod, type);
299+
if (contextTy->is<ArchetypeType>())
300+
return Type();
334301

335-
return pa->getConcreteType();
302+
return contextTy;
336303
}
337304

338305
Type GenericSignature::getRepresentative(Type type, ModuleDecl &mod) {
339-
assert(type->isTypeParameter());
340-
auto &builder = *getArchetypeBuilder(mod);
341-
auto pa = builder.resolveArchetype(type);
342-
assert(pa && "not a valid dependent type of this signature?");
343-
auto rep = pa->getRepresentative();
344-
if (rep->isConcreteType()) return rep->getConcreteType();
345-
if (pa == rep) {
346-
assert(rep->getDependentType(builder, /*allowUnresolved*/ false)
347-
->getCanonicalType() == type->getCanonicalType());
348-
return type;
349-
}
350-
return rep->getDependentType(builder, /*allowUnresolved*/ false);
306+
auto genericEnv = getCanonicalGenericEnvironment(mod);
307+
auto contextTy = genericEnv->mapTypeIntoContext(&mod, type);
308+
return genericEnv->mapTypeOutOfContext(&mod, contextTy)->getCanonicalType();
351309
}
352310

353311
bool GenericSignature::areSameTypeParameterInContext(Type type1, Type type2,
@@ -358,18 +316,10 @@ bool GenericSignature::areSameTypeParameterInContext(Type type1, Type type2,
358316
if (type1.getPointer() == type2.getPointer())
359317
return true;
360318

361-
auto &builder = *getArchetypeBuilder(mod);
362-
auto pa1 = builder.resolveArchetype(type1);
363-
assert(pa1 && "not a valid dependent type of this signature?");
364-
pa1 = pa1->getRepresentative();
365-
assert(!pa1->isConcreteType());
366-
367-
auto pa2 = builder.resolveArchetype(type2);
368-
assert(pa2 && "not a valid dependent type of this signature?");
369-
pa2 = pa2->getRepresentative();
370-
assert(!pa2->isConcreteType());
371-
372-
return pa1 == pa2;
319+
auto genericEnv = getCanonicalGenericEnvironment(mod);
320+
auto first = genericEnv->mapTypeIntoContext(&mod, type1);
321+
auto second = genericEnv->mapTypeIntoContext(&mod, type2);
322+
return first->isEqual(second);
373323
}
374324

375325
bool GenericSignature::isCanonicalTypeInContext(Type type, ModuleDecl &mod) {
@@ -383,48 +333,13 @@ bool GenericSignature::isCanonicalTypeInContext(Type type, ModuleDecl &mod) {
383333
if (!type->hasTypeParameter())
384334
return true;
385335

386-
auto &builder = *getArchetypeBuilder(mod);
387-
388-
// Look for non-canonical type parameters.
389-
return !type.findIf([&](Type component) -> bool {
390-
if (!component->isTypeParameter()) return false;
391-
392-
auto pa = builder.resolveArchetype(component);
393-
if (!pa) return false;
394-
395-
auto rep = pa->getArchetypeAnchor();
396-
return (rep->isConcreteType() || pa != rep);
397-
});
336+
auto genericEnv = getCanonicalGenericEnvironment(mod);
337+
auto contextTy = genericEnv->mapTypeIntoContext(&mod, type);
338+
return type->isEqual(genericEnv->mapTypeOutOfContext(&mod, contextTy));
398339
}
399340

400341
CanType GenericSignature::getCanonicalTypeInContext(Type type, ModuleDecl &mod) {
401-
type = type->getCanonicalType();
402-
403-
// All the contextual canonicality rules apply to type parameters, so if the
404-
// type doesn't involve any type parameters, it's already canonical.
405-
if (!type->hasTypeParameter())
406-
return CanType(type);
407-
408-
auto &builder = *getArchetypeBuilder(mod);
409-
410-
// Replace non-canonical type parameters.
411-
type = type.transform([&](Type component) -> Type {
412-
if (!component->isTypeParameter()) return component;
413-
414-
// Resolve the potential archetype. This can be null in nested generic
415-
// types, which we can't immediately canonicalize.
416-
auto pa = builder.resolveArchetype(component);
417-
if (!pa) return component;
418-
419-
auto rep = pa->getArchetypeAnchor();
420-
if (rep->isConcreteType()) {
421-
return getCanonicalTypeInContext(rep->getConcreteType(), mod);
422-
} else {
423-
return rep->getDependentType(builder, /*allowUnresolved*/ false);
424-
}
425-
});
426-
427-
auto result = type->getCanonicalType();
428-
assert(isCanonicalTypeInContext(result, mod));
429-
return result;
342+
auto genericEnv = getCanonicalGenericEnvironment(mod);
343+
auto contextTy = genericEnv->mapTypeIntoContext(&mod, type);
344+
return genericEnv->mapTypeOutOfContext(&mod, contextTy)->getCanonicalType();
430345
}

lib/IRGen/Fulfillment.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,8 @@ bool FulfillmentMap::Everything
328328
::hasLimitedInterestingConformances(CanType type) const {
329329
return false;
330330
}
331-
GenericSignature::ConformsToArray
331+
332+
ArrayRef<ProtocolDecl *>
332333
FulfillmentMap::Everything::getInterestingConformances(CanType type) const{
333334
return {};
334335
}

lib/IRGen/Fulfillment.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class FulfillmentMap {
6363
virtual bool hasLimitedInterestingConformances(CanType type) const = 0;
6464

6565
/// Return the limited interesting conformances for an interesting type.
66-
virtual GenericSignature::ConformsToArray
66+
virtual ArrayRef<ProtocolDecl *>
6767
getInterestingConformances(CanType type) const = 0;
6868

6969
virtual ~InterestingKeysCallback() = default;
@@ -75,7 +75,7 @@ class FulfillmentMap {
7575
bool isInterestingType(CanType type) const override;
7676
bool hasInterestingType(CanType type) const override;
7777
bool hasLimitedInterestingConformances(CanType type) const override;
78-
GenericSignature::ConformsToArray
78+
ArrayRef<ProtocolDecl *>
7979
getInterestingConformances(CanType type) const override;
8080
};
8181

lib/IRGen/GenCall.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,16 +1183,15 @@ void CallEmission::emitToMemory(Address addr,
11831183
// We're never being asked to do anything with *formal*
11841184
// indirect results here, just the possibility of a direct-in-SIL
11851185
// result that's actually being passed indirectly.
1186-
CanType origResultType = origFnType->getSILResult().getSwiftRValueType();
1186+
SILType origResultType = origFnType->getSILResult();
11871187
CanType substResultType = substFnType->getSILResult().getSwiftRValueType();
11881188

1189-
if (origResultType->hasTypeParameter())
1190-
origResultType = IGF.IGM.getContextArchetypes()
1191-
.substDependentType(origResultType)
1192-
->getCanonicalType();
1189+
if (origResultType.hasTypeParameter())
1190+
origResultType = IGF.IGM.mapTypeIntoContext(origResultType);
11931191

1194-
if (origResultType != substResultType) {
1195-
auto origTy = IGF.IGM.getStoragePointerTypeForLowered(origResultType);
1192+
if (origResultType.getSwiftRValueType() != substResultType) {
1193+
auto origTy = IGF.IGM.getStoragePointerTypeForLowered(
1194+
origResultType.getSwiftRValueType());
11961195
origAddr = IGF.Builder.CreateBitCast(origAddr, origTy);
11971196
}
11981197

0 commit comments

Comments
 (0)