@@ -1407,18 +1407,37 @@ class OpenParameterPackElements {
1407
1407
ConstraintSystem &CS;
1408
1408
int64_t argIdx;
1409
1409
Type patternTy;
1410
+
1410
1411
// A map that relates a type variable opened for a reference to a parameter
1411
1412
// pack to an array of parallel type variables, one for each argument.
1412
1413
llvm::MapVector<TypeVariableType *, SmallVector<TypeVariableType *, 2>> PackElementCache;
1413
1414
1415
+ // A map from argument index to the corresponding shape type for pack
1416
+ // expansion arguments. When the parameter pack is expanded by a
1417
+ // pack expansion argument, the corresponding pattern type is also
1418
+ // wrapped in a pack expansion. Each pack reference in the pattern
1419
+ // type will be bound to a pack expansion in the aggregated pack type
1420
+ // created in 'intoPackTypes'.
1421
+ llvm::SmallDenseMap<int64_t, Type> Expansions;
1422
+
1414
1423
public:
1415
1424
OpenParameterPackElements(ConstraintSystem &CS, PackExpansionType *PET)
1416
1425
: CS(CS), argIdx(-1), patternTy(PET->getPatternType()) {}
1417
1426
1418
1427
public:
1419
- Type expandParameter() {
1428
+ Type expandParameter(Type argType ) {
1420
1429
argIdx += 1;
1421
- return patternTy.transform(*this);
1430
+ auto pattern = patternTy.transform(*this);
1431
+
1432
+ // If the argument that invoked expansion is itself a pack
1433
+ // expansion, wrap the pattern type in a pack expansion type
1434
+ // of the same shape.
1435
+ if (auto expansion = argType->getAs<PackExpansionType>()) {
1436
+ Expansions[argIdx] = expansion->getCountType();
1437
+ pattern = PackExpansionType::get(pattern, expansion->getCountType());
1438
+ }
1439
+
1440
+ return pattern;
1422
1441
}
1423
1442
1424
1443
void intoPackTypes(llvm::function_ref<void(TypeVariableType *, Type)> fn) && {
@@ -1435,9 +1454,21 @@ class OpenParameterPackElements {
1435
1454
1436
1455
for (const auto &entry : PackElementCache) {
1437
1456
SmallVector<Type, 8> elements;
1438
- llvm::transform(entry.second, std::back_inserter(elements), [](Type t) {
1439
- return t;
1440
- });
1457
+ for (int64_t i = 0; i < (int64_t)entry.second.size(); ++i) {
1458
+ auto *typeVar = entry.second[i];
1459
+
1460
+ // If this argument is a pack expansion, wrap the corresponding
1461
+ // type variable in a pack expansion to distinguish it from
1462
+ // a scalar type argument. The type variable itself represents
1463
+ // the argument pattern.
1464
+ if (auto shape = Expansions[i]) {
1465
+ elements.push_back(PackExpansionType::get(typeVar, shape));
1466
+ continue;
1467
+ }
1468
+
1469
+ elements.push_back(typeVar);
1470
+ }
1471
+
1441
1472
auto packType = PackType::get(CS.getASTContext(), elements);
1442
1473
fn(entry.first, packType);
1443
1474
}
@@ -1833,9 +1864,11 @@ static ConstraintSystem::TypeMatchResult matchCallArguments(
1833
1864
const auto &argument = argsWithLabels[argIdx];
1834
1865
auto argTy = argument.getPlainType();
1835
1866
1836
- // First, re-open the parameter type so we bind the elements of the type
1837
- // sequence into their proper positions.
1838
- auto substParamTy = openParameterPack.expandParameter();
1867
+ // First, expand the opened parameter pack for this argument.
1868
+ // This will open a new type variable for each pack reference
1869
+ // in the pattern type of the parameter, and substitute the type
1870
+ // variables into the pattern type.
1871
+ auto substParamTy = openParameterPack.expandParameter(argTy);
1839
1872
1840
1873
cs.addConstraint(
1841
1874
subKind, argTy, substParamTy, loc, /*isFavored=*/false);
0 commit comments