1
+ // ===--- ParameterPack.cpp - Utilities for variadic generics --------------===//
2
+ //
3
+ // This source file is part of the Swift.org open source project
4
+ //
5
+ // Copyright (c) 2022 Apple Inc. and the Swift project authors
6
+ // Licensed under Apache License v2.0 with Runtime Library Exception
7
+ //
8
+ // See https://swift.org/LICENSE.txt for license information
9
+ // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10
+ //
11
+ // ===----------------------------------------------------------------------===//
12
+ //
13
+ // This file implements utilities for substituting type parameter packs
14
+ // appearing in pack expansion types.
15
+ //
16
+ // ===----------------------------------------------------------------------===//
17
+
18
+ #include " swift/AST/Types.h"
19
+ #include " swift/AST/Decl.h"
20
+ #include " swift/AST/Type.h"
21
+ #include " llvm/ADT/SmallVector.h"
22
+
23
+ using namespace swift ;
24
+
25
+ void TypeBase::getTypeParameterPacks (
26
+ SmallVectorImpl<Type> &rootParameterPacks) const {
27
+ llvm::SmallDenseSet<CanType, 2 > visited;
28
+
29
+ auto recordType = [&](Type t) {
30
+ if (visited.insert (t->getCanonicalType ()).second )
31
+ rootParameterPacks.push_back (t);
32
+ };
33
+
34
+ Type (const_cast <TypeBase *>(this )).visit ([&](Type t) {
35
+ if (auto *paramTy = t->getAs <GenericTypeParamType>()) {
36
+ if (paramTy->isParameterPack ()) {
37
+ recordType (paramTy);
38
+ }
39
+ } else if (auto *archetypeTy = t->getAs <PackArchetypeType>()) {
40
+ if (archetypeTy->isRoot ()) {
41
+ recordType (t);
42
+ }
43
+ }
44
+ });
45
+ }
46
+
47
+ bool GenericTypeParamType::isParameterPack () const {
48
+ if (auto param = getDecl ()) {
49
+ return param->isParameterPack ();
50
+ }
51
+
52
+ auto fixedNum = ParamOrDepthIndex.get <DepthIndexTy>();
53
+ return (fixedNum & GenericTypeParamType::TYPE_SEQUENCE_BIT) ==
54
+ GenericTypeParamType::TYPE_SEQUENCE_BIT;
55
+ }
56
+
57
+ // / G<{X1, ..., Xn}, {Y1, ..., Yn}>... => {G<X1, Y1>, ..., G<Xn, Yn>}...
58
+ PackExpansionType *PackExpansionType::expand () {
59
+ auto countType = getCountType ();
60
+ auto *countPack = countType->getAs <PackType>();
61
+ if (countPack == nullptr )
62
+ return this ;
63
+
64
+ auto patternType = getPatternType ();
65
+ if (patternType->is <PackType>())
66
+ return this ;
67
+
68
+ unsigned j = 0 ;
69
+ SmallVector<Type, 4 > expandedTypes;
70
+ for (auto type : countPack->getElementTypes ()) {
71
+ Type expandedCount;
72
+ if (auto *expansion = type->getAs <PackExpansionType>())
73
+ expandedCount = expansion->getCountType ();
74
+
75
+ auto expandedPattern = patternType.transformRec (
76
+ [&](Type t) -> Optional<Type> {
77
+ if (t->is <PackExpansionType>())
78
+ return t;
79
+
80
+ if (auto *nestedPack = t->getAs <PackType>()) {
81
+ auto nestedPackElts = nestedPack->getElementTypes ();
82
+ if (j < nestedPackElts.size ()) {
83
+ if (expandedCount) {
84
+ if (auto *expansion = nestedPackElts[j]->getAs <PackExpansionType>())
85
+ return expansion->getPatternType ();
86
+ } else {
87
+ return nestedPackElts[j];
88
+ }
89
+ }
90
+
91
+ return ErrorType::get (t->getASTContext ());
92
+ }
93
+
94
+ return None;
95
+ });
96
+
97
+ if (expandedCount) {
98
+ expandedTypes.push_back (PackExpansionType::get (expandedPattern,
99
+ expandedCount));
100
+ } else {
101
+ expandedTypes.push_back (expandedPattern);
102
+ }
103
+
104
+ ++j;
105
+ }
106
+
107
+ auto *packType = PackType::get (getASTContext (), expandedTypes);
108
+ return PackExpansionType::get (packType, countType);
109
+ }
110
+
111
+ bool TupleType::containsPackExpansionType () const {
112
+ for (auto elt : getElements ()) {
113
+ if (elt.getType ()->is <PackExpansionType>())
114
+ return true ;
115
+ }
116
+
117
+ return false ;
118
+ }
119
+
120
+ // / (W, {X, Y}..., Z) => (W, X, Y, Z)
121
+ TupleType *TupleType::flattenPackTypes () {
122
+ bool anyChanged = false ;
123
+ SmallVector<TupleTypeElt, 4 > elts;
124
+
125
+ for (unsigned i = 0 , e = getNumElements (); i < e; ++i) {
126
+ auto elt = getElement (i);
127
+
128
+ if (auto *expansionType = elt.getType ()->getAs <PackExpansionType>()) {
129
+ if (auto *packType = expansionType->getPatternType ()->getAs <PackType>()) {
130
+ if (!anyChanged) {
131
+ elts.append (getElements ().begin (), getElements ().begin () + i);
132
+ anyChanged = true ;
133
+ }
134
+
135
+ bool first = true ;
136
+ for (auto packElt : packType->getElementTypes ()) {
137
+ if (first) {
138
+ elts.push_back (TupleTypeElt (packElt, elt.getName ()));
139
+ first = false ;
140
+ continue ;
141
+ }
142
+ elts.push_back (TupleTypeElt (packElt));
143
+ }
144
+
145
+ continue ;
146
+ }
147
+ }
148
+
149
+ if (anyChanged)
150
+ elts.push_back (elt);
151
+ }
152
+
153
+ if (!anyChanged)
154
+ return this ;
155
+
156
+ return TupleType::get (elts, getASTContext ());
157
+ }
158
+
159
+ bool AnyFunctionType::containsPackExpansionType (ArrayRef<Param> params) {
160
+ for (auto param : params) {
161
+ if (param.getPlainType ()->is <PackExpansionType>())
162
+ return true ;
163
+ }
164
+
165
+ return false ;
166
+ }
167
+
168
+ // / (W, {X, Y}..., Z) -> T => (W, X, Y, Z) -> T
169
+ AnyFunctionType *AnyFunctionType::flattenPackTypes () {
170
+ bool anyChanged = false ;
171
+ SmallVector<AnyFunctionType::Param, 4 > params;
172
+
173
+ for (unsigned i = 0 , e = getParams ().size (); i < e; ++i) {
174
+ auto param = getParams ()[i];
175
+
176
+ if (auto *expansionType = param.getPlainType ()->getAs <PackExpansionType>()) {
177
+ if (auto *packType = expansionType->getPatternType ()->getAs <PackType>()) {
178
+ if (!anyChanged) {
179
+ params.append (getParams ().begin (), getParams ().begin () + i);
180
+ anyChanged = true ;
181
+ }
182
+
183
+ bool first = true ;
184
+ for (auto packElt : packType->getElementTypes ()) {
185
+ if (first) {
186
+ params.push_back (param.withType (packElt));
187
+ first = false ;
188
+ continue ;
189
+ }
190
+ params.push_back (param.withType (packElt).getWithoutLabels ());
191
+ }
192
+
193
+ continue ;
194
+ }
195
+ }
196
+
197
+ if (anyChanged)
198
+ params.push_back (param);
199
+ }
200
+
201
+ if (!anyChanged)
202
+ return this ;
203
+
204
+ if (auto *genericFuncType = getAs<GenericFunctionType>()) {
205
+ return GenericFunctionType::get (genericFuncType->getGenericSignature (),
206
+ params, getResult (), getExtInfo ());
207
+ } else {
208
+ return FunctionType::get (params, getResult (), getExtInfo ());
209
+ }
210
+ }
211
+
212
+ bool PackType::containsPackExpansionType () const {
213
+ for (auto type : getElementTypes ()) {
214
+ if (type->is <PackExpansionType>())
215
+ return true ;
216
+ }
217
+
218
+ return false ;
219
+ }
220
+
221
+ // / {W, {X, Y}..., Z} => {W, X, Y, Z}
222
+ PackType *PackType::flattenPackTypes () {
223
+ bool anyChanged = false ;
224
+ SmallVector<Type, 4 > elts;
225
+
226
+ for (unsigned i = 0 , e = getNumElements (); i < e; ++i) {
227
+ auto elt = getElementType (i);
228
+
229
+ if (auto *expansionType = elt->getAs <PackExpansionType>()) {
230
+ if (auto *packType = expansionType->getPatternType ()->getAs <PackType>()) {
231
+ if (!anyChanged) {
232
+ elts.append (getElementTypes ().begin (), getElementTypes ().begin () + i);
233
+ anyChanged = true ;
234
+ }
235
+
236
+ for (auto packElt : packType->getElementTypes ()) {
237
+ elts.push_back (packElt);
238
+ }
239
+
240
+ continue ;
241
+ }
242
+ }
243
+
244
+ if (anyChanged)
245
+ elts.push_back (elt);
246
+ }
247
+
248
+ if (!anyChanged)
249
+ return this ;
250
+
251
+ return PackType::get (getASTContext (), elts);
252
+ }
0 commit comments