@@ -1089,20 +1089,16 @@ namespace {
1089
1089
return outputTy;
1090
1090
}
1091
1091
1092
- Type openPackElement (Type packType, ConstraintLocator *locator) {
1093
- // If 'each t' is written outside of a pack expansion expression, allow the
1094
- // type to bind to a hole. The invalid pack reference will be diagnosed when
1095
- // attempting to bind the type variable for the underlying pack reference to
1096
- // a pack type without TVO_CanBindToPack.
1097
- if (PackElementEnvironments.empty ()) {
1092
+ Type openPackElement (Type packType, ConstraintLocator *locator,
1093
+ PackExpansionExpr *packElementEnvironment) {
1094
+ if (!packElementEnvironment) {
1098
1095
return CS.createTypeVariable (locator,
1099
1096
TVO_CanBindToHole | TVO_CanBindToNoEscape);
1100
1097
}
1101
1098
1102
1099
// The type of a PackElementExpr is the opened pack element archetype
1103
1100
// of the pack reference.
1104
- OpenPackElementType openPackElement (CS, locator,
1105
- PackElementEnvironments.back ());
1101
+ OpenPackElementType openPackElement (CS, locator, packElementEnvironment);
1106
1102
return openPackElement (packType, /* packRepr*/ nullptr );
1107
1103
}
1108
1104
@@ -1124,6 +1120,26 @@ namespace {
1124
1120
1125
1121
void addPackElementEnvironment (PackExpansionExpr *expr) {
1126
1122
PackElementEnvironments.push_back (expr);
1123
+
1124
+ SmallVector<ASTNode, 2 > expandedPacks;
1125
+ collectExpandedPacks (expr, expandedPacks);
1126
+ for (auto pack : expandedPacks) {
1127
+ if (auto *elementExpr = getAsExpr<PackElementExpr>(pack)) {
1128
+ CS.addPackEnvironment (elementExpr, expr);
1129
+ }
1130
+ }
1131
+
1132
+ auto *patternLoc = CS.getConstraintLocator (
1133
+ expr, ConstraintLocator::PackExpansionPattern);
1134
+ auto patternType = CS.createTypeVariable (
1135
+ patternLoc,
1136
+ TVO_CanBindToPack | TVO_CanBindToNoEscape | TVO_CanBindToHole);
1137
+ auto *shapeLoc =
1138
+ CS.getConstraintLocator (expr, ConstraintLocator::PackShape);
1139
+ auto *shapeTypeVar = CS.createTypeVariable (
1140
+ shapeLoc, TVO_CanBindToPack | TVO_CanBindToHole);
1141
+ auto expansionType = PackExpansionType::get (patternType, shapeTypeVar);
1142
+ CS.setType (expr, expansionType);
1127
1143
}
1128
1144
1129
1145
virtual Type visitErrorExpr (ErrorExpr *E) {
@@ -1384,6 +1400,17 @@ namespace {
1384
1400
return BoundGenericStructType::get (regexDecl, Type (), {matchType});
1385
1401
}
1386
1402
1403
+ PackExpansionExpr *getParentPackExpansionExpr (Expr *E) const {
1404
+ auto *current = E;
1405
+ while (auto *parent = CS.getParentExpr (current)) {
1406
+ if (auto *expansion = dyn_cast<PackExpansionExpr>(parent)) {
1407
+ return expansion;
1408
+ }
1409
+ current = parent;
1410
+ }
1411
+ return nullptr ;
1412
+ }
1413
+
1387
1414
Type visitDeclRefExpr (DeclRefExpr *E) {
1388
1415
auto locator = CS.getConstraintLocator (E);
1389
1416
@@ -1426,13 +1453,15 @@ namespace {
1426
1453
1427
1454
// value packs cannot be referenced without `each` immediately
1428
1455
// preceding them.
1429
- if (auto *expansion = knownType->getAs <PackExpansionType>()) {
1430
- if (!PackElementEnvironments.empty () &&
1456
+ if (auto *expansionType = knownType->getAs <PackExpansionType>()) {
1457
+ if (auto *parentExpansionExpr = getParentPackExpansionExpr (E);
1458
+ parentExpansionExpr &&
1431
1459
!isExpr<PackElementExpr>(CS.getParentExpr (E))) {
1432
- auto packType = expansion ->getPatternType ();
1460
+ auto packType = expansionType ->getPatternType ();
1433
1461
(void )CS.recordFix (
1434
1462
IgnoreMissingEachKeyword::create (CS, packType, locator));
1435
- auto eltType = openPackElement (packType, locator);
1463
+ auto eltType =
1464
+ openPackElement (packType, locator, parentExpansionExpr);
1436
1465
CS.setType (E, eltType);
1437
1466
return eltType;
1438
1467
}
@@ -3033,21 +3062,11 @@ namespace {
3033
3062
assert (PackElementEnvironments.back () == expr);
3034
3063
PackElementEnvironments.pop_back ();
3035
3064
3036
- auto *patternLoc =
3037
- CS.getConstraintLocator (expr, ConstraintLocator::PackExpansionPattern);
3038
- auto patternTy = CS.createTypeVariable (patternLoc,
3039
- TVO_CanBindToPack |
3040
- TVO_CanBindToNoEscape |
3041
- TVO_CanBindToHole);
3065
+ auto expansionType = CS.getType (expr)->castTo <PackExpansionType>();
3042
3066
auto elementResultType = CS.getType (expr->getPatternExpr ());
3043
3067
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);
3068
+ expansionType->getPatternType (),
3069
+ CS.getConstraintLocator (expr));
3051
3070
3052
3071
// Generate ShapeOf constraints between all packs expanded by this
3053
3072
// pack expansion expression through the shape type variable.
@@ -3061,9 +3080,14 @@ namespace {
3061
3080
3062
3081
for (auto pack : expandedPacks) {
3063
3082
Type packType;
3064
- if (auto *elementExpr = getAsExpr<PackElementExpr>(pack)) {
3065
- packType = CS.getType (elementExpr->getPackRefExpr ());
3066
- } else if (auto *elementType = getAsTypeRepr<PackElementTypeRepr>(pack)) {
3083
+ // / Skipping over pack elements because the relationship to its
3084
+ // / environment is now established during \c addPackElementEnvironment
3085
+ // / upon visiting its pack expansion and the Shape constraint added
3086
+ // / upon visiting the pack element.
3087
+ if (isExpr<PackElementExpr>(pack)) {
3088
+ continue ;
3089
+ } else if (auto *elementType =
3090
+ getAsTypeRepr<PackElementTypeRepr>(pack)) {
3067
3091
// OpenPackElementType sets types for 'each T' type reprs in
3068
3092
// expressions. Some invalid code won't make it there, and
3069
3093
// the constraint system won't have recorded a type.
@@ -3075,26 +3099,47 @@ namespace {
3075
3099
llvm_unreachable (" unsupported pack reference ASTNode" );
3076
3100
}
3077
3101
3102
+ auto *elementShape = CS.createTypeVariable (
3103
+ CS.getConstraintLocator (pack, ConstraintLocator::PackShape),
3104
+ TVO_CanBindToPack);
3105
+ CS.addConstraint (
3106
+ ConstraintKind::ShapeOf, elementShape, packType,
3107
+ CS.getConstraintLocator (pack, ConstraintLocator::PackShape));
3078
3108
CS.addConstraint (
3079
- ConstraintKind::ShapeOf, shapeTypeVar, packType ,
3109
+ ConstraintKind::Equal, elementShape, expansionType-> getCountType () ,
3080
3110
CS.getConstraintLocator (expr, ConstraintLocator::PackShape));
3081
3111
}
3082
3112
3083
- return PackExpansionType::get (patternTy, shapeTypeVar) ;
3113
+ return expansionType ;
3084
3114
}
3085
3115
3086
3116
Type visitPackElementExpr (PackElementExpr *expr) {
3087
3117
auto packType = CS.getType (expr->getPackRefExpr ());
3088
-
3089
- if (isSingleUnlabeledPackExpansionTuple (packType)) {
3090
- packType =
3091
- addMemberRefConstraints (expr, expr->getPackRefExpr (),
3092
- DeclNameRef (CS.getASTContext ().Id_element ),
3093
- FunctionRefKind::Unapplied, {});
3094
- CS.setType (expr->getPackRefExpr (), packType);
3118
+ auto *packEnvironment = CS.getPackEnvironment (expr);
3119
+ auto elementType = openPackElement (
3120
+ packType, CS.getConstraintLocator (expr), packEnvironment);
3121
+ if (packEnvironment) {
3122
+ auto expansionType =
3123
+ CS.getType (packEnvironment)->castTo <PackExpansionType>();
3124
+ CS.addConstraint (ConstraintKind::ShapeOf, expansionType->getCountType (),
3125
+ elementType,
3126
+ CS.getConstraintLocator (packEnvironment,
3127
+ ConstraintLocator::PackShape));
3128
+ auto *elementShape = CS.createTypeVariable (
3129
+ CS.getConstraintLocator (expr, ConstraintLocator::PackShape),
3130
+ TVO_CanBindToPack);
3131
+ CS.addConstraint (
3132
+ ConstraintKind::ShapeOf, elementShape, elementType,
3133
+ CS.getConstraintLocator (expr, ConstraintLocator::PackShape));
3134
+ CS.addConstraint (
3135
+ ConstraintKind::Equal, elementShape, expansionType->getCountType (),
3136
+ CS.getConstraintLocator (expr, ConstraintLocator::PackShape));
3137
+ } else {
3138
+ CS.recordFix (AllowInvalidPackReference::create (
3139
+ CS, packType, CS.getConstraintLocator (expr->getPackRefExpr ())));
3095
3140
}
3096
3141
3097
- return openPackElement (packType, CS. getConstraintLocator (expr)) ;
3142
+ return elementType ;
3098
3143
}
3099
3144
3100
3145
Type visitMaterializePackExpr (MaterializePackExpr *expr) {
0 commit comments