33
33
34
34
using namespace swift ;
35
35
36
+ ArrayRef<Type> SubstitutionMap::getReplacementTypes () const {
37
+ if (empty ()) return { };
38
+
39
+ return llvm::makeArrayRef (replacementTypes.get (),
40
+ genericSig->getGenericParams ().size ());
41
+ }
42
+
43
+ MutableArrayRef<Type> SubstitutionMap::getReplacementTypes () {
44
+ if (empty ()) return { };
45
+
46
+ return MutableArrayRef<Type>(replacementTypes.get (),
47
+ genericSig->getGenericParams ().size ());
48
+
49
+ }
50
+
51
+ SubstitutionMap::SubstitutionMap (GenericSignature *genericSig) : genericSig(genericSig) {
52
+ if (genericSig) {
53
+ replacementTypes.reset (new Type [genericSig->getGenericParams ().size ()]);
54
+ }
55
+ }
56
+
36
57
SubstitutionMap::SubstitutionMap (GenericEnvironment *genericEnv)
37
58
: SubstitutionMap(genericEnv->getGenericSignature ()) { }
38
59
60
+ SubstitutionMap::SubstitutionMap (const SubstitutionMap &other)
61
+ : SubstitutionMap(other.getGenericSignature())
62
+ {
63
+ std::copy (other.getReplacementTypes ().begin (),
64
+ other.getReplacementTypes ().end (),
65
+ getReplacementTypes ().begin ());
66
+
67
+ conformanceMap = other.conformanceMap ;
68
+ }
69
+
70
+ SubstitutionMap &SubstitutionMap::operator =(const SubstitutionMap &other) {
71
+ *this = SubstitutionMap (other);
72
+ return *this ;
73
+ }
74
+
75
+ SubstitutionMap::~SubstitutionMap () { }
76
+
39
77
bool SubstitutionMap::hasArchetypes () const {
40
- for (auto &entry : subMap)
41
- if (entry. second ->hasArchetype ())
78
+ for (Type replacementTy : getReplacementTypes ()) {
79
+ if (replacementTy && replacementTy ->hasArchetype ())
42
80
return true ;
81
+ }
43
82
return false ;
44
83
}
45
84
46
85
bool SubstitutionMap::hasOpenedExistential () const {
47
- for (auto &entry : subMap)
48
- if (entry. second ->hasOpenedExistential ())
86
+ for (Type replacementTy : getReplacementTypes ()) {
87
+ if (replacementTy && replacementTy ->hasOpenedExistential ())
49
88
return true ;
89
+ }
50
90
return false ;
51
91
}
52
92
53
93
bool SubstitutionMap::hasDynamicSelf () const {
54
- for (auto &entry : subMap)
55
- if (entry. second ->hasDynamicSelfType ())
94
+ for (Type replacementTy : getReplacementTypes ()) {
95
+ if (replacementTy && replacementTy ->hasDynamicSelfType ())
56
96
return true ;
97
+ }
57
98
return false ;
58
99
}
59
100
@@ -70,21 +111,36 @@ Type SubstitutionMap::lookupSubstitution(CanSubstitutableType type) const {
70
111
genericEnv->mapTypeOutOfContext (archetype)->getCanonicalType ());
71
112
}
72
113
114
+ // Find the index of the replacement type based on the generic parameter we
115
+ // have.
73
116
auto genericParam = cast<GenericTypeParamType>(type);
74
- auto known = subMap.find (genericParam);
75
- if (known != subMap.end () && known->second )
76
- return known->second ;
117
+ auto mutableThis = const_cast <SubstitutionMap *>(this );
118
+ auto replacementTypes = mutableThis->getReplacementTypes ();
119
+ auto genericParams = getGenericSignature ()->getGenericParams ();
120
+ auto replacementIndex =
121
+ GenericParamKey (genericParam).findIndexIn (genericParams);
122
+
123
+ // If this generic parameter isn't represented, we don't have a replacement
124
+ // type for it.
125
+ if (replacementIndex == genericParams.size ())
126
+ return Type ();
127
+
128
+ // If we already have a replacement type, return it.
129
+ Type &replacementType = replacementTypes[replacementIndex];
130
+ if (replacementType)
131
+ return replacementType;
77
132
78
133
// The generic parameter may have been made concrete by the generic signature,
79
134
// substitute into the concrete type.
80
135
ModuleDecl &anyModule = *genericParam->getASTContext ().getStdlibModule ();
81
136
auto genericSig = getGenericSignature ();
82
137
if (auto concreteType = genericSig->getConcreteType (genericParam, anyModule)){
83
- auto mutableThis = const_cast <SubstitutionMap *>(this );
84
- mutableThis->subMap [genericParam] = ErrorType::get (concreteType);
85
- Type result = concreteType.subst (*this );
86
- mutableThis->subMap [genericParam] = result;
87
- return result;
138
+ // Set the replacement type to an error, to block infinite recursion.
139
+ replacementType = ErrorType::get (concreteType);
140
+
141
+ // Substitute into the replacement type.
142
+ replacementType = concreteType.subst (*this );
143
+ return replacementType;
88
144
}
89
145
90
146
// Not known.
@@ -95,9 +151,15 @@ void SubstitutionMap::
95
151
addSubstitution (CanGenericTypeParamType type, Type replacement) {
96
152
assert (getGenericSignature () &&
97
153
" cannot add entries to empty substitution map" );
98
- auto result = subMap.insert (std::make_pair (type, replacement));
99
- assert (result.second || result.first ->second ->isEqual (replacement));
100
- (void ) result;
154
+
155
+ auto replacementTypes = getReplacementTypes ();
156
+ auto genericParams = getGenericSignature ()->getGenericParams ();
157
+ auto replacementIndex = GenericParamKey (type).findIndexIn (genericParams);
158
+
159
+ assert ((!replacementTypes[replacementIndex] ||
160
+ replacementTypes[replacementIndex]->isEqual (replacement)));
161
+
162
+ replacementTypes[replacementIndex] = replacement;
101
163
}
102
164
103
165
Optional<ProtocolConformanceRef>
@@ -215,11 +277,11 @@ SubstitutionMap SubstitutionMap::subst(TypeSubstitutionFn subs,
215
277
LookupConformanceFn conformances) const {
216
278
SubstitutionMap result (*this );
217
279
218
- for (auto iter = result.subMap . begin (),
219
- end = result. subMap . end ();
220
- iter != end; ++iter) {
221
- iter-> second = iter-> second . subst (subs, conformances,
222
- SubstFlags::UseErrorType);
280
+ for (auto &replacementType : result.getReplacementTypes ()) {
281
+ if (replacementType) {
282
+ replacementType = replacementType. subst (subs, conformances,
283
+ SubstFlags::UseErrorType);
284
+ }
223
285
}
224
286
225
287
for (auto iter = result.conformanceMap .begin (),
@@ -425,11 +487,16 @@ void SubstitutionMap::dump(llvm::raw_ostream &out) const {
425
487
genericSig->print (out);
426
488
out << " \n " ;
427
489
out << " Substitutions:\n " ;
428
- for (const auto &sub : subMap) {
490
+ auto genericParams = genericSig->getGenericParams ();
491
+ auto replacementTypes = getReplacementTypes ();
492
+ for (unsigned i : indices (genericParams)) {
429
493
out.indent (2 );
430
- sub. first ->print (out);
494
+ genericParams[i] ->print (out);
431
495
out << " -> " ;
432
- sub.second ->print (out);
496
+ if (replacementTypes[i])
497
+ replacementTypes[i]->print (out);
498
+ else
499
+ out << " <<unresolved concrete type>>" ;
433
500
out << " \n " ;
434
501
}
435
502
0 commit comments