Skip to content

Commit 488aa70

Browse files
authored
Merge pull request #12329 from slavapestov/archetype-get-interface-type
Archetypes now store an interface type
2 parents f9b481a + 4bd2b30 commit 488aa70

File tree

14 files changed

+48
-233
lines changed

14 files changed

+48
-233
lines changed

include/swift/AST/GenericEnvironment.h

Lines changed: 1 addition & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -37,37 +37,17 @@ class SILType;
3737
/// Describes the mapping between archetypes and interface types for the
3838
/// generic parameters of a DeclContext.
3939
class alignas(1 << DeclAlignInBits) GenericEnvironment final
40-
: private llvm::TrailingObjects<GenericEnvironment, Type,
41-
std::pair<ArchetypeType *,
42-
GenericTypeParamType *>> {
40+
: private llvm::TrailingObjects<GenericEnvironment, Type> {
4341
GenericSignature *Signature = nullptr;
4442
GenericSignatureBuilder *Builder = nullptr;
4543
DeclContext *OwningDC = nullptr;
4644

47-
// The number of generic type parameter -> context type mappings we have
48-
// recorded so far. This saturates at the number of generic type parameters,
49-
// at which point the archetype-to-interface trailing array is sorted.
50-
unsigned NumMappingsRecorded : 16;
51-
52-
// The number of archetype-to-interface type mappings. This is always <=
53-
// \c NumMappingsRecorded.
54-
unsigned NumArchetypeToInterfaceMappings : 16;
55-
5645
friend TrailingObjects;
5746

58-
/// An entry in the array mapping from archetypes to their corresponding
59-
/// generic type parameters.
60-
typedef std::pair<ArchetypeType *, GenericTypeParamType *>
61-
ArchetypeToInterfaceMapping;
62-
6347
size_t numTrailingObjects(OverloadToken<Type>) const {
6448
return Signature->getGenericParams().size();
6549
}
6650

67-
size_t numTrailingObjects(OverloadToken<ArchetypeToInterfaceMapping>) const {
68-
return Signature->getGenericParams().size();
69-
}
70-
7151
/// Retrieve the array containing the context types associated with the
7252
/// generic parameters, stored in parallel with the generic parameters of the
7353
/// generic signature.
@@ -84,30 +64,6 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
8464
Signature->getGenericParams().size());
8565
}
8666

87-
/// Retrieve the active set of archetype-to-interface mappings.
88-
ArrayRef<ArchetypeToInterfaceMapping>
89-
getActiveArchetypeToInterfaceMappings() const {
90-
return { getTrailingObjects<ArchetypeToInterfaceMapping>(),
91-
NumArchetypeToInterfaceMappings };
92-
}
93-
94-
/// Retrieve the active set of archetype-to-interface mappings.
95-
MutableArrayRef<ArchetypeToInterfaceMapping>
96-
getActiveArchetypeToInterfaceMappings() {
97-
return { getTrailingObjects<ArchetypeToInterfaceMapping>(),
98-
NumArchetypeToInterfaceMappings };
99-
}
100-
101-
/// Retrieve the buffer for the archetype-to-interface mappings.
102-
///
103-
/// Only the first \c NumArchetypeToInterfaceMappings elements in the buffer
104-
/// are valid.
105-
MutableArrayRef<ArchetypeToInterfaceMapping>
106-
getArchetypeToInterfaceMappingsBuffer() {
107-
return { getTrailingObjects<ArchetypeToInterfaceMapping>(),
108-
Signature->getGenericParams().size() };
109-
}
110-
11167
GenericEnvironment(GenericSignature *signature,
11268
GenericSignatureBuilder *builder);
11369

@@ -129,19 +85,6 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
12985
};
13086
friend class QueryInterfaceTypeSubstitutions;
13187

