22
22
#include " swift/AST/SubstitutionList.h"
23
23
#include " swift/AST/Type.h"
24
24
#include " llvm/ADT/ArrayRef.h"
25
+ #include " llvm/ADT/DenseMapInfo.h"
25
26
#include " llvm/ADT/FoldingSet.h"
26
27
#include " llvm/ADT/Optional.h"
27
28
#include " llvm/Support/TrailingObjects.h"
@@ -48,13 +49,18 @@ enum class CombineSubstitutionMaps {
48
49
// / abstract types to replacement types, together with associated conformances
49
50
// / to use for deriving nested types and conformances.
50
51
// /
51
- // / Depending on how the SubstitutionMap is constructed, the abstract types are
52
- // / either archetypes or interface types. Care must be exercised to only look
53
- // / up one or the other .
52
+ // / Substitution maps are primarily used when performing substitutions into
53
+ // / any entity that can reference type parameters, e.g., types (via
54
+ // / Type::subst()) and conformances (via ProtocolConformanceRef::subst()) .
54
55
// /
55
56
// / SubstitutionMaps are constructed by calling the getSubstitutionMap() method
56
57
// / on a GenericSignature or (equivalently) by calling one of the static
57
- // / \c SubstitutionMap::get() methods.
58
+ // / \c SubstitutionMap::get() methods. However, most substitution maps are
59
+ // / computed using higher-level entry points such as
60
+ // / TypeBase::getMemberSubstitutionMap().
61
+ // /
62
+ // / Substitution maps are ASTContext-allocated and are uniqued on construction,
63
+ // / so they can be used as fields in AST nodes.
58
64
class SubstitutionMap {
59
65
public:
60
66
// / Stored data for a substitution map, which uses tail allocation for the
@@ -149,25 +155,10 @@ class SubstitutionMap {
149
155
// / signature nor any replacement types/conformances.
150
156
Storage *storage = nullptr ;
151
157
152
- // / Retrieve the array of replacement types, which line up with the
153
- // / generic parameters.
154
- // /
155
- // / Note that the types may be null, for cases where the generic parameter
156
- // / is concrete but hasn't been queried yet.
157
- ArrayRef<Type> getReplacementTypes () const {
158
- return storage ? storage->getReplacementTypes () : ArrayRef<Type>();
159
- }
160
-
161
158
MutableArrayRef<Type> getReplacementTypes () {
162
159
return storage ? storage->getReplacementTypes () : MutableArrayRef<Type>();
163
160
}
164
161
165
- // / Retrieve the array of protocol conformances, which line up with the
166
- // / requirements of the generic signature.
167
- ArrayRef<ProtocolConformanceRef> getConformances () const {
168
- return storage ? storage->getConformances ()
169
- : ArrayRef<ProtocolConformanceRef>();
170
- }
171
162
MutableArrayRef<ProtocolConformanceRef> getConformances () {
172
163
return storage ? storage->getConformances ()
173
164
: MutableArrayRef<ProtocolConformanceRef>();
@@ -180,10 +171,21 @@ class SubstitutionMap {
180
171
ArrayRef<ProtocolConformanceRef> conformances)
181
172
: storage(Storage::get(genericSig, replacementTypes, conformances)) { }
182
173
174
+ explicit SubstitutionMap (Storage *storage) : storage(storage) { }
175
+
183
176
public:
184
177
// / Build an empty substitution map.
185
178
SubstitutionMap () { }
186
179
180
+ // / Build an interface type substitution map for the given generic
181
+ // / signature and a vector of Substitutions that correspond to the
182
+ // / requirements of this generic signature.
183
+ static SubstitutionMap get (GenericSignature *genericSig,
184
+ ArrayRef<Type> replacementTypes,
185
+ ArrayRef<ProtocolConformanceRef> conformances) {
186
+ return SubstitutionMap (genericSig, replacementTypes, conformances);
187
+ }
188
+
187
189
// / Build an interface type substitution map for the given generic
188
190
// / signature and a vector of Substitutions that correspond to the
189
191
// / requirements of this generic signature.
@@ -202,13 +204,32 @@ class SubstitutionMap {
202
204
return storage ? storage->getGenericSignature () : nullptr ;
203
205
}
204
206
207
+ // / Retrieve the array of protocol conformances, which line up with the
208
+ // / requirements of the generic signature.
209
+ ArrayRef<ProtocolConformanceRef> getConformances () const {
210
+ return storage ? storage->getConformances ()
211
+ : ArrayRef<ProtocolConformanceRef>();
212
+ }
213
+
205
214
// / Look up a conformance for the given type to the given protocol.
206
215
Optional<ProtocolConformanceRef>
207
216
lookupConformance (CanType type, ProtocolDecl *proto) const ;
208
217
209
218
// / Whether the substitution map is empty.
210
219
bool empty () const { return getGenericSignature () == nullptr ; }
211
220
221
+ // / Whether the substitution map is non-empty.
222
+ explicit operator bool () const { return !empty (); }
223
+
224
+ // / Retrieve the array of replacement types, which line up with the
225
+ // / generic parameters.
226
+ // /
227
+ // / Note that the types may be null, for cases where the generic parameter
228
+ // / is concrete but hasn't been queried yet.
229
+ ArrayRef<Type> getReplacementTypes () const {
230
+ return storage ? storage->getReplacementTypes () : ArrayRef<Type>();
231
+ }
232
+
212
233
// / Query whether any replacement types in the map contain archetypes.
213
234
bool hasArchetypes () const ;
214
235
@@ -287,6 +308,22 @@ class SubstitutionMap {
287
308
// / Profile the substitution map, for use with LLVM's FoldingSet.
288
309
void profile (llvm::FoldingSetNodeID &id) const ;
289
310
311
+ const void *getOpaqueValue () const { return storage; }
312
+
313
+ static SubstitutionMap getFromOpaqueValue (const void *ptr) {
314
+ return SubstitutionMap (const_cast <Storage *>((const Storage *)ptr));
315
+ }
316
+
317
+ static SubstitutionMap getEmptyKey () {
318
+ return SubstitutionMap (
319
+ (Storage *)llvm::DenseMapInfo<void *>::getEmptyKey ());
320
+ }
321
+
322
+ static SubstitutionMap getTombstoneKey () {
323
+ return SubstitutionMap (
324
+ (Storage *)llvm::DenseMapInfo<void *>::getTombstoneKey ());
325
+ }
326
+
290
327
private:
291
328
friend class GenericSignature ;
292
329
friend class GenericEnvironment ;
@@ -301,4 +338,37 @@ class SubstitutionMap {
301
338
302
339
} // end namespace swift
303
340
341
+ namespace llvm {
342
+ template <>
343
+ struct PointerLikeTypeTraits <swift::SubstitutionMap> {
344
+ static void *getAsVoidPointer (swift::SubstitutionMap map) {
345
+ return const_cast <void *>(map.getOpaqueValue ());
346
+ }
347
+ static swift::SubstitutionMap getFromVoidPointer (const void *ptr) {
348
+ return swift::SubstitutionMap::getFromOpaqueValue (ptr);
349
+ }
350
+
351
+ // / Note: Assuming storage is at leaste 4-byte aligned.
352
+ enum { NumLowBitsAvailable = 2 };
353
+ };
354
+
355
+ // Substitution maps hash just like pointers.
356
+ template <> struct DenseMapInfo <swift::SubstitutionMap> {
357
+ static swift::SubstitutionMap getEmptyKey () {
358
+ return swift::SubstitutionMap::getEmptyKey ();
359
+ }
360
+ static swift::SubstitutionMap getTombstoneKey () {
361
+ return swift::SubstitutionMap::getTombstoneKey ();
362
+ }
363
+ static unsigned getHashValue (swift::SubstitutionMap map) {
364
+ return DenseMapInfo<void *>::getHashValue (map.getOpaqueValue ());
365
+ }
366
+ static bool isEqual (swift::SubstitutionMap lhs,
367
+ swift::SubstitutionMap rhs) {
368
+ return lhs.getOpaqueValue () == rhs.getOpaqueValue ();
369
+ }
370
+ };
371
+
372
+ }
373
+
304
374
#endif
0 commit comments