Skip to content

Commit 5091886

Browse files
committed
[ConstraintSystem] Implement type checking for converting a tuple to a
pack using the `.element` syntax.
1 parent a0e1810 commit 5091886

17 files changed

+142
-0
lines changed

include/swift/AST/Expr.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3650,6 +3650,43 @@ class PackExpansionExpr final : public Expr {
36503650
}
36513651
};
36523652

3653+
/// An expression to materialize a pack from a tuple containing a pack
3654+
/// expansion, spelled \c tuple.element.
3655+
///
3656+
/// These nodes are created by CSApply and should only appear in a
3657+
/// type-checked AST in the context of a \c PackExpansionExpr .
3658+
class MaterializePackExpr final : public Expr {
3659+
/// The expression from which to materialize a pack.
3660+
Expr *FromExpr;
3661+
3662+
MaterializePackExpr(Expr *fromExpr, bool implicit, Type type)
3663+
: Expr(ExprKind::MaterializePack, implicit, type),
3664+
FromExpr(fromExpr) {}
3665+
3666+
public:
3667+
static MaterializePackExpr *create(ASTContext &ctx, Expr *fromExpr,
3668+
bool implicit = false,
3669+
Type type = Type());
3670+
3671+
Expr *getFromExpr() const { return FromExpr; }
3672+
3673+
void setFromExpr(Expr *fromExpr) {
3674+
FromExpr = fromExpr;
3675+
}
3676+
3677+
SourceLoc getStartLoc() const {
3678+
return FromExpr->getStartLoc();
3679+
}
3680+
3681+
SourceLoc getEndLoc() const {
3682+
return FromExpr->getEndLoc();
3683+
}
3684+
3685+
static bool classof(const Expr *E) {
3686+
return E->getKind() == ExprKind::MaterializePack;
3687+
}
3688+
};
3689+
36533690
/// SequenceExpr - A list of binary operations which has not yet been
36543691
/// folded into a tree. The operands all have even indices, while the
36553692
/// subexpressions with odd indices are all (potentially overloaded)

include/swift/AST/ExprNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ EXPR(InOut, Expr)
132132
EXPR(VarargExpansion, Expr)
133133
EXPR(PackExpansion, Expr)
134134
EXPR(PackElement, Expr)
135+
EXPR(MaterializePack, Expr)
135136
EXPR(DynamicType, Expr)
136137
EXPR(RebindSelfInConstructor, Expr)
137138
EXPR(OpaqueValue, Expr)

include/swift/Sema/OverloadChoice.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ enum class OverloadChoiceKind : int {
5454
/// The overload choice selects a particular declaration that
5555
/// was found by unwrapping an optional context type.
5656
DeclViaUnwrappedOptional,
57+
/// The overload choice materializes a pack from a tuple using
58+
/// the \c .element syntax.
59+
MaterializePack,
5760
/// The overload choice indexes into a tuple. Index zero will
5861
/// have the value of this enumerator, index one will have the value of this
5962
/// enumerator + 1, and so on. Thus, this enumerator must always be last.

lib/AST/ASTDumper.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2529,6 +2529,12 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
25292529
PrintWithColorRAII(OS, ParenthesisColor) << ')';
25302530
}
25312531

2532+
void visitMaterializePackExpr(MaterializePackExpr *E) {
2533+
printCommon(E, "materialize_pack_expr") << "\n";
2534+
printRec(E->getFromExpr());
2535+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
2536+
}
2537+
25322538
void visitForceTryExpr(ForceTryExpr *E) {
25332539
printCommon(E, "force_try_expr");
25342540
OS << '\n';

lib/AST/ASTPrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4959,6 +4959,11 @@ void PrintAST::visitPackExpansionExpr(PackExpansionExpr *expr) {
49594959
visit(expr->getPatternExpr());
49604960
}
49614961

4962+
void PrintAST::visitMaterializePackExpr(MaterializePackExpr *expr) {
4963+
visit(expr->getFromExpr());
4964+
Printer << ".element";
4965+
}
4966+
49624967
void PrintAST::visitPackElementExpr(PackElementExpr *expr) {
49634968
visit(expr->getPackRefExpr());
49644969
}

lib/AST/ASTWalker.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,14 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
874874
return nullptr;
875875
}
876876

877+
Expr *visitMaterializePackExpr(MaterializePackExpr *E) {
878+
if (Expr *fromExpr = doIt(E->getFromExpr())) {
879+
E->setFromExpr(fromExpr);
880+
return E;
881+
}
882+
return nullptr;
883+
}
884+
877885
Expr *visitSequenceExpr(SequenceExpr *E) {
878886
for (unsigned i = 0, e = E->getNumElements(); i != e; ++i)
879887
if (Expr *Elt = doIt(E->getElement(i)))

lib/AST/Expr.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@ ConcreteDeclRef Expr::getReferencedDecl(bool stopAtParenExpr) const {
398398
NO_REFERENCE(VarargExpansion);
399399
NO_REFERENCE(PackExpansion);
400400
NO_REFERENCE(PackElement);
401+
NO_REFERENCE(MaterializePack);
401402
NO_REFERENCE(DynamicType);
402403

403404
PASS_THROUGH_REFERENCE(RebindSelfInConstructor, getSubExpr);
@@ -757,6 +758,7 @@ bool Expr::canAppendPostfixExpression(bool appendingPostfixOperator) const {
757758
case ExprKind::VarargExpansion:
758759
case ExprKind::PackExpansion:
759760
case ExprKind::PackElement:
761+
case ExprKind::MaterializePack:
760762
return false;
761763

762764
case ExprKind::Call:
@@ -936,6 +938,7 @@ bool Expr::isValidParentOfTypeExpr(Expr *typeExpr) const {
936938
case ExprKind::VarargExpansion:
937939
case ExprKind::PackExpansion:
938940
case ExprKind::PackElement:
941+
case ExprKind::MaterializePack:
939942
case ExprKind::DynamicType:
940943
case ExprKind::RebindSelfInConstructor:
941944
case ExprKind::OpaqueValue:
@@ -1302,6 +1305,12 @@ PackElementExpr::create(ASTContext &ctx, SourceLoc eachLoc, Expr *packRefExpr,
13021305
return new (ctx) PackElementExpr(eachLoc, packRefExpr, implicit, type);
13031306
}
13041307

1308+
MaterializePackExpr *
1309+
MaterializePackExpr::create(ASTContext &ctx, Expr *fromExpr,
1310+
bool implicit, Type type) {
1311+
return new (ctx) MaterializePackExpr(fromExpr, implicit, type);
1312+
}
1313+
13051314
SequenceExpr *SequenceExpr::create(ASTContext &ctx, ArrayRef<Expr*> elements) {
13061315
assert(elements.size() & 1 && "even number of elements in sequence");
13071316
size_t bytes = totalSizeToAlloc<Expr *>(elements.size());

lib/IDE/SelectedOverloadInfo.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ swift::ide::getSelectedOverloadInfo(const Solution &S,
8686
}
8787
case OverloadChoiceKind::DynamicMemberLookup:
8888
case OverloadChoiceKind::TupleIndex:
89+
case OverloadChoiceKind::MaterializePack:
8990
// If it's DynamicMemberLookup, we don't know which function is being
9091
// called, so we can't extract any information from it.
9192
// TupleIndex isn't a function call and is not relevant for argument

lib/SILGen/SILGenExpr.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ namespace {
446446
RValue visitBridgeToObjCExpr(BridgeToObjCExpr *E, SGFContext C);
447447
RValue visitPackExpansionExpr(PackExpansionExpr *E, SGFContext C);
448448
RValue visitPackElementExpr(PackElementExpr *E, SGFContext C);
449+
RValue visitMaterializePackExpr(MaterializePackExpr *E, SGFContext C);
449450
RValue visitBridgeFromObjCExpr(BridgeFromObjCExpr *E, SGFContext C);
450451
RValue visitConditionalBridgeFromObjCExpr(ConditionalBridgeFromObjCExpr *E,
451452
SGFContext C);
@@ -1533,6 +1534,11 @@ RValueEmitter::visitPackElementExpr(PackElementExpr *E, SGFContext C) {
15331534
llvm_unreachable("not implemented for PackElementExpr");
15341535
}
15351536

1537+
RValue
1538+
RValueEmitter::visitMaterializePackExpr(MaterializePackExpr *E, SGFContext C) {
1539+
llvm_unreachable("not implemented for MaterializePackExpr");
1540+
}
1541+
15361542
RValue RValueEmitter::visitArchetypeToSuperExpr(ArchetypeToSuperExpr *E,
15371543
SGFContext C) {
15381544
ManagedValue archetype = SGF.emitRValueAsSingleValue(E->getSubExpr());

lib/Sema/CSApply.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3414,6 +3414,14 @@ namespace {
34143414
nameLoc.getBaseNameLoc(), toType));
34153415
}
34163416

3417+
case OverloadChoiceKind::MaterializePack: {
3418+
auto packType = simplifyType(cs.getType(expr));
3419+
return cs.cacheType(
3420+
MaterializePackExpr::create(cs.getASTContext(),
3421+
base, /*implicit=*/false,
3422+
packType));
3423+
}
3424+
34173425
case OverloadChoiceKind::KeyPathApplication:
34183426
llvm_unreachable("should only happen in a subscript");
34193427

@@ -3789,6 +3797,10 @@ namespace {
37893797
return simplifyExprType(expr);
37903798
}
37913799

3800+
Expr *visitMaterializePackExpr(MaterializePackExpr *expr) {
3801+
llvm_unreachable("MaterializePackExpr already type-checked");
3802+
}
3803+
37923804
Expr *visitDynamicTypeExpr(DynamicTypeExpr *expr) {
37933805
Expr *base = expr->getBase();
37943806
base = cs.coerceToRValue(base);

0 commit comments

Comments
 (0)