132-
/// Query function suitable for use as a \c TypeSubstitutionFn that queries
133-
/// the mapping of archetypes back to interface types.
134-
class QueryArchetypeToInterfaceSubstitutions {
135-
const GenericEnvironment *self;
136-
137-
public:
138-
QueryArchetypeToInterfaceSubstitutions(const GenericEnvironment *self)
139-
: self(self) { }
140-
141-
Type operator()(SubstitutableType *type) const;
142-
};
143-
friend class QueryArchetypeToInterfaceSubstitutions;
144-
14588
public:
14689
GenericSignature *getGenericSignature() const {
14790
return Signature;
@@ -151,10 +94,6 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
15194
return Signature->getGenericParams();
15295
}
15396

154-
/// Determine whether this generic environment contains the given
155-
/// primary archetype.
156-
bool containsPrimaryArchetype(ArchetypeType *archetype) const;
157-
15897
/// Create a new, "incomplete" generic environment that will be populated
15998
/// by calls to \c addMapping().
16099
static

include/swift/AST/Types.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4041,7 +4041,7 @@ class ArchetypeType final : public SubstitutableType,
40414041

40424042
llvm::PointerUnion3<ArchetypeType *, TypeBase *,
40434043
GenericEnvironment *> ParentOrOpenedOrEnvironment;
4044-
llvm::PointerUnion<AssociatedTypeDecl *, Identifier> AssocTypeOrName;
4044+
Type InterfaceType;
40454045
MutableArrayRef<std::pair<Identifier, Type>> NestedTypes;
40464046

40474047
void populateNestedTypes() const;
@@ -4053,7 +4053,7 @@ class ArchetypeType final : public SubstitutableType,
40534053
/// The ConformsTo array will be copied into the ASTContext by this routine.
40544054
static CanTypeWrapper<ArchetypeType>
40554055
getNew(const ASTContext &Ctx, ArchetypeType *Parent,
4056-
AssociatedTypeDecl *AssocType,
4056+
DependentMemberType *InterfaceType,
40574057
SmallVectorImpl<ProtocolDecl *> &ConformsTo,
40584058
Type Superclass, LayoutConstraint Layout);
40594059

@@ -4063,8 +4063,8 @@ class ArchetypeType final : public SubstitutableType,
40634063
/// by this routine.
40644064
static CanTypeWrapper<ArchetypeType>
40654065
getNew(const ASTContext &Ctx,
4066-
GenericEnvironment *genericEnvironment,
4067-
Identifier Name,
4066+
GenericEnvironment *GenericEnv,
4067+
GenericTypeParamType *InterfaceType,
40684068
SmallVectorImpl<ProtocolDecl *> &ConformsTo,
40694069
Type Superclass, LayoutConstraint Layout);
40704070

@@ -4108,15 +4108,17 @@ class ArchetypeType final : public SubstitutableType,
41084108
/// Note: opened archetypes currently don't have generic environments.
41094109
GenericEnvironment *getGenericEnvironment() const;
41104110

4111+
/// Retrieve the interface type of this associated type, which will either
4112+
/// be a GenericTypeParamType or a DependentMemberType.
4113+
Type getInterfaceType() const { return InterfaceType; }
4114+
41114115
/// Retrieve the associated type to which this archetype (if it is a nested
41124116
/// archetype) corresponds.
41134117
///
41144118
/// This associated type will have the same name as the archetype and will
41154119
/// be a member of one of the protocols to which the parent archetype
41164120
/// conforms.
4117-
AssociatedTypeDecl *getAssocType() const {
4118-
return AssocTypeOrName.dyn_cast<AssociatedTypeDecl *>();
4119-
}
4121+
AssociatedTypeDecl *getAssocType() const;
41204122

