Skip to content

Commit 9c0de31

Browse files
committed
AST: Simpler implementation of mapTypeOutOfContext()
Now that archetypes store an interface type, GenericEnvironments no longer need to store a reverse mapping.
1 parent 9579c9e commit 9c0de31

File tree

3 files changed

+5
-181
lines changed

3 files changed

+5
-181
lines changed

include/swift/AST/GenericEnvironment.h

Lines changed: 1 addition & 58 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;

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/GenericEnvironment.cpp

Lines changed: 3 additions & 121 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(
@@ -160,7 +108,9 @@ GenericEnvironment::mapTypeOutOfContext(GenericEnvironment *env,
160108
}
161109

162110
Type GenericEnvironment::mapTypeOutOfContext(Type type) const {
163-
type = type.subst(QueryArchetypeToInterfaceSubstitutions(this),
111+
type = type.subst([&](SubstitutableType *t) -> Type {
112+
return cast<ArchetypeType>(t)->getInterfaceType();
113+
},
164114
MakeAbstractConformanceForGenericType(),
165115
SubstFlags::AllowLoweredTypes);
166116
assert(!type->hasArchetype() && "not fully substituted");
@@ -204,74 +154,6 @@ Type GenericEnvironment::QueryInterfaceTypeSubstitutions::operator()(
204154
return Type();
205155
}
206156

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

0 commit comments

Comments
 (0)