Skip to content

Commit 3adb1dd

Browse files
committed
Sema: Remove OpenParameterPackElements
1 parent 485e4b0 commit 3adb1dd

File tree

3 files changed

+48
-177
lines changed

3 files changed

+48
-177
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 33 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,120 +1402,6 @@ class AllowLabelMismatches : public MatchCallArgumentListener {
14021402
}
14031403
};
14041404

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-
15191405
namespace {
15201406
/// Flags that should be applied to the existential argument type after
15211407
/// opening.
@@ -1860,31 +1746,20 @@ static ConstraintSystem::TypeMatchResult matchCallArguments(
18601746
// inout and @autoclosure.
18611747
if (cs.getASTContext().LangOpts.hasFeature(Feature::VariadicGenerics) &&
18621748
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>();
18681750

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);
18771755
}
18781756

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);
18871759

1760+
cs.addConstraint(
1761+
subKind, argPackExpansion, paramPackExpansion,
1762+
loc, /*isFavored=*/false);
18881763
continue;
18891764
}
18901765

@@ -2529,23 +2404,29 @@ static PackType *replaceTypeVariablesWithFreshPacks(ConstraintSystem &cs,
25292404
PackTypeVariableCollector collector;
25302405
pattern.walk(collector);
25312406

2407+
if (collector.typeVars.empty())
2408+
return nullptr;
2409+
25322410
auto *loc = cs.getConstraintLocator(locator);
25332411

25342412
// For each pack type variable occurring in the pattern type, compute a
25352413
// binding pack type comprised of fresh type variables.
25362414
for (auto *typeVar : collector.typeVars) {
25372415
auto &freshTypeVars = typeVars[typeVar];
25382416
for (unsigned i = 0, e = pack->getNumElements(); i < e; ++i) {
2417+
auto *packExpansionElt = pack->getElementType(i)->getAs<PackExpansionType>();
2418+
25392419
// Preserve the pack expansion structure of the original pack. If the ith
25402420
// element was a pack expansion type, create a new pack expansion type
25412421
// wrapping a pack type variable. Otherwise, create a new scalar
25422422
// type variable.
25432423
//
25442424
// FIXME: Locator for diagnostics
25452425
// FIXME: Other TVO_* flags for type variables?
2546-
if (pack->getElementType(i)->is<PackExpansionType>()) {
2426+
if (packExpansionElt != nullptr) {
25472427
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()));
25492430
} else {
25502431
freshTypeVars.push_back(cs.createTypeVariable(loc, /*options=*/0));
25512432
}
@@ -2627,35 +2508,22 @@ ConstraintSystem::matchPackExpansionTypes(PackExpansionType *expansion1,
26272508
auto pattern1 = expansion1->getPatternType();
26282509
auto pattern2 = expansion2->getPatternType();
26292510

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-
26432511
// If both sides are expanded or neither side is, just match them
26442512
// directly.
2645-
if ((isExpanded1 && isExpanded2) ||
2646-
(!isExpanded1 && !isExpanded2)) {
2513+
if (pattern1->is<PackType>() == pattern2->is<PackType>()) {
26472514
return matchTypes(pattern1, pattern2, kind, flags, locator);
26482515

26492516
// If the right hand side is expanded, we have something like
26502517
// Foo<$T0>... vs Pack{Foo<Int>, Foo<String>}...; We're going to
26512518
// bind $T0 to Pack{Int, String}.
2652-
} else if (!isExpanded1 && isExpanded2) {
2519+
} else if (!pattern1->is<PackType>() && pattern2->is<PackType>()) {
26532520
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+
}
26592527
}
26602528

26612529
return getTypeMatchFailure(locator);
@@ -2664,13 +2532,14 @@ ConstraintSystem::matchPackExpansionTypes(PackExpansionType *expansion1,
26642532
// Pack{Foo<Int>, Foo<String>}... vs Foo<$T0>...; We're going to
26652533
// bind $T0 to Pack{Int, String}.
26662534
} else {
2667-
assert(isExpanded1 && !isExpanded2);
2535+
assert(pattern1->is<PackType>() && !pattern2->is<PackType>());
26682536
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+
}
26742543
}
26752544

26762545
return getTypeMatchFailure(locator);

test/Constraints/pack_expansion_types.swift

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ func returnTupleLabel1<T...>() -> (x: T...) { fatalError() }
88

99
func returnTupleLabel2<T...>() -> (Int, x: T...) { fatalError() }
1010

11-
func returnTupleLabel3<T...>() -> (Int, T..., y: Float) { fatalError() } // expected-note {{in call to function 'returnTupleLabel3()'}}
11+
func returnTupleLabel3<T...>() -> (Int, T..., y: Float) { fatalError() }
1212

13-
func returnTupleLabel4<T...>() -> (Int, x: T..., y: Float) { fatalError() }
13+
func returnTupleLabel4<T...>() -> (Int, x: T..., y: Float) { fatalError() } // expected-note {{in call to function 'returnTupleLabel4()'}}
1414

15-
func returnTupleLabel5<T..., U...>() -> (Int, T..., y: U...) { fatalError() } // expected-note {{in call to function 'returnTupleLabel5()'}}
15+
func returnTupleLabel5<T..., U...>() -> (Int, T..., y: U...) { fatalError() }
1616

17-
func returnTupleLabel6<T..., U...>() -> (Int, x: T..., y: U...) { fatalError() }
17+
func returnTupleLabel6<T..., U...>() -> (Int, x: T..., y: U...) { fatalError() } // expected-note {{in call to function 'returnTupleLabel6()'}}
1818

1919
func concreteReturnTupleValid() {
2020
let _: () = returnTuple1()
@@ -103,20 +103,22 @@ func genericReturnTupleInvalid<T...>(_: T...) {
103103
let _: (x: T...) = returnTupleLabel2() // expected-error {{type of expression is ambiguous without more context}}
104104
let _: (Int, y: String, T...) = returnTupleLabel2() // expected-error {{type of expression is ambiguous without more context}}
105105

106-
let _: (T..., y: Float) = returnTupleLabel3() // expected-error {{'(Int, T..., y: Float)' is not convertible to '(T..., y: Float)', tuples have a different number of elements}}
107-
// expected-error@-1 {{generic parameter 'T' could not be inferred}}
106+
let _: (T..., y: Float) = returnTupleLabel3() // expected-error {{type of expression is ambiguous without more context}}
108107

109108
let _: (Int, String, T..., x: Float) = returnTupleLabel3() // expected-error {{type of expression is ambiguous without more context}}
110109

111-
let _: (T..., y: Float) = returnTupleLabel4() // expected-error {{cannot convert value of type '(Int, y: Float)' to specified type '(T..., y: Float)'}}
110+
let _: (T..., y: Float) = returnTupleLabel4() // expected-error {{'(Int, x: T..., y: Float)' is not convertible to '(T..., y: Float)', tuples have a different number of elements}}
111+
// expected-error@-1 {{generic parameter 'T' could not be inferred}}
112+
112113
let _: (Int, x: String, y: T...) = returnTupleLabel4() // expected-error {{cannot convert value of type '(Int, x: String, y: Float)' to specified type '(Int, x: String, y: T...)'}}
113114

114115
let _: (Int, T..., x: T...) = returnTupleLabel5() // expected-error {{type of expression is ambiguous without more context}}
115116

116-
let _: (T..., y: Float, T...) = returnTupleLabel5() // expected-error {{'(Int, T..., y: Float, T...)' is not convertible to '(T..., y: Float, T...)', tuples have a different number of elements}}
117-
// expected-error@-1 {{generic parameter 'T' could not be inferred}}
117+
let _: (T..., y: Float, T...) = returnTupleLabel5() // expected-error {{type of expression is ambiguous without more context}}
118118

119-
let _: (T..., y: Int) = returnTupleLabel6() // expected-error {{cannot convert value of type '(Int, y: Int)' to specified type '(T..., y: Int)'}}
119+
let _: (T..., y: Int) = returnTupleLabel6() // expected-error {{'(Int, x: T..., y: U...)' is not convertible to '(T..., y: Int)', tuples have a different number of elements}}
120+
// expected-error@-1 {{generic parameter 'T' could not be inferred}}
121+
// expected-error@-2 {{generic parameter 'U' could not be inferred}}
120122
}
121123

122124
func returnFunction1<T...>() -> (T...) -> () {}

test/Constraints/variadic_generic_constraints.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ takesParallelSequences(t: Array<String>(), Set<Int>(), u: Array<Int>(), Set<Stri
5656
// Same-shape requirements
5757

5858
func zip<T..., U...>(t: T..., u: U...) -> ((T, U)...) {}
59-
// expected-note@-1 {{where 'T' = 'U', 'U' = 'T'}}
59+
// expected-note@-1 {{where 'T' = 'T', 'U' = 'U'}}
6060

6161
let _ = zip() // ok
6262
let _ = zip(t: 1, u: "hi") // ok
@@ -72,5 +72,5 @@ func goodCallToZip<T..., U...>(t: T..., u: U...) where ((T, U)...): Any {
7272

7373
func badCallToZip<T..., U...>(t: T..., u: U...) {
7474
_ = zip(t: t..., u: u...)
75-
// expected-error@-1 {{global function 'zip(t:u:)' requires the type packs 'U' and 'T' have the same shape}}
76-
}
75+
// expected-error@-1 {{global function 'zip(t:u:)' requires the type packs 'T' and 'U' have the same shape}}
76+
}

0 commit comments

Comments
 (0)