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,9 +111,37 @@ Type SubstitutionMap::lookupSubstitution(CanSubstitutableType type) const {
70
111
genericEnv->mapTypeOutOfContext (archetype)->getCanonicalType ());
71
112
}
72
113
73
- auto known = subMap.find (cast<GenericTypeParamType>(type));
74
- if (known != subMap.end () && known->second )
75
- return known->second ;
114
+ // Find the index of the replacement type based on the generic parameter we
115
+ // have.
116
+ auto genericParam = cast<GenericTypeParamType>(type);
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;
132
+
133
+ // The generic parameter may have been made concrete by the generic signature,
134
+ // substitute into the concrete type.
135
+ ModuleDecl &anyModule = *genericParam->getASTContext ().getStdlibModule ();
136
+ auto genericSig = getGenericSignature ();
137
+ if (auto concreteType = genericSig->getConcreteType (genericParam, anyModule)){
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;
144
+ }
76
145
77
146
// Not known.
78
147
return Type ();
@@ -82,9 +151,15 @@ void SubstitutionMap::
82
151
addSubstitution (CanGenericTypeParamType type, Type replacement) {
83
152
assert (getGenericSignature () &&
84
153
" cannot add entries to empty substitution map" );
85
- auto result = subMap.insert (std::make_pair (type, replacement));
86
- assert (result.second || result.first ->second ->isEqual (replacement));
87
- (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;
88
163
}
89
164
90
165
Optional<ProtocolConformanceRef>
@@ -202,11 +277,11 @@ SubstitutionMap SubstitutionMap::subst(TypeSubstitutionFn subs,
202
277
LookupConformanceFn conformances) const {
203
278
SubstitutionMap result (*this );
204
279
205
- for (auto iter = result.subMap . begin (),
206
- end = result. subMap . end ();
207
- iter != end; ++iter) {
208
- iter-> second = iter-> second . subst (subs, conformances,
209
- SubstFlags::UseErrorType);
280
+ for (auto &replacementType : result.getReplacementTypes ()) {
281
+ if (replacementType) {
282
+ replacementType = replacementType. subst (subs, conformances,
283
+ SubstFlags::UseErrorType);
284
+ }
210
285
}
211
286
212
287
for (auto iter = result.conformanceMap .begin (),
@@ -412,11 +487,16 @@ void SubstitutionMap::dump(llvm::raw_ostream &out) const {
412
487
genericSig->print (out);
413
488
out << " \n " ;
414
489
out << " Substitutions:\n " ;
415
- for (const auto &sub : subMap) {
490
+ auto genericParams = genericSig->getGenericParams ();
491
+ auto replacementTypes = getReplacementTypes ();
492
+ for (unsigned i : indices (genericParams)) {
416
493
out.indent (2 );
417
- sub. first ->print (out);
494
+ genericParams[i] ->print (out);
418
495
out << " -> " ;
419
- sub.second ->print (out);
496
+ if (replacementTypes[i])
497
+ replacementTypes[i]->print (out);
498
+ else
499
+ out << " <<unresolved concrete type>>" ;
420
500
out << " \n " ;
421
501
}
422
502
0 commit comments