@@ -1402,120 +1402,6 @@ class AllowLabelMismatches : public MatchCallArgumentListener {
1402
1402
}
1403
1403
};
1404
1404
1405
- namespace {
1406
- class OpenParameterPackElements {
1407
- ConstraintSystem &CS;
1408
- int64_t argIdx;
1409
- Type patternTy;
1410
-
1411
- // A map that relates a type variable opened for a reference to a parameter
1412
- // pack to an array of parallel type variables, one for each argument.
1413
- llvm::MapVector<TypeVariableType *, SmallVector<TypeVariableType *, 2>> PackElementCache;
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
-
1423
- public:
1424
- OpenParameterPackElements(ConstraintSystem &CS, PackExpansionType *PET)
1425
- : CS(CS), argIdx(-1), patternTy(PET->getPatternType()) {}
1426
-
1427
- public:
1428
- Type expandParameter(Type argType) {
1429
- argIdx += 1;
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;
1441
- }
1442
-
1443
- void intoPackTypes(llvm::function_ref<void(TypeVariableType *, Type)> fn) && {
1444
- if (argIdx == -1) {
1445
- // No arguments. Each pack in the pattern will have no elements.
1446
- patternTy.visit([&](Type type) {
1447
- auto *typeVar = type->getAs<TypeVariableType>();
1448
- if (!typeVar || !typeVar->getImpl().getGenericParameter()->isParameterPack())
1449
- return;
1450
-
1451
- this->PackElementCache[typeVar].clear();
1452
- });
1453
- }
1454
-
1455
- for (const auto &entry : PackElementCache) {
1456
- SmallVector<Type, 8> elements;
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
-
1472
- auto packType = PackType::get(CS.getASTContext(), elements);
1473
- fn(entry.first, packType);
1474
- }
1475
- }
1476
-
1477
- Type operator()(Type Ty) {
1478
- if (!Ty || !Ty->isTypeVariableOrMember())
1479
- return Ty;
1480
-
1481
- auto *TV = Ty->getAs<TypeVariableType>();
1482
- if (!TV)
1483
- return Ty;
1484
-
1485
- // Leave plain opened type variables alone.
1486
- if (!TV->getImpl().getGenericParameter()->isParameterPack())
1487
- return TV;
1488
-
1489
- // Create a clone of the parameter pack type variable.
1490
- auto *clonedTV = CS.createTypeVariable(TV->getImpl().getLocator(),
1491
- TV->getImpl().getRawOptions());
1492
-
1493
- // Is there an entry for this parameter pack?
1494
- const auto &entries = PackElementCache.find(TV);
1495
- if (entries == PackElementCache.end()) {
1496
- // We're just seeing this parameter pack fresh, so enter a new type
1497
- // variable in its place and cache down the fact we just saw it.
1498
- PackElementCache[TV] = {clonedTV};
1499
- } else if ((int64_t)entries->second.size() <= argIdx) {
1500
- // We've seen this pack before, but we have a brand new element.
1501
- // Expand the cache entry.
1502
- PackElementCache[TV].push_back(clonedTV);
1503
- } else {
1504
- // Not only have we seen this pack before, we've seen this
1505
- // argument index before. Extract the old cache entry, emplace the new
1506
- // one, and bind them together.
1507
- auto *oldEntry = PackElementCache[TV][argIdx];
1508
- PackElementCache[TV][argIdx] = clonedTV;
1509
-
1510
- CS.addConstraint(ConstraintKind::Bind, oldEntry, clonedTV,
1511
- TV->getImpl().getLocator());
1512
- }
1513
-
1514
- return clonedTV;
1515
- }
1516
- };
1517
- }
1518
-
1519
1405
namespace {
1520
1406
/// Flags that should be applied to the existential argument type after
1521
1407
/// opening.
@@ -1860,31 +1746,20 @@ static ConstraintSystem::TypeMatchResult matchCallArguments(
1860
1746
// inout and @autoclosure.
1861
1747
if (cs.getASTContext().LangOpts.hasFeature(Feature::VariadicGenerics) &&
1862
1748
paramInfo.isVariadicGenericParameter(paramIdx)) {
1863
- auto *PET = paramTy->castTo<PackExpansionType>();
1864
- OpenParameterPackElements openParameterPack{cs, PET};
1865
- for (auto argIdx : parameterBindings[paramIdx]) {
1866
- const auto &argument = argsWithLabels[argIdx];
1867
- auto argTy = argument.getPlainType();
1749
+ auto *paramPackExpansion = paramTy->castTo<PackExpansionType>();
1868
1750
1869
- // First, expand the opened parameter pack for this argument.
1870
- // This will open a new type variable for each pack reference
1871
- // in the pattern type of the parameter, and substitute the type
1872
- // variables into the pattern type.
1873
- auto substParamTy = openParameterPack.expandParameter(argTy);
1874
-
1875
- cs.addConstraint(
1876
- subKind, argTy, substParamTy, loc, /*isFavored=*/false);
1751
+ SmallVector<Type, 2> argTypes;
1752
+ for (auto argIdx : parameterBindings[paramIdx]) {
1753
+ auto argType = argsWithLabels[argIdx].getPlainType();
1754
+ argTypes.push_back(argType);
1877
1755
}
1878
1756
1879
- // Now that we have the pack mappings, bind the raw list to the
1880
- // whole parameter pack. This ensures references to the pack in
1881
- // return position refer to the whole pack of elements we just gathered.
1882
- std::move(openParameterPack)
1883
- .intoPackTypes([&](TypeVariableType *tsParam, Type pack) {
1884
- cs.addConstraint(ConstraintKind::Bind, pack, tsParam, loc,
1885
- /*isFavored=*/false);
1886
- });
1757
+ auto *argPack = PackType::get(cs.getASTContext(), argTypes);
1758
+ auto *argPackExpansion = PackExpansionType::get(argPack, argPack);
1887
1759
1760
+ cs.addConstraint(
1761
+ subKind, argPackExpansion, paramPackExpansion,
1762
+ loc, /*isFavored=*/false);
1888
1763
continue;
1889
1764
}
1890
1765
@@ -2529,23 +2404,29 @@ static PackType *replaceTypeVariablesWithFreshPacks(ConstraintSystem &cs,
2529
2404
PackTypeVariableCollector collector;
2530
2405
pattern.walk(collector);
2531
2406
2407
+ if (collector.typeVars.empty())
2408
+ return nullptr;
2409
+
2532
2410
auto *loc = cs.getConstraintLocator(locator);
2533
2411
2534
2412
// For each pack type variable occurring in the pattern type, compute a
2535
2413
// binding pack type comprised of fresh type variables.
2536
2414
for (auto *typeVar : collector.typeVars) {
2537
2415
auto &freshTypeVars = typeVars[typeVar];
2538
2416
for (unsigned i = 0, e = pack->getNumElements(); i < e; ++i) {
2417
+ auto *packExpansionElt = pack->getElementType(i)->getAs<PackExpansionType>();
2418
+
2539
2419
// Preserve the pack expansion structure of the original pack. If the ith
2540
2420
// element was a pack expansion type, create a new pack expansion type
2541
2421
// wrapping a pack type variable. Otherwise, create a new scalar
2542
2422
// type variable.
2543
2423
//
2544
2424
// FIXME: Locator for diagnostics
2545
2425
// FIXME: Other TVO_* flags for type variables?
2546
- if (pack->getElementType(i)->is<PackExpansionType>() ) {
2426
+ if (packExpansionElt != nullptr ) {
2547
2427
auto *freshTypeVar = cs.createTypeVariable(loc, TVO_CanBindToPack);
2548
- freshTypeVars.push_back(PackExpansionType::get(freshTypeVar, freshTypeVar));
2428
+ freshTypeVars.push_back(PackExpansionType::get(
2429
+ freshTypeVar, packExpansionElt->getCountType()));
2549
2430
} else {
2550
2431
freshTypeVars.push_back(cs.createTypeVariable(loc, /*options=*/0));
2551
2432
}
@@ -2627,35 +2508,22 @@ ConstraintSystem::matchPackExpansionTypes(PackExpansionType *expansion1,
2627
2508
auto pattern1 = expansion1->getPatternType();
2628
2509
auto pattern2 = expansion2->getPatternType();
2629
2510
2630
- // A pattern is 'expanded' if it is a pack type, pack archetype or
2631
- // pack type variable. Otherwise, it is a concrete type which can be
2632
- // instantiated by replacing any pack type variables that occur within.
2633
- auto isFullyExpanded = [](Type t) -> bool {
2634
- return (t->is<PackType>() ||
2635
- t->is<PackArchetypeType>() ||
2636
- (t->is<TypeVariableType>() &&
2637
- t->castTo<TypeVariableType>()->getImpl().canBindToPack()));
2638
- };
2639
-
2640
- bool isExpanded1 = isFullyExpanded(pattern1);
2641
- bool isExpanded2 = isFullyExpanded(pattern2);
2642
-
2643
2511
// If both sides are expanded or neither side is, just match them
2644
2512
// directly.
2645
- if ((isExpanded1 && isExpanded2) ||
2646
- (!isExpanded1 && !isExpanded2)) {
2513
+ if (pattern1->is<PackType>() == pattern2->is<PackType>()) {
2647
2514
return matchTypes(pattern1, pattern2, kind, flags, locator);
2648
2515
2649
2516
// If the right hand side is expanded, we have something like
2650
2517
// Foo<$T0>... vs Pack{Foo<Int>, Foo<String>}...; We're going to
2651
2518
// bind $T0 to Pack{Int, String}.
2652
- } else if (!isExpanded1 && isExpanded2 ) {
2519
+ } else if (!pattern1->is<PackType>() && pattern2->is<PackType>() ) {
2653
2520
if (auto *pack2 = pattern2->getAs<PackType>()) {
2654
- auto *pack1 = replaceTypeVariablesWithFreshPacks(
2655
- *this, pattern1, pack2, locator);
2656
- // FIXME: Locator for diagnostics.
2657
- addConstraint(kind, pack1, pack2, locator);
2658
- return getTypeMatchSuccess();
2521
+ if (auto *pack1 = replaceTypeVariablesWithFreshPacks(
2522
+ *this, pattern1, pack2, locator)) {
2523
+ // FIXME: Locator for diagnostics.
2524
+ addConstraint(kind, pack1, pack2, locator);
2525
+ return getTypeMatchSuccess();
2526
+ }
2659
2527
}
2660
2528
2661
2529
return getTypeMatchFailure(locator);
@@ -2664,13 +2532,14 @@ ConstraintSystem::matchPackExpansionTypes(PackExpansionType *expansion1,
2664
2532
// Pack{Foo<Int>, Foo<String>}... vs Foo<$T0>...; We're going to
2665
2533
// bind $T0 to Pack{Int, String}.
2666
2534
} else {
2667
- assert(isExpanded1 && !isExpanded2 );
2535
+ assert(pattern1->is<PackType>() && !pattern2->is<PackType>() );
2668
2536
if (auto *pack1 = pattern1->getAs<PackType>()) {
2669
- auto *pack2 = replaceTypeVariablesWithFreshPacks(
2670
- *this, pattern2, pack1, locator);
2671
- // FIXME: Locator for diagnostics.
2672
- addConstraint(kind, pack1, pack2, locator);
2673
- return getTypeMatchSuccess();
2537
+ if (auto *pack2 = replaceTypeVariablesWithFreshPacks(
2538
+ *this, pattern2, pack1, locator)) {
2539
+ // FIXME: Locator for diagnostics.
2540
+ addConstraint(kind, pack1, pack2, locator);
2541
+ return getTypeMatchSuccess();
2542
+ }
2674
2543
}
2675
2544
2676
2545
return getTypeMatchFailure(locator);
0 commit comments