41214123
/// getConformsTo - Retrieve the set of protocols to which this substitutable
41224124
/// type shall conform.
@@ -4224,7 +4226,7 @@ class ArchetypeType final : public SubstitutableType,
42244226
const ASTContext &Ctx,
42254227
llvm::PointerUnion<ArchetypeType *, GenericEnvironment *>
42264228
ParentOrGenericEnv,
4227-
llvm::PointerUnion<AssociatedTypeDecl *, Identifier> AssocTypeOrName,
4229+
Type InterfaceType,
42284230
ArrayRef<ProtocolDecl *> ConformsTo,
42294231
Type Superclass, LayoutConstraint Layout);
42304232

lib/AST/ASTContext.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4055,8 +4055,7 @@ GenericEnvironment *GenericEnvironment::getIncomplete(
40554055

40564056
// Allocate and construct the new environment.
40574057
unsigned numGenericParams = signature->getGenericParams().size();
4058-
size_t bytes = totalSizeToAlloc<Type, ArchetypeToInterfaceMapping>(
4059-
numGenericParams, numGenericParams);
4058+
size_t bytes = totalSizeToAlloc<Type>(numGenericParams);
40604059
void *mem = ctx.Allocate(bytes, alignof(GenericEnvironment));
40614060
return new (mem) GenericEnvironment(signature, builder);
40624061
}

lib/AST/ASTMangler.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -892,8 +892,7 @@ void ASTMangler::appendType(Type type) {
892892

893893
// Find the archetype information.
894894
const DeclContext *DC = DeclCtx;
895-
auto GTPT = GenericEnvironment::mapTypeOutOfContext(GenericEnv, archetype)
896-
->castTo<GenericTypeParamType>();
895+
auto GTPT = archetype->getInterfaceType()->castTo<GenericTypeParamType>();
897896

898897
// The DWARF output created by Swift is intentionally flat,
899898
// therefore archetypes are emitted with their DeclContext if

lib/AST/ASTVerifier.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,11 +170,11 @@ struct LazyGenericEnvironment {
170170
if (isLazy()) return true;
171171

172172
if (auto genericEnv = storage.dyn_cast<GenericEnvironment *>())
173-
return genericEnv->containsPrimaryArchetype(archetype);
173+
return archetype->getGenericEnvironment() == genericEnv;
174174

175175
if (auto dc = storage.dyn_cast<DeclContext *>()) {
176176
if (auto genericEnv = dc->getGenericEnvironmentOfContext())
177-
return genericEnv->containsPrimaryArchetype(archetype);
177+
return archetype->getGenericEnvironment() == genericEnv;
178178
}
179179

180180
return false;

lib/AST/GenericEnvironment.cpp

Lines changed: 3 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@ GenericEnvironment::GenericEnvironment(GenericSignature *signature,
2525
GenericSignatureBuilder *builder)
2626
: Signature(signature), Builder(builder)
2727
{
28-
NumMappingsRecorded = 0;
29-
NumArchetypeToInterfaceMappings = 0;
30-
3128
// Clear out the memory that holds the context types.
3229
std::uninitialized_fill(getContextTypes().begin(), getContextTypes().end(),
3330
Type());
@@ -73,55 +70,6 @@ void GenericEnvironment::addMapping(GenericParamKey key,
7370
// Add the mapping from the generic parameter to the context type.
7471
assert(getContextTypes()[index].isNull() && "Already recoded this mapping");
7572
getContextTypes()[index] = contextType;
76-
77-
// If we mapped the generic parameter to an archetype, add it to the
78-
// reverse mapping.
79-
if (auto *archetype = contextType->getAs<ArchetypeType>()) {
80-
auto genericParam = genericParams[index];
81-
82-
// Check whether we've already recorded a generic parameter for this
83-
// archetype. Note that we always perform a linear search, because we
84-
// won't have sorted the list yet.
85-
bool found = false;
86-
for (auto &mapping : getActiveArchetypeToInterfaceMappings()) {
87-
if (mapping.first != archetype) continue;
88-
89-
// Multiple generic parameters map to the same archetype. If the
90-
// existing entry comes from a later generic parameter, replace it with
91-
// the earlier generic parameter. This gives us a deterministic reverse
92-
// mapping.
93-
auto otherGP = mapping.second->castTo<GenericTypeParamType>();
94-
if (GenericParamKey(genericParam) < GenericParamKey(otherGP))
95-
mapping.second = genericParam;
96-
found = true;
97-
break;
98-
}
99-
100-
// If we haven't recorded a generic parameter for this archetype, do so now.
101-
if (!found) {
102-
void *ptr = getArchetypeToInterfaceMappingsBuffer().data()
103-
+ NumArchetypeToInterfaceMappings;
104-
new (ptr) ArchetypeToInterfaceMapping(archetype, genericParam);
105-
++NumArchetypeToInterfaceMappings;
106-
}
107-
}
108-
109-
// Note that we've recorded this mapping.
110-
++NumMappingsRecorded;
111-
112-
// If we've recorded all of the mappings, go ahead and sort the array of
113-
// archetype-to-interface-type mappings.
114-
if (NumMappingsRecorded == genericParams.size()) {
115-
llvm::array_pod_sort(getActiveArchetypeToInterfaceMappings().begin(),
116-
getActiveArchetypeToInterfaceMappings().end(),
117-
[](const ArchetypeToInterfaceMapping *lhs,
118-
const ArchetypeToInterfaceMapping *rhs) -> int {
119-
std::less<ArchetypeType *> compare;
120-
if (compare(lhs->first, rhs->first)) return -1;
121-
if (compare(rhs->first, lhs->first)) return 1;
122-
return 0;
123-
});
124-
}
12573
}
12674

12775
Optional<Type> GenericEnvironment::getMappingIfPresent(
@@ -138,12 +86,6 @@ Optional<Type> GenericEnvironment::getMappingIfPresent(
13886
return None;
13987
}
14088

141-
bool GenericEnvironment::containsPrimaryArchetype(
142-
ArchetypeType *archetype) const {
143-
return static_cast<bool>(
144-
QueryArchetypeToInterfaceSubstitutions(this)(archetype));
145-
}
146-
14789
Type GenericEnvironment::mapTypeIntoContext(GenericEnvironment *env,
14890
Type type) {
14991
assert(!type->hasArchetype() && "already have a contextual type");
@@ -166,7 +108,9 @@ GenericEnvironment::mapTypeOutOfContext(GenericEnvironment *env,
166108
}
167109

168110
Type GenericEnvironment::mapTypeOutOfContext(Type type) const {
169-
type = type.subst(QueryArchetypeToInterfaceSubstitutions(this),
111+
type = type.subst([&](SubstitutableType *t) -> Type {
112+
return cast<ArchetypeType>(t)->getInterfaceType();
113+
},
170114
MakeAbstractConformanceForGenericType(),
171115
SubstFlags::AllowLoweredTypes);
172116
assert(!type->hasArchetype() && "not fully substituted");
@@ -210,74 +154,6 @@ Type GenericEnvironment::QueryInterfaceTypeSubstitutions::operator()(
210154
return Type();
211155
}
212156

213-
Type GenericEnvironment::QueryArchetypeToInterfaceSubstitutions::operator()(
214-
SubstitutableType *type) const {
215-
auto archetype = type->getAs<ArchetypeType>();
216-
if (!archetype) return Type();
217-
218-
// Only top-level archetypes need to be substituted directly; nested
219-
// archetypes will be handled via their root archetypes.
220-
if (archetype->getParent()) return Type();
221-
222-
// If not all generic parameters have had their context types recorded,
223-
// perform a linear search.
224-
auto genericParams = self->Signature->getGenericParams();
225-
unsigned numGenericParams = genericParams.size();
226-
if (self->NumMappingsRecorded < numGenericParams) {
227-
// Search through all of the active archetype-to-interface mappings.
228-
for (auto &mapping : self->getActiveArchetypeToInterfaceMappings())
229-
if (mapping.first == archetype) return mapping.second;
230-
231-
// We don't know if the archetype is from a different context or if we
232-
// simply haven't recorded it yet. Spin through all of the generic
233-
// parameters looking for one that provides this mapping.
234-
for (auto gp : genericParams) {
235-
// Map the generic parameter into our context. If we get back an
236-
// archetype that matches, we're done.
237-
auto gpArchetype = self->mapTypeIntoContext(gp)->getAs<ArchetypeType>();
238-
if (gpArchetype == archetype) return gp;
239-
}
240-
241-
// We have checked all of the generic parameters and not found anything;
242-
// there is no substitution.
243-
return Type();
244-
}
245-
246-
// All generic parameters have ad their context types recorded, which means
247-
// that the archetypes-to-interface-types array is sorted by address. Use a
248-
// binary search.
249-
struct MappingComparison {
250-
bool operator()(const ArchetypeToInterfaceMapping &lhs,
251-
const ArchetypeType *rhs) const {
252-
std::less<const ArchetypeType *> compare;
253-
254-
return compare(lhs.first, rhs);
255-
}
256-
257-
bool operator()(const ArchetypeType *lhs,
258-
const ArchetypeToInterfaceMapping &rhs) const {
259-
std::less<const ArchetypeType *> compare;
260-
261-
return compare(lhs, rhs.first);
262-
}
263-
264-
bool operator()(const ArchetypeToInterfaceMapping &lhs,
265-
const ArchetypeToInterfaceMapping &rhs) const {
266-
std::less<const ArchetypeType *> compare;
267-
268-
return compare(lhs.first, rhs.first);
269-
}
270-
} mappingComparison;
271-
272-
auto mappings = self->getActiveArchetypeToInterfaceMappings();
273-
auto known = std::lower_bound(mappings.begin(), mappings.end(), archetype,
274-
mappingComparison);
275-
if (known != mappings.end() && known->first == archetype)
276-
return known->second;
277-
278-
return Type();
279-
}
280-
281157
Type GenericEnvironment::mapTypeIntoContext(
282158
Type type,
283159
LookupConformanceFn lookupConformance) const {

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1856,16 +1856,16 @@ Type EquivalenceClass::getTypeInContext(GenericSignatureBuilder &builder,
18561856
ASTContext &ctx = builder.getASTContext();
18571857
if (parentArchetype) {
18581858
// Create a nested archetype.
1859-
archetype = ArchetypeType::getNew(ctx, parentArchetype, assocType, protos,
1859+
auto *depMemTy = anchor->castTo<DependentMemberType>();
1860+
archetype = ArchetypeType::getNew(ctx, parentArchetype, depMemTy, protos,
18601861
superclass, layout);
18611862

18621863
// Register this archetype with its parent.
18631864
parentArchetype->registerNestedType(assocType->getName(), archetype);
18641865
} else {
18651866
// Create a top-level archetype.
18661867
auto genericParam = anchor->castTo<GenericTypeParamType>();
1867-
Identifier name = genericParam->getName();
1868-
archetype = ArchetypeType::getNew(ctx, genericEnv, name, protos,
1868+
archetype = ArchetypeType::getNew(ctx, genericEnv, genericParam, protos,
18691869
superclass, layout);
18701870

18711871
// Register the archetype with the generic environment.
@@ -2685,8 +2685,7 @@ void ArchetypeType::resolveNestedType(
26852685
auto genericEnv = getGenericEnvironment();
26862686
auto &builder = *genericEnv->getGenericSignatureBuilder();
26872687

2688-
Type interfaceType =
2689-
genericEnv->mapTypeOutOfContext(const_cast<ArchetypeType *>(this));
2688+
Type interfaceType = getInterfaceType();
26902689
Type memberInterfaceType =
26912690
DependentMemberType::get(interfaceType, nested.first);
26922691
auto equivClass =

0 commit comments

Comments
 (0)