Skip to content

Commit 5895356

Browse files
committed
[CSGen] Use PackExpansionExpr::getExpandedPacks to generate ShapeOf constraints
rather than relying on PackElementExprs collected by preCheck. This handles pack element expressions and pack element type reprs, and enforces that all packs expanded by a given pack expansion expression all have the same shape. Once the parser creates PackExpansionExpr directly (based on a dedicated syntax instead of postfix '...'), the code in preCheck for identifying and creating pack expansions can simply be deleted.
1 parent b977adf commit 5895356

File tree

7 files changed

+36
-16
lines changed

7 files changed

+36
-16
lines changed

include/swift/AST/Types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ class InOutType;
7272
class OpaqueTypeDecl;
7373
class OpenedArchetypeType;
7474
class PackType;
75+
class PackReferenceTypeRepr;
7576
class PlaceholderTypeRepr;
7677
enum class ReferenceCounting : uint8_t;
7778
enum class ResilienceExpansion : unsigned;

include/swift/Sema/ConstraintSystem.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6130,7 +6130,7 @@ class OpenPackElementType {
61306130
this->locator = cs.getConstraintLocator(locator);
61316131
}
61326132

6133-
Type operator()(Type packType) const {
6133+
Type operator()(Type packType, PackReferenceTypeRepr *packRepr) const {
61346134
// Only assert we have an element environment when invoking the function
61356135
// object. In cases where pack elements are referenced outside of a
61366136
// pack expansion, type resolution will error before opening the pack
@@ -6141,6 +6141,14 @@ class OpenPackElementType {
61416141
auto elementLoc = cs.getConstraintLocator(locator,
61426142
LocatorPathElt::OpenedPackElement(elementEnv));
61436143

6144+
// If we're opening a pack element from an explicit type repr,
6145+
// set the type repr types in the constraint system for generating
6146+
// ShapeOf constraints when visiting the PackExpansionExpr.
6147+
if (packRepr) {
6148+
cs.setType(packRepr->getPackType(), packType);
6149+
cs.setType(packRepr, elementType);
6150+
}
6151+
61446152
cs.addConstraint(ConstraintKind::PackElementOf, elementType,
61456153
packType, elementLoc);
61466154
return elementType;

lib/Sema/CSGen.cpp

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3009,18 +3009,24 @@ namespace {
30093009
auto *shapeTypeVar = CS.createTypeVariable(shapeLoc,
30103010
TVO_CanBindToPack |
30113011
TVO_CanBindToHole);
3012-
Type packType;
3013-
if (!expr->getPackElements().empty()) {
3014-
auto packReference = expr->getPackElements().front()->getPackRefExpr();
3015-
packType = CS.simplifyType(CS.getType(packReference));
3016-
} else {
3017-
// FIXME: The generic environment needs to be per-shape-class.
3018-
llvm::SmallVector<GenericEnvironment::PackElementBinding, 2> bindings;
3019-
elementEnv->getPackElementBindings(bindings);
3020-
packType = bindings.front().second;
3012+
3013+
// Generate ShapeOf constraints between all packs expanded by this
3014+
// pack expansion expression through the shape type variable.
3015+
SmallVector<ASTNode, 2> expandedPacks;
3016+
expr->getExpandedPacks(expandedPacks);
3017+
for (auto pack : expandedPacks) {
3018+
Type packType;
3019+
if (auto *elementExpr = getAsExpr<PackElementExpr>(pack)) {
3020+
packType = CS.getType(elementExpr->getPackRefExpr());
3021+
} else if (auto *elementType = getAsTypeRepr<PackReferenceTypeRepr>(pack)) {
3022+
packType = CS.getType(elementType->getPackType());
3023+
} else {
3024+
llvm_unreachable("unsupported pack reference ASTNode");
3025+
}
3026+
3027+
CS.addConstraint(ConstraintKind::ShapeOf, packType, shapeTypeVar,
3028+
CS.getConstraintLocator(expr));
30213029
}
3022-
CS.addConstraint(ConstraintKind::ShapeOf, packType, shapeTypeVar,
3023-
CS.getConstraintLocator(expr));
30243030

30253031
return PackExpansionType::get(patternTy, shapeTypeVar);
30263032
}
@@ -3032,7 +3038,7 @@ namespace {
30323038
// of the pack reference.
30333039
OpenPackElementType openPackElement(CS, CS.getConstraintLocator(expr),
30343040
PackElementEnvironments.back());
3035-
return openPackElement(packType);
3041+
return openPackElement(packType, /*packRepr*/ nullptr);
30363042
}
30373043

30383044
Type visitDynamicTypeExpr(DynamicTypeExpr *expr) {

lib/Sema/ConstraintSystem.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -781,7 +781,7 @@ Type ConstraintSystem::openUnboundGenericType(GenericTypeDecl *decl,
781781
DC, None,
782782
[](auto) -> Type { llvm_unreachable("should not be used"); },
783783
[](auto &, auto) -> Type { llvm_unreachable("should not be used"); },
784-
[](auto) -> Type { llvm_unreachable("should not be used"); })
784+
[](auto, auto) -> Type { llvm_unreachable("should not be used"); })
785785
.applyUnboundGenericArguments(decl, parentTy, SourceLoc(), arguments);
786786
if (!parentTy && !isTypeResolution) {
787787
result = DC->mapTypeIntoContext(result);

lib/Sema/PreCheckExpr.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,10 @@ static BinaryExpr *getCompositionExpr(Expr *expr) {
400400
}
401401

402402
static Expr *getPackExpansion(DeclContext *dc, Expr *expr, SourceLoc opLoc) {
403+
// FIXME: The parser should create PackExpansionExprs directly, pack
404+
// elements should be discovered via PackExpansionExpr::getExpandedPacks,
405+
// and the generic environment should be created lazily when solving
406+
// PackElementOf constraints.
403407
struct PackReferenceFinder : public ASTWalker {
404408
DeclContext *dc;
405409
llvm::SmallVector<PackElementExpr *, 2> packElements;

lib/Sema/TypeCheckType.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4288,7 +4288,7 @@ NeverNullType TypeResolver::resolvePackReference(PackReferenceTypeRepr *repr,
42884288
// Open the pack reference to an element archetype if requested.
42894289
if (auto openPackElement = resolution.getPackElementOpener()) {
42904290
auto *env = resolution.getGenericSignature().getGenericEnvironment();
4291-
return openPackElement(env->mapTypeIntoContext(packReference));
4291+
return openPackElement(env->mapTypeIntoContext(packReference), repr);
42924292
}
42934293

42944294
return packReference;

lib/Sema/TypeCheckType.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,8 @@ using HandlePlaceholderTypeReprFn =
482482

483483
/// A function reference used to replace pack references with opened
484484
/// element archetypes when resolving a \c PackReferenceTypeRepr.
485-
using OpenPackElementFn = llvm::function_ref<Type(Type)>;
485+
using OpenPackElementFn =
486+
llvm::function_ref<Type(Type, PackReferenceTypeRepr *)>;
486487

487488
/// Handles the resolution of types within a given declaration context,
488489
/// which might involve resolving generic parameters to a particular

0 commit comments

Comments
 (0)