12
12
//
13
13
// This file defines the SubstitutionMap class.
14
14
//
15
- // This is a data structure type describing the mapping of abstract types to
16
- // replacement types, together with associated conformances to use for deriving
17
- // nested types.
18
- //
19
- // Depending on how the SubstitutionMap is constructed, the abstract types are
20
- // either archetypes or interface types. Care must be exercised to only look up
21
- // one or the other.
22
- //
23
- // SubstitutionMaps are constructed by calling the getSubstitutionMap() method
24
- // on a GenericSignature or GenericEnvironment.
25
- //
26
15
// ===----------------------------------------------------------------------===//
27
16
28
17
#ifndef SWIFT_AST_SUBSTITUTION_MAP_H
29
18
#define SWIFT_AST_SUBSTITUTION_MAP_H
30
19
20
+ #include " swift/AST/GenericSignature.h"
31
21
#include " swift/AST/ProtocolConformanceRef.h"
22
+ #include " swift/AST/SubstitutionList.h"
32
23
#include " swift/AST/Type.h"
33
24
#include " llvm/ADT/ArrayRef.h"
34
- #include " llvm/ADT/DenseMap .h"
25
+ #include " llvm/ADT/FoldingSet .h"
35
26
#include " llvm/ADT/Optional.h"
36
- #include " llvm/ADT/SmallPtrSet.h"
37
- #include " llvm/ADT/SmallVector.h"
27
+ #include " llvm/Support/TrailingObjects.h"
38
28
39
29
namespace llvm {
40
30
class FoldingSetNodeID ;
41
31
}
42
32
43
33
namespace swift {
44
34
45
- class GenericSignature ;
46
35
class GenericEnvironment ;
47
36
class SubstitutableType ;
48
37
typedef CanTypeWrapper<GenericTypeParamType> CanGenericTypeParamType;
@@ -55,48 +44,165 @@ enum class CombineSubstitutionMaps {
55
44
AtIndex
56
45
};
57
46
47
+ // / SubstitutionMap is a data structure type that describes the mapping of
48
+ // / abstract types to replacement types, together with associated conformances
49
+ // / to use for deriving nested types and conformances.
50
+ // /
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.
54
+ // /
55
+ // / SubstitutionMaps are constructed by calling the getSubstitutionMap() method
56
+ // / on a GenericSignature or (equivalently) by calling one of the static
57
+ // / \c SubstitutionMap::get() methods.
58
58
class SubstitutionMap {
59
- // / The generic signature for which we are performing substitutions.
60
- GenericSignature *genericSig;
61
-
62
- // / The replacement types for the generic type parameters.
63
- std::unique_ptr<Type[]> replacementTypes;
59
+ public:
60
+ // / Stored data for a substitution map, which uses tail allocation for the
61
+ // / replacement types and conformances.
62
+ class Storage final
63
+ : public llvm::FoldingSetNode,
64
+ llvm::TrailingObjects<Storage, Type, ProtocolConformanceRef>
65
+ {
66
+ friend TrailingObjects;
67
+
68
+ // / The generic signature for which we are performing substitutions.
69
+ GenericSignature * const genericSig;
70
+
71
+ // / The number of conformance requirements, cached to avoid constantly
72
+ // / recomputing it on conformance-buffer access.
73
+ const unsigned numConformanceRequirements;
74
+
75
+ Storage () = delete ;
76
+
77
+ Storage (GenericSignature *genericSig,
78
+ ArrayRef<Type> replacementTypes,
79
+ ArrayRef<ProtocolConformanceRef> conformances);
80
+
81
+ private:
82
+ unsigned getNumReplacementTypes () const {
83
+ return genericSig->getGenericParams ().size ();
84
+ }
85
+
86
+ size_t numTrailingObjects (OverloadToken<Type>) const {
87
+ return getNumReplacementTypes ();
88
+ }
89
+
90
+ size_t numTrailingObjects (OverloadToken<ProtocolConformanceRef>) const {
91
+ return numConformanceRequirements;
92
+ }
93
+
94
+ public:
95
+ // / Form storage for the given generic signature and its replacement
96
+ // / types and conformances.
97
+ static Storage *get (GenericSignature *genericSig,
98
+ ArrayRef<Type> replacementTypes,
99
+ ArrayRef<ProtocolConformanceRef> conformances);
100
+
101
+ // / Retrieve the generic signature that describes the shape of this
102
+ // / storage.
103
+ GenericSignature *getGenericSignature () const { return genericSig; }
104
+
105
+ // / Retrieve the array of replacement types, which line up with the
106
+ // / generic parameters.
107
+ // /
108
+ // / Note that the types may be null, for cases where the generic parameter
109
+ // / is concrete but hasn't been queried yet.
110
+ ArrayRef<Type> getReplacementTypes () const {
111
+ return llvm::makeArrayRef (getTrailingObjects<Type>(),
112
+ getNumReplacementTypes ());
113
+ }
114
+
115
+ MutableArrayRef<Type> getReplacementTypes () {
116
+ return MutableArrayRef<Type>(getTrailingObjects<Type>(),
117
+ getNumReplacementTypes ());
118
+ }
119
+
120
+ // / Retrieve the array of protocol conformances, which line up with the
121
+ // / requirements of the generic signature.
122
+ ArrayRef<ProtocolConformanceRef> getConformances () const {
123
+ return llvm::makeArrayRef (getTrailingObjects<ProtocolConformanceRef>(),
124
+ numConformanceRequirements);
125
+ }
126
+ MutableArrayRef<ProtocolConformanceRef> getConformances () {
127
+ return MutableArrayRef<ProtocolConformanceRef>(
128
+ getTrailingObjects<ProtocolConformanceRef>(),
129
+ numConformanceRequirements);
130
+ }
131
+
132
+ // / Profile the substitution map storage, for use with LLVM's FoldingSet.
133
+ void Profile (llvm::FoldingSetNodeID &id) const {
134
+ Profile (id, getGenericSignature (), getReplacementTypes (),
135
+ getConformances ());
136
+ }
137
+
138
+ // / Profile the substitution map storage, for use with LLVM's FoldingSet.
139
+ static void Profile (llvm::FoldingSetNodeID &id,
140
+ GenericSignature *genericSig,
141
+ ArrayRef<Type> replacementTypes,
142
+ ArrayRef<ProtocolConformanceRef> conformances);
143
+ };
64
144
65
- // FIXME: Switch to a more efficient representation that corresponds to
66
- // the conformance requirements in the GenericSignature.
67
- llvm::DenseMap<CanType, SmallVector<ProtocolConformanceRef, 1 >>
68
- conformanceMap;
145
+ private:
146
+ // / The storage needed to describe the set of substitutions.
147
+ // /
148
+ // / When null, this substitution map is empty, having neither a generic
149
+ // / signature nor any replacement types/conformances.
150
+ Storage *storage = nullptr ;
69
151
70
152
// / Retrieve the array of replacement types, which line up with the
71
153
// / generic parameters.
72
154
// /
73
155
// / Note that the types may be null, for cases where the generic parameter
74
156
// / is concrete but hasn't been queried yet.
75
- ArrayRef<Type> getReplacementTypes () const ;
76
-
77
- MutableArrayRef<Type> getReplacementTypes ();
157
+ ArrayRef<Type> getReplacementTypes () const {
158
+ return storage ? storage->getReplacementTypes () : ArrayRef<Type>();
159
+ }
160
+
161
+ MutableArrayRef<Type> getReplacementTypes () {
162
+ return storage ? storage->getReplacementTypes () : MutableArrayRef<Type>();
163
+ }
164
+
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
+ MutableArrayRef<ProtocolConformanceRef> getConformances () {
172
+ return storage ? storage->getConformances ()
173
+ : MutableArrayRef<ProtocolConformanceRef>();
174
+ }
175
+
176
+ // / Form a substitution map for the given generic signature with the
177
+ // / specified replacement types and conformances.
178
+ SubstitutionMap (GenericSignature *genericSig,
179
+ ArrayRef<Type> replacementTypes,
180
+ ArrayRef<ProtocolConformanceRef> conformances)
181
+ : storage(Storage::get(genericSig, replacementTypes, conformances)) { }
78
182
79
183
public:
80
- SubstitutionMap ()
81
- : SubstitutionMap(static_cast <GenericSignature *>(nullptr )) { }
82
-
83
- SubstitutionMap (GenericSignature *genericSig);
84
-
85
- SubstitutionMap (GenericEnvironment *genericEnv);
86
-
87
- SubstitutionMap (SubstitutionMap &&other) = default ;
88
- SubstitutionMap &operator =(SubstitutionMap &&other) = default ;
184
+ // / Build an empty substitution map.
185
+ SubstitutionMap () { }
89
186
90
- SubstitutionMap (const SubstitutionMap &other);
187
+ // / Build an interface type substitution map for the given generic
188
+ // / signature and a vector of Substitutions that correspond to the
189
+ // / requirements of this generic signature.
190
+ static SubstitutionMap get (GenericSignature *genericSig,
191
+ SubstitutionList substitutions);
91
192
92
- SubstitutionMap &operator =(const SubstitutionMap &other);
93
-
94
- ~SubstitutionMap ();
193
+ // / Build an interface type substitution map for the given generic signature
194
+ // / from a type substitution function and conformance lookup function.
195
+ static SubstitutionMap get (GenericSignature *genericSig,
196
+ TypeSubstitutionFn subs,
197
+ LookupConformanceFn lookupConformance);
95
198
96
199
// / Retrieve the generic signature describing the environment in which
97
200
// / substitutions occur.
98
- GenericSignature *getGenericSignature () const { return genericSig; }
201
+ GenericSignature *getGenericSignature () const {
202
+ return storage ? storage->getGenericSignature () : nullptr ;
203
+ }
99
204
205
+ // / Look up a conformance for the given type to the given protocol.
100
206
Optional<ProtocolConformanceRef>
101
207
lookupConformance (CanType type, ProtocolDecl *proto) const ;
102
208
@@ -191,13 +297,6 @@ class SubstitutionMap {
191
297
// / stored inside the map. In most cases, you should call Type::subst()
192
298
// / instead, since that will resolve member types also.
193
299
Type lookupSubstitution (CanSubstitutableType type) const ;
194
-
195
- // You should not need to call these directly to build SubstitutionMaps;
196
- // instead, use GenericSignature::getSubstitutionMap() or
197
- // GenericEnvironment::getSubstitutionMap().
198
-
199
- void addSubstitution (CanGenericTypeParamType type, Type replacement);
200
- void addConformance (CanType type, ProtocolConformanceRef conformance);
201
300
};
202
301
203
302
} // end namespace swift
0 commit comments