Skip to content

Commit 241d0b8

Browse files
committed
Merge pull request #67164 from sophiapoirier/pack-environments-for-elements
add tracking of pack environments for pack elements to Constraint System
1 parent 756b03a commit 241d0b8

File tree

5 files changed

+123
-28
lines changed

5 files changed

+123
-28
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1475,6 +1475,10 @@ class Solution {
14751475
llvm::DenseMap<ConstraintLocator *, std::pair<UUID, Type>>
14761476
PackExpansionEnvironments;
14771477

1478+
/// The pack expansion environment that can open a given pack element.
1479+
llvm::SmallMapVector<PackElementExpr *, PackExpansionExpr *, 2>
1480+
PackEnvironments;
1481+
14781482
/// The locators of \c Defaultable constraints whose defaults were used.
14791483
llvm::SmallPtrSet<ConstraintLocator *, 2> DefaultedConstraints;
14801484

@@ -2251,6 +2255,9 @@ class ConstraintSystem {
22512255
llvm::SmallMapVector<ConstraintLocator *, std::pair<UUID, Type>, 4>
22522256
PackExpansionEnvironments;
22532257

2258+
llvm::SmallMapVector<PackElementExpr *, PackExpansionExpr *, 2>
2259+
PackEnvironments;
2260+
22542261
/// The set of functions that have been transformed by a result builder.
22552262
llvm::MapVector<AnyFunctionRef, AppliedBuilderTransform>
22562263
resultBuilderTransformed;
@@ -2737,6 +2744,9 @@ class ConstraintSystem {
27372744
/// The length of \c PackExpansionEnvironments.
27382745
unsigned numPackExpansionEnvironments;
27392746

2747+
/// The length of \c PackEnvironments.
2748+
unsigned numPackEnvironments;
2749+
27402750
/// The length of \c DefaultedConstraints.
27412751
unsigned numDefaultedConstraints;
27422752

@@ -3232,6 +3242,13 @@ class ConstraintSystem {
32323242
GenericEnvironment *getPackElementEnvironment(ConstraintLocator *locator,
32333243
CanType shapeClass);
32343244

3245+
/// Get the opened element generic environment for the given pack element.
3246+
PackExpansionExpr *getPackEnvironment(PackElementExpr *packElement) const;
3247+
3248+
/// Associate an opened element generic environment to a pack element.
3249+
void addPackEnvironment(PackElementExpr *packElement,
3250+
PackExpansionExpr *packExpansion);
3251+
32353252
/// Retrieve the constraint locator for the given anchor and
32363253
/// path, uniqued and automatically infer the summary flags
32373254
ConstraintLocator *

lib/Sema/CSGen.cpp

Lines changed: 66 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,20 +1089,20 @@ namespace {
10891089
return outputTy;
10901090
}
10911091

1092-
Type openPackElement(Type packType, ConstraintLocator *locator) {
1092+
Type openPackElement(Type packType, ConstraintLocator *locator,
1093+
PackExpansionExpr *packElementEnvironment) {
10931094
// If 'each t' is written outside of a pack expansion expression, allow the
10941095
// type to bind to a hole. The invalid pack reference will be diagnosed when
10951096
// attempting to bind the type variable for the underlying pack reference to
10961097
// a pack type without TVO_CanBindToPack.
1097-
if (PackElementEnvironments.empty()) {
1098+
if (!packElementEnvironment) {
10981099
return CS.createTypeVariable(locator,
10991100
TVO_CanBindToHole | TVO_CanBindToNoEscape);
11001101
}
11011102

11021103
// The type of a PackElementExpr is the opened pack element archetype
11031104
// of the pack reference.
1104-
OpenPackElementType openPackElement(CS, locator,
1105-
PackElementEnvironments.back());
1105+
OpenPackElementType openPackElement(CS, locator, packElementEnvironment);
11061106
return openPackElement(packType, /*packRepr*/ nullptr);
11071107
}
11081108

@@ -1124,6 +1124,26 @@ namespace {
11241124

11251125
void addPackElementEnvironment(PackExpansionExpr *expr) {
11261126
PackElementEnvironments.push_back(expr);
1127+
1128+
SmallVector<ASTNode, 2> expandedPacks;
1129+
collectExpandedPacks(expr, expandedPacks);
1130+
for (auto pack : expandedPacks) {
1131+
if (auto *elementExpr = getAsExpr<PackElementExpr>(pack)) {
1132+
CS.addPackEnvironment(elementExpr, expr);
1133+
}
1134+
}
1135+
1136+
auto *patternLoc = CS.getConstraintLocator(
1137+
expr, ConstraintLocator::PackExpansionPattern);
1138+
auto patternType = CS.createTypeVariable(
1139+
patternLoc,
1140+
TVO_CanBindToPack | TVO_CanBindToNoEscape | TVO_CanBindToHole);
1141+
auto *shapeLoc =
1142+
CS.getConstraintLocator(expr, ConstraintLocator::PackShape);
1143+
auto *shapeTypeVar = CS.createTypeVariable(
1144+
shapeLoc, TVO_CanBindToPack | TVO_CanBindToHole);
1145+
auto expansionType = PackExpansionType::get(patternType, shapeTypeVar);
1146+
CS.setType(expr, expansionType);
11271147
}
11281148

11291149
virtual Type visitErrorExpr(ErrorExpr *E) {
@@ -1384,6 +1404,17 @@ namespace {
13841404
return BoundGenericStructType::get(regexDecl, Type(), {matchType});
13851405
}
13861406

1407+
PackExpansionExpr *getParentPackExpansionExpr(Expr *E) const {
1408+
auto *current = E;
1409+
while (auto *parent = CS.getParentExpr(current)) {
1410+
if (auto *expansion = dyn_cast<PackExpansionExpr>(parent)) {
1411+
return expansion;
1412+
}
1413+
current = parent;
1414+
}
1415+
return nullptr;
1416+
}
1417+
13871418
Type visitDeclRefExpr(DeclRefExpr *E) {
13881419
auto locator = CS.getConstraintLocator(E);
13891420

@@ -1426,13 +1457,15 @@ namespace {
14261457

14271458
// value packs cannot be referenced without `each` immediately
14281459
// preceding them.
1429-
if (auto *expansion = knownType->getAs<PackExpansionType>()) {
1430-
if (!PackElementEnvironments.empty() &&
1460+
if (auto *expansionType = knownType->getAs<PackExpansionType>()) {
1461+
if (auto *parentExpansionExpr = getParentPackExpansionExpr(E);
1462+
parentExpansionExpr &&
14311463
!isExpr<PackElementExpr>(CS.getParentExpr(E))) {
1432-
auto packType = expansion->getPatternType();
1464+
auto packType = expansionType->getPatternType();
14331465
(void)CS.recordFix(
14341466
IgnoreMissingEachKeyword::create(CS, packType, locator));
1435-
auto eltType = openPackElement(packType, locator);
1467+
auto eltType =
1468+
openPackElement(packType, locator, parentExpansionExpr);
14361469
CS.setType(E, eltType);
14371470
return eltType;
14381471
}
@@ -3033,21 +3066,11 @@ namespace {
30333066
assert(PackElementEnvironments.back() == expr);
30343067
PackElementEnvironments.pop_back();
30353068

3036-
auto *patternLoc =
3037-
CS.getConstraintLocator(expr, ConstraintLocator::PackExpansionPattern);
3038-
auto patternTy = CS.createTypeVariable(patternLoc,
3039-
TVO_CanBindToPack |
3040-
TVO_CanBindToNoEscape |
3041-
TVO_CanBindToHole);
3069+
auto expansionType = CS.getType(expr)->castTo<PackExpansionType>();
30423070
auto elementResultType = CS.getType(expr->getPatternExpr());
30433071
CS.addConstraint(ConstraintKind::PackElementOf, elementResultType,
3044-
patternTy, CS.getConstraintLocator(expr));
3045-
3046-
auto *shapeLoc =
3047-
CS.getConstraintLocator(expr, ConstraintLocator::PackShape);
3048-
auto *shapeTypeVar = CS.createTypeVariable(shapeLoc,
3049-
TVO_CanBindToPack |
3050-
TVO_CanBindToHole);
3072+
expansionType->getPatternType(),
3073+
CS.getConstraintLocator(expr));
30513074

30523075
// Generate ShapeOf constraints between all packs expanded by this
30533076
// pack expansion expression through the shape type variable.
@@ -3061,9 +3084,14 @@ namespace {
30613084

30623085
for (auto pack : expandedPacks) {
30633086
Type packType;
3064-
if (auto *elementExpr = getAsExpr<PackElementExpr>(pack)) {
3065-
packType = CS.getType(elementExpr->getPackRefExpr());
3066-
} else if (auto *elementType = getAsTypeRepr<PackElementTypeRepr>(pack)) {
3087+
/// Skipping over pack elements because the relationship to its
3088+
/// environment is now established during \c addPackElementEnvironment
3089+
/// upon visiting its pack expansion and the Shape constraint added
3090+
/// upon visiting the pack element.
3091+
if (isExpr<PackElementExpr>(pack)) {
3092+
continue;
3093+
} else if (auto *elementType =
3094+
getAsTypeRepr<PackElementTypeRepr>(pack)) {
30673095
// OpenPackElementType sets types for 'each T' type reprs in
30683096
// expressions. Some invalid code won't make it there, and
30693097
// the constraint system won't have recorded a type.
@@ -3076,11 +3104,11 @@ namespace {
30763104
}
30773105

30783106
CS.addConstraint(
3079-
ConstraintKind::ShapeOf, shapeTypeVar, packType,
3107+
ConstraintKind::ShapeOf, expansionType->getCountType(), packType,
30803108
CS.getConstraintLocator(expr, ConstraintLocator::PackShape));
30813109
}
30823110

3083-
return PackExpansionType::get(patternTy, shapeTypeVar);
3111+
return expansionType;
30843112
}
30853113

30863114
Type visitPackElementExpr(PackElementExpr *expr) {
@@ -3094,7 +3122,18 @@ namespace {
30943122
CS.setType(expr->getPackRefExpr(), packType);
30953123
}
30963124

3097-
return openPackElement(packType, CS.getConstraintLocator(expr));
3125+
auto *packEnvironment = CS.getPackEnvironment(expr);
3126+
if (packEnvironment) {
3127+
auto expansionType =
3128+
CS.getType(packEnvironment)->castTo<PackExpansionType>();
3129+
CS.addConstraint(ConstraintKind::ShapeOf, expansionType->getCountType(),
3130+
packType,
3131+
CS.getConstraintLocator(packEnvironment,
3132+
ConstraintLocator::PackShape));
3133+
}
3134+
3135+
return openPackElement(packType, CS.getConstraintLocator(expr),
3136+
packEnvironment);
30983137
}
30993138

31003139
Type visitMaterializePackExpr(MaterializePackExpr *expr) {

lib/Sema/CSSolver.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,8 @@ Solution ConstraintSystem::finalize() {
226226
solution.PackExpansionEnvironments.insert(env);
227227
}
228228

229+
solution.PackEnvironments = PackEnvironments;
230+
229231
return solution;
230232
}
231233

@@ -290,6 +292,11 @@ void ConstraintSystem::applySolution(const Solution &solution) {
290292
PackExpansionEnvironments.insert(expansion);
291293
}
292294

295+
// Register the solutions's pack environments.
296+
for (auto &packEnvironment : solution.PackEnvironments) {
297+
PackEnvironments.insert(packEnvironment);
298+
}
299+
293300
// Register the defaulted type variables.
294301
DefaultedConstraints.insert(solution.DefaultedConstraints.begin(),
295302
solution.DefaultedConstraints.end());
@@ -613,6 +620,7 @@ ConstraintSystem::SolverScope::SolverScope(ConstraintSystem &cs)
613620
numOpenedExistentialTypes = cs.OpenedExistentialTypes.size();
614621
numOpenedPackExpansionTypes = cs.OpenedPackExpansionTypes.size();
615622
numPackExpansionEnvironments = cs.PackExpansionEnvironments.size();
623+
numPackEnvironments = cs.PackEnvironments.size();
616624
numDefaultedConstraints = cs.DefaultedConstraints.size();
617625
numAddedNodeTypes = cs.addedNodeTypes.size();
618626
numAddedKeyPathComponentTypes = cs.addedKeyPathComponentTypes.size();
@@ -697,6 +705,9 @@ ConstraintSystem::SolverScope::~SolverScope() {
697705
// Remove any pack expansion environments.
698706
truncate(cs.PackExpansionEnvironments, numPackExpansionEnvironments);
699707

708+
// Remove any pack environments.
709+
truncate(cs.PackEnvironments, numPackEnvironments);
710+
700711
// Remove any defaulted type variables.
701712
truncate(cs.DefaultedConstraints, numDefaultedConstraints);
702713

lib/Sema/ConstraintSystem.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,21 @@ ConstraintSystem::getPackElementEnvironment(ConstraintLocator *locator,
683683
shapeParam, contextSubs);
684684
}
685685

686+
PackExpansionExpr *
687+
ConstraintSystem::getPackEnvironment(PackElementExpr *packElement) const {
688+
const auto match = PackEnvironments.find(packElement);
689+
return (match == PackEnvironments.end()) ? nullptr : match->second;
690+
}
691+
692+
void ConstraintSystem::addPackEnvironment(PackElementExpr *packElement,
693+
PackExpansionExpr *packExpansion) {
694+
assert(packElement);
695+
assert(packExpansion);
696+
[[maybe_unused]] const auto inserted =
697+
PackEnvironments.insert({packElement, packExpansion}).second;
698+
assert(inserted && "Mapping already defined?");
699+
}
700+
686701
/// Extend the given depth map by adding depths for all of the subexpressions
687702
/// of the given expression.
688703
static void extendDepthMap(

test/Constraints/pack-expansion-expressions.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ func typeReprPacks<each T: ExpressibleByIntegerLiteral>(_ t: repeat each T) {
8888
func sameShapeDiagnostics<each T, each U>(t: repeat each T, u: repeat each U) {
8989
_ = (repeat (each t, each u)) // expected-error {{pack expansion requires that 'each T' and 'each U' have the same shape}}
9090
_ = (repeat Array<(each T, each U)>()) // expected-error {{pack expansion requires that 'each T' and 'each U' have the same shape}}
91-
_ = (repeat (Array<each T>(), each u)) // expected-error {{pack expansion requires that 'each T' and 'each U' have the same shape}}
91+
_ = (repeat (Array<each T>(), each u)) // expected-error {{pack expansion requires that 'each U' and 'each T' have the same shape}}
9292
}
9393

9494
func returnPackExpansionType<each T>(_ t: repeat each T) -> repeat each T { // expected-error {{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument list}}
@@ -602,3 +602,16 @@ func test_that_expansions_are_bound_early() {
602602
})
603603
}
604604
}
605+
606+
do {
607+
func test<T>(x: T) {}
608+
609+
// rdar://110711746 to make this valid
610+
func caller1<each T>(x: repeat each T) {
611+
_ = (repeat { test(x: each x) }()) // expected-error {{pack reference 'each T' can only appear in pack expansion}}
612+
}
613+
614+
func caller2<each T>(x: repeat each T) {
615+
_ = { (repeat test(x: each x)) }()
616+
}
617+
}

0 commit comments

Comments
 (0)