Skip to content

Commit 7354ad3

Browse files
committed
[ConstraintSystem] Use opened element types for opaque values in pack expansions.
1 parent 5c9b8bf commit 7354ad3

File tree

7 files changed

+110
-21
lines changed

7 files changed

+110
-21
lines changed

include/swift/AST/Expr.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3531,14 +3531,16 @@ class PackExpansionExpr final : public Expr,
35313531

35323532
Expr *PatternExpr;
35333533
SourceLoc DotsLoc;
3534+
GenericEnvironment *Environment;
35343535

35353536
PackExpansionExpr(Expr *patternExpr,
35363537
ArrayRef<OpaqueValueExpr *> opaqueValues,
35373538
ArrayRef<Expr *> bindings,
35383539
SourceLoc dotsLoc,
3540+
GenericEnvironment *environment,
35393541
bool implicit, Type type)
35403542
: Expr(ExprKind::PackExpansion, implicit, type),
3541-
PatternExpr(patternExpr), DotsLoc(dotsLoc) {
3543+
PatternExpr(patternExpr), DotsLoc(dotsLoc), Environment(environment) {
35423544
assert(opaqueValues.size() == bindings.size());
35433545
Bits.PackExpansionExpr.NumBindings = opaqueValues.size();
35443546

@@ -3569,6 +3571,7 @@ class PackExpansionExpr final : public Expr,
35693571
ArrayRef<OpaqueValueExpr *> opaqueValues,
35703572
ArrayRef<Expr *> bindings,
35713573
SourceLoc dotsLoc,
3574+
GenericEnvironment *environment,
35723575
bool implicit = false,
35733576
Type type = Type());
35743577

@@ -3594,6 +3597,10 @@ class PackExpansionExpr final : public Expr,
35943597
getMutableBindings()[i] = e;
35953598
}
35963599

3600+
GenericEnvironment *getGenericEnvironment() {
3601+
return Environment;
3602+
}
3603+
35973604
SourceLoc getStartLoc() const {
35983605
return PatternExpr->getStartLoc();
35993606
}

lib/AST/ASTVerifier.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,8 @@ class Verifier : public ASTWalker {
824824
if (!shouldVerify(cast<Expr>(expr)))
825825
return false;
826826

827+
Generics.push_back(expr->getGenericEnvironment()->getGenericSignature());
828+
827829
for (auto *placeholder : expr->getOpaqueValues()) {
828830
assert(!OpaqueValues.count(placeholder));
829831
OpaqueValues[placeholder] = 0;
@@ -832,6 +834,15 @@ class Verifier : public ASTWalker {
832834
return true;
833835
}
834836

837+
void verifyCheckedAlways(PackExpansionExpr *E) {
838+
// Remove the element generic environment before verifying
839+
// the pack expansion type, which contains pack archetypes.
840+
assert(Generics.back().get<GenericSignature>().getPointer() ==
841+
E->getGenericEnvironment()->getGenericSignature().getPointer());
842+
Generics.pop_back();
843+
verifyCheckedAlwaysBase(E);
844+
}
845+
835846
void cleanup(PackExpansionExpr *expr) {
836847
for (auto *placeholder : expr->getOpaqueValues()) {
837848
assert(OpaqueValues.count(placeholder));

lib/AST/Expr.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,15 +1240,15 @@ VarargExpansionExpr *VarargExpansionExpr::createArrayExpansion(ASTContext &ctx,
12401240
PackExpansionExpr *
12411241
PackExpansionExpr::create(ASTContext &ctx, Expr *patternExpr,
12421242
ArrayRef<OpaqueValueExpr *> opaqueValues,
1243-
ArrayRef<Expr *> bindings,
1244-
SourceLoc dotsLoc, bool implicit,
1245-
Type type) {
1243+
ArrayRef<Expr *> bindings, SourceLoc dotsLoc,
1244+
GenericEnvironment *environment,
1245+
bool implicit, Type type) {
12461246
size_t size =
12471247
totalSizeToAlloc<OpaqueValueExpr *, Expr *>(opaqueValues.size(),
12481248
bindings.size());
12491249
void *mem = ctx.Allocate(size, alignof(PackExpansionExpr));
12501250
return ::new (mem) PackExpansionExpr(patternExpr, opaqueValues,
1251-
bindings, dotsLoc,
1251+
bindings, dotsLoc, environment,
12521252
implicit, type);
12531253
}
12541254

lib/Sema/CSApply.cpp

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7095,16 +7095,44 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
70957095
auto toExpansionType = toType->getAs<PackExpansionType>();
70967096
auto *expansion = dyn_cast<PackExpansionExpr>(expr);
70977097

7098+
// FIXME: Duplicated code from `PackReferenceFinder` in PreCheckExpr.
7099+
auto toElementType = toExpansionType->getPatternType();
7100+
toElementType =
7101+
toElementType->mapTypeOutOfContext().transform([&](Type type) -> Type {
7102+
auto *genericParam = type->getAs<GenericTypeParamType>();
7103+
if (!genericParam || !genericParam->isParameterPack())
7104+
return type;
7105+
7106+
auto param = GenericTypeParamType::get(/*isParameterPack*/false,
7107+
genericParam->getDepth(),
7108+
genericParam->getIndex(), ctx);
7109+
return expansion->getGenericEnvironment()->mapTypeIntoContext(param);
7110+
});
7111+
70987112
auto *pattern = coerceToType(expansion->getPatternExpr(),
7099-
toExpansionType->getPatternType(),
7100-
locator);
7101-
auto patternType = cs.getType(pattern);
7113+
toElementType, locator);
7114+
7115+
// FIXME: Duplicated code from `visitPackExpansionExpr` in CSGen.
7116+
auto patternType =
7117+
cs.getType(pattern).transform([&](Type type) -> Type {
7118+
auto *element = type->getAs<ElementArchetypeType>();
7119+
if (!element)
7120+
return type;
7121+
7122+
auto *elementParam = element->mapTypeOutOfContext()->getAs<GenericTypeParamType>();
7123+
auto *pack = GenericTypeParamType::get(/*isParameterPack*/true,
7124+
elementParam->getDepth(),
7125+
elementParam->getIndex(),
7126+
ctx);
7127+
return cs.DC->mapTypeIntoContext(pack);
7128+
});
71027129
auto shapeType = toExpansionType->getCountType();
71037130
auto expansionTy = PackExpansionType::get(patternType, shapeType);
71047131

71057132
return cs.cacheType(PackExpansionExpr::create(ctx, pattern,
71067133
expansion->getOpaqueValues(), expansion->getBindings(),
7107-
expansion->getEndLoc(), expansion->isImplicit(), expansionTy));
7134+
expansion->getEndLoc(), expansion->getGenericEnvironment(),
7135+
expansion->isImplicit(), expansionTy));
71087136
}
71097137

71107138
case TypeKind::BuiltinTuple:

lib/Sema/CSGen.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2886,7 +2886,21 @@ namespace {
28862886
CS.setType(binding, type);
28872887
}
28882888

2889-
auto patternTy = CS.getType(expr->getPatternExpr());
2889+
// Replace opened element archetypes with pack archetypes
2890+
// for the resulting type of the pack expansion.
2891+
auto elementResultType = CS.getType(expr->getPatternExpr());
2892+
auto patternTy = elementResultType.transform([&](Type type) -> Type {
2893+
auto *element = type->getAs<ElementArchetypeType>();
2894+
if (!element)
2895+
return type;
2896+
2897+
auto *elementParam = element->mapTypeOutOfContext()->getAs<GenericTypeParamType>();
2898+
auto *pack = GenericTypeParamType::get(/*isParameterPack*/true,
2899+
elementParam->getDepth(),
2900+
elementParam->getIndex(),
2901+
CS.getASTContext());
2902+
return CS.DC->mapTypeIntoContext(pack);
2903+
});
28902904

28912905
// FIXME: Use a ShapeOf constraint here.
28922906
Type shapeType;

lib/Sema/PreCheckExpr.cpp

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "swift/AST/ASTVisitor.h"
2222
#include "swift/AST/ASTWalker.h"
2323
#include "swift/AST/DiagnosticsParse.h"
24+
#include "swift/AST/GenericEnvironment.h"
2425
#include "swift/AST/NameLookup.h"
2526
#include "swift/AST/NameLookupRequests.h"
2627
#include "swift/AST/ParameterList.h"
@@ -414,15 +415,19 @@ static bool exprLooksLikeAType(Expr *expr) {
414415
getCompositionExpr(expr);
415416
}
416417

417-
static Expr *getPackExpansion(ASTContext &ctx, Expr *expr, SourceLoc opLoc) {
418+
static Expr *getPackExpansion(DeclContext *dc, Expr *expr, SourceLoc opLoc) {
418419
struct PackReferenceFinder : public ASTWalker {
419-
ASTContext &ctx;
420+
DeclContext *dc;
420421
llvm::SmallVector<OpaqueValueExpr *, 2> opaqueValues;
421422
llvm::SmallVector<Expr *, 2> bindings;
423+
GenericEnvironment *environment;
422424

423-
PackReferenceFinder(ASTContext &ctx) : ctx(ctx) {}
425+
PackReferenceFinder(DeclContext *dc)
426+
: dc(dc), environment(nullptr) {}
424427

425428
virtual PreWalkResult<Expr *> walkToExprPre(Expr *E) override {
429+
auto &ctx = dc->getASTContext();
430+
426431
if (auto *declRef = dyn_cast<DeclRefExpr>(E)) {
427432
auto *decl = dyn_cast<VarDecl>(declRef->getDecl());
428433
if (!decl)
@@ -431,11 +436,30 @@ static Expr *getPackExpansion(ASTContext &ctx, Expr *expr, SourceLoc opLoc) {
431436
if (auto expansionType = decl->getType()->getAs<PackExpansionType>()) {
432437
auto sourceRange = declRef->getSourceRange();
433438

434-
// FIXME: The OpaqueValueExpr should use the opened element
435-
// type of the pattern.
439+
// Map the pattern interface type to the element interface type
440+
// by making all type parameter packs scalar type parameters.
436441
auto patternType = expansionType->getPatternType();
437-
auto *opaqueValue = new (ctx) OpaqueValueExpr(sourceRange,
438-
patternType);
442+
auto elementInterfaceType =
443+
patternType->mapTypeOutOfContext().transform([&](Type type) -> Type {
444+
auto *genericParam = type->getAs<GenericTypeParamType>();
445+
if (!genericParam || !genericParam->isParameterPack())
446+
return type;
447+
448+
return GenericTypeParamType::get(/*isParameterPack*/false,
449+
genericParam->getDepth(),
450+
genericParam->getIndex(), ctx);
451+
});
452+
453+
// Map the element interface type into the context of the opened
454+
// element signature.
455+
if (!environment) {
456+
auto sig = ctx.getOpenedElementSignature(
457+
dc->getGenericSignatureOfContext().getCanonicalSignature());
458+
environment = GenericEnvironment::forOpenedElement(sig, UUID::fromTime());
459+
}
460+
auto elementType = environment->mapTypeIntoContext(elementInterfaceType);
461+
462+
auto *opaqueValue = new (ctx) OpaqueValueExpr(sourceRange, elementType);
439463
opaqueValues.push_back(opaqueValue);
440464
bindings.push_back(declRef);
441465
return Action::Continue(opaqueValue);
@@ -444,15 +468,15 @@ static Expr *getPackExpansion(ASTContext &ctx, Expr *expr, SourceLoc opLoc) {
444468

445469
return Action::Continue(E);
446470
}
447-
} packReferenceFinder(ctx);
471+
} packReferenceFinder(dc);
448472

449473
auto *pattern = expr->walk(packReferenceFinder);
450474

451475
if (!packReferenceFinder.bindings.empty()) {
452-
return PackExpansionExpr::create(ctx, pattern,
476+
return PackExpansionExpr::create(dc->getASTContext(), pattern,
453477
packReferenceFinder.opaqueValues,
454478
packReferenceFinder.bindings,
455-
opLoc);
479+
opLoc, packReferenceFinder.environment);
456480
}
457481

458482
return nullptr;
@@ -1356,7 +1380,7 @@ namespace {
13561380
auto *op = dyn_cast<OverloadedDeclRefExpr>(postfixExpr->getFn());
13571381
if (op && op->getDecls()[0]->getBaseName().getIdentifier().isExpansionOperator()) {
13581382
auto *operand = postfixExpr->getOperand();
1359-
if (auto *expansion = getPackExpansion(Ctx, operand, op->getLoc())) {
1383+
if (auto *expansion = getPackExpansion(DC, operand, op->getLoc())) {
13601384
return Action::Continue(expansion);
13611385
}
13621386
}

test/Constraints/pack-expansion-expressions.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,14 @@ func forward<U...>(_ u: U...) -> (U...) {
2020
return tuplify(u...)
2121
}
2222

23+
// FIXME: This fails with opened element types. Add an ElementOf constraint to
24+
// handle cases where the pattern type is resolved after constraint generation
25+
// and mapped to pack archetypes in the solver.
26+
/*
2327
func forwardAndMap<U..., V...>(us u: U..., vs v: V...) -> ([(U, V)]...) {
2428
return tuplify([(u, v)]...)
2529
}
30+
*/
2631

2732
func variadicMap<T..., Result...>(_ t: T..., transform: ((T) -> Result)...) -> (Result...) {
2833
return (transform(t)...)

0 commit comments

Comments
 (0)