@@ -167,6 +167,10 @@ bool ParamPackMatcher::match() {
167
167
lhsParams = lhsParams.drop_front (prefixLength).drop_back (suffixLength);
168
168
rhsParams = rhsParams.drop_front (prefixLength).drop_back (suffixLength);
169
169
170
+ // If nothing remains, we're done.
171
+ if (lhsParams.empty () && rhsParams.empty ())
172
+ return false ;
173
+
170
174
// If the left hand side is a single pack expansion type, bind it
171
175
// to what remains of the right hand side.
172
176
if (lhsParams.size () == 1 ) {
@@ -198,7 +202,92 @@ bool ParamPackMatcher::match() {
198
202
auto lhs = PackType::get (ctx, lhsTypes);
199
203
200
204
// FIXME: Check rhs flags
201
- pairs.emplace_back (lhs, rhsParams[0 ].getPlainType (), prefixLength);
205
+ pairs.emplace_back (lhs, rhsType, prefixLength);
206
+ return false ;
207
+ }
208
+ }
209
+
210
+ // Otherwise, all remaining possibilities are invalid:
211
+ // - Neither side has any pack expansions, and they have different lengths.
212
+ // - One side has a pack expansion but the other side is too short, eg
213
+ // {Int, T..., Float} vs {Int}.
214
+ // - The prefix and suffix are mismatched, so we're left with something
215
+ // like {T..., Int} vs {Float, U...}.
216
+ return true ;
217
+ }
218
+
219
+ PackMatcher::PackMatcher (
220
+ ArrayRef<Type> lhsTypes,
221
+ ArrayRef<Type> rhsTypes,
222
+ ASTContext &ctx)
223
+ : lhsTypes(lhsTypes), rhsTypes(rhsTypes), ctx(ctx) {}
224
+
225
+ bool PackMatcher::match () {
226
+ unsigned minLength = std::min (lhsTypes.size (), rhsTypes.size ());
227
+
228
+ // Consume the longest possible prefix where neither type in
229
+ // the pair is a pack expansion type.
230
+ unsigned prefixLength = 0 ;
231
+ for (unsigned i = 0 ; i < minLength; ++i) {
232
+ auto lhsType = lhsTypes[i];
233
+ auto rhsType = rhsTypes[i];
234
+
235
+ if (lhsType->is <PackExpansionType>() ||
236
+ rhsType->is <PackExpansionType>()) {
237
+ break ;
238
+ }
239
+
240
+ pairs.emplace_back (lhsType, rhsType, i);
241
+ ++prefixLength;
242
+ }
243
+
244
+ // Consume the longest possible suffix where neither type in
245
+ // the pair is a pack expansion type.
246
+ unsigned suffixLength = 0 ;
247
+ for (unsigned i = 0 ; i < minLength - prefixLength; ++i) {
248
+ auto lhsType = lhsTypes[lhsTypes.size () - i - 1 ];
249
+ auto rhsType = rhsTypes[rhsTypes.size () - i - 1 ];
250
+
251
+ if (lhsType->is <PackExpansionType>() ||
252
+ rhsType->is <PackExpansionType>()) {
253
+ break ;
254
+ }
255
+
256
+ pairs.emplace_back (lhsType, rhsType, i);
257
+ ++suffixLength;
258
+ }
259
+
260
+ assert (prefixLength + suffixLength <= lhsTypes.size ());
261
+ assert (prefixLength + suffixLength <= rhsTypes.size ());
262
+
263
+ // Drop the consumed prefix and suffix from each list of types.
264
+ lhsTypes = lhsTypes.drop_front (prefixLength).drop_back (suffixLength);
265
+ rhsTypes = rhsTypes.drop_front (prefixLength).drop_back (suffixLength);
266
+
267
+ // If nothing remains, we're done.
268
+ if (lhsTypes.empty () && rhsTypes.empty ())
269
+ return false ;
270
+
271
+ // If the left hand side is a single pack expansion type, bind it
272
+ // to what remains of the right hand side.
273
+ if (lhsTypes.size () == 1 ) {
274
+ auto lhsType = lhsTypes[0 ];
275
+ if (auto *lhsExpansionType = lhsType->getAs <PackExpansionType>()) {
276
+ auto rhs = PackType::get (ctx, rhsTypes);
277
+
278
+ pairs.emplace_back (lhsExpansionType->getPatternType (), rhs, prefixLength);
279
+ return false ;
280
+ }
281
+ }
282
+
283
+ // If the right hand side is a single pack expansion type, bind it
284
+ // to what remains of the left hand side.
285
+ if (rhsTypes.size () == 1 ) {
286
+ auto rhsType = rhsTypes[0 ];
287
+ if (auto *rhsExpansionType = rhsType->getAs <PackExpansionType>()) {
288
+ auto lhs = PackType::get (ctx, lhsTypes);
289
+
290
+ pairs.emplace_back (lhs, rhsType, prefixLength);
202
291
return false ;
203
292
}
204
293
}
0 commit comments