Skip to content

Commit 0782e45

Browse files
Merge pull request #67320 from sophiapoirier/abstract-tuple-stored-property-shadows-global
[ConstraintSystem] implement implicit pack materialization for abstract tuples instead of explicit '.element'
2 parents 1716369 + 21fe35a commit 0782e45

File tree

12 files changed

+264
-60
lines changed

12 files changed

+264
-60
lines changed

include/swift/AST/KnownIdentifiers.def

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,6 @@ IDENTIFIER(size)
325325
IDENTIFIER(speed)
326326
IDENTIFIER(unchecked)
327327
IDENTIFIER(unsafe)
328-
IDENTIFIER(element)
329328

330329
// The singleton instance of TupleTypeDecl in the Builtin module
331330
IDENTIFIER(TheTupleType)

include/swift/Sema/Constraint.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,9 @@ enum class ConstraintKind : char {
234234
ExplicitGenericArguments,
235235
/// Both (first and second) pack types should have the same reduced shape.
236236
SameShape,
237+
/// The first type is a tuple containing a single unlabeled element that is a
238+
/// pack expansion. The second type is that pack expansion.
239+
MaterializePackExpansion,
237240
};
238241

239242
/// Classification of the different kinds of constraints.
@@ -703,6 +706,7 @@ class Constraint final : public llvm::ilist_node<Constraint>,
703706
case ConstraintKind::UnresolvedMemberChainBase:
704707
case ConstraintKind::PackElementOf:
705708
case ConstraintKind::SameShape:
709+
case ConstraintKind::MaterializePackExpansion:
706710
return ConstraintClassification::Relational;
707711

708712
case ConstraintKind::ValueMember:

include/swift/Sema/ConstraintSystem.h

Lines changed: 29 additions & 1 deletion
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 *
@@ -4921,6 +4938,13 @@ class ConstraintSystem {
49214938
TypeMatchOptions flags,
49224939
ConstraintLocatorBuilder locator);
49234940

4941+
/// Remove the tuple wrapping of left-hand type if it contains only a single
4942+
/// unlabeled element that is a pack expansion.
4943+
SolutionKind
4944+
simplifyMaterializePackExpansionConstraint(Type type1, Type type2,
4945+
TypeMatchOptions flags,
4946+
ConstraintLocatorBuilder locator);
4947+
49244948
public: // FIXME: Public for use by static functions.
49254949
/// Simplify a conversion constraint with a fix applied to it.
49264950
SolutionKind simplifyFixConstraint(ConstraintFix *fix, Type type1, Type type2,
@@ -5463,7 +5487,8 @@ class OpenPackElementType {
54635487
}
54645488

54655489
cs.addConstraint(ConstraintKind::PackElementOf, elementType,
5466-
packType, cs.getConstraintLocator(elementEnv));
5490+
packType->getRValueType(),
5491+
cs.getConstraintLocator(elementEnv));
54675492
return elementType;
54685493
}
54695494
};
@@ -6146,6 +6171,9 @@ void dumpAnchor(ASTNode anchor, SourceManager *SM, raw_ostream &out);
61466171

61476172
bool isSingleUnlabeledPackExpansionTuple(Type type);
61486173

6174+
/// \returns null if \c type is not a single unlabeled pack expansion tuple.
6175+
Type getPatternTypeOfSingleUnlabeledPackExpansionTuple(Type type);
6176+
61496177
} // end namespace constraints
61506178

61516179
template<typename ...Args>

lib/Sema/CSApply.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3852,9 +3852,8 @@ namespace {
38523852
auto packRefType = cs.getType(packRefExpr);
38533853
if (auto *tuple = packRefType->getRValueType()->getAs<TupleType>();
38543854
tuple && tuple->isSingleUnlabeledPackExpansion()) {
3855-
auto *expansion =
3856-
tuple->getElementType(0)->castTo<PackExpansionType>();
3857-
auto patternType = expansion->getPatternType();
3855+
auto patternType =
3856+
getPatternTypeOfSingleUnlabeledPackExpansionTuple(tuple);
38583857
auto *materializedPackExpr = MaterializePackExpr::create(
38593858
cs.getASTContext(), packRefExpr, packRefExpr->getLoc(),
38603859
patternType, /*implicit*/ true);

lib/Sema/CSBindings.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1483,6 +1483,7 @@ void PotentialBindings::infer(Constraint *constraint) {
14831483
case ConstraintKind::ExplicitGenericArguments:
14841484
case ConstraintKind::PackElementOf:
14851485
case ConstraintKind::SameShape:
1486+
case ConstraintKind::MaterializePackExpansion:
14861487
// Constraints from which we can't do anything.
14871488
break;
14881489

lib/Sema/CSDiagnostics.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6170,8 +6170,10 @@ bool InvalidPackElement::diagnoseAsError() {
61706170
}
61716171

61726172
bool InvalidPackReference::diagnoseAsError() {
6173-
emitDiagnostic(diag::pack_reference_outside_expansion,
6174-
packType);
6173+
auto patternType =
6174+
getPatternTypeOfSingleUnlabeledPackExpansionTuple(packType);
6175+
auto diagnosisType = patternType ? patternType : packType;
6176+
emitDiagnostic(diag::pack_reference_outside_expansion, diagnosisType);
61756177
return true;
61766178
}
61776179

lib/Sema/CSGen.cpp

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

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) {
10981095
return CS.createTypeVariable(locator,
10991096
TVO_CanBindToHole | TVO_CanBindToNoEscape);
11001097
}
11011098

11021099
// The type of a PackElementExpr is the opened pack element archetype
11031100
// of the pack reference.
1104-
OpenPackElementType openPackElement(CS, locator,
1105-
PackElementEnvironments.back());
1101+
OpenPackElementType openPackElement(CS, locator, packElementEnvironment);
11061102
return openPackElement(packType, /*packRepr*/ nullptr);
11071103
}
11081104

@@ -1124,6 +1120,26 @@ namespace {
11241120

11251121
void addPackElementEnvironment(PackExpansionExpr *expr) {
11261122
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);
11271143
}
11281144

11291145
virtual Type visitErrorExpr(ErrorExpr *E) {
@@ -1384,6 +1400,17 @@ namespace {
13841400
return BoundGenericStructType::get(regexDecl, Type(), {matchType});
13851401
}
13861402

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+
13871414
Type visitDeclRefExpr(DeclRefExpr *E) {
13881415
auto locator = CS.getConstraintLocator(E);
13891416

@@ -1426,13 +1453,15 @@ namespace {
14261453

14271454
// value packs cannot be referenced without `each` immediately
14281455
// 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 &&
14311459
!isExpr<PackElementExpr>(CS.getParentExpr(E))) {
1432-
auto packType = expansion->getPatternType();
1460+
auto packType = expansionType->getPatternType();
14331461
(void)CS.recordFix(
14341462
IgnoreMissingEachKeyword::create(CS, packType, locator));
1435-
auto eltType = openPackElement(packType, locator);
1463+
auto eltType =
1464+
openPackElement(packType, locator, parentExpansionExpr);
14361465
CS.setType(E, eltType);
14371466
return eltType;
14381467
}
@@ -3033,21 +3062,11 @@ namespace {
30333062
assert(PackElementEnvironments.back() == expr);
30343063
PackElementEnvironments.pop_back();
30353064

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>();
30423066
auto elementResultType = CS.getType(expr->getPatternExpr());
30433067
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));
30513070

30523071
// Generate ShapeOf constraints between all packs expanded by this
30533072
// pack expansion expression through the shape type variable.
@@ -3061,9 +3080,14 @@ namespace {
30613080

30623081
for (auto pack : expandedPacks) {
30633082
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)) {
30673091
// OpenPackElementType sets types for 'each T' type reprs in
30683092
// expressions. Some invalid code won't make it there, and
30693093
// the constraint system won't have recorded a type.
@@ -3075,26 +3099,47 @@ namespace {
30753099
llvm_unreachable("unsupported pack reference ASTNode");
30763100
}
30773101

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));
30783108
CS.addConstraint(
3079-
ConstraintKind::ShapeOf, shapeTypeVar, packType,
3109+
ConstraintKind::Equal, elementShape, expansionType->getCountType(),
30803110
CS.getConstraintLocator(expr, ConstraintLocator::PackShape));
30813111
}
30823112

3083-
return PackExpansionType::get(patternTy, shapeTypeVar);
3113+
return expansionType;
30843114
}
30853115

30863116
Type visitPackElementExpr(PackElementExpr *expr) {
30873117
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())));
30953140
}
30963141

3097-
return openPackElement(packType, CS.getConstraintLocator(expr));
3142+
return elementType;
30983143
}
30993144

31003145
Type visitMaterializePackExpr(MaterializePackExpr *expr) {

0 commit comments

Comments
 (0)