Skip to content

Commit b78b6b9

Browse files
authored
Merge pull request #63991 from hborla/materialize-pack-from-tuple
[ConstraintSystem] Implement type checking for converting a tuple to a pack using the `.element` syntax.
2 parents 54b35e8 + 00aad22 commit b78b6b9

17 files changed

+148
-0
lines changed

include/swift/AST/Expr.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3650,6 +3650,47 @@ 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+
/// The source location of \c .element
3663+
SourceLoc ElementLoc;
3664+
3665+
MaterializePackExpr(Expr *fromExpr, SourceLoc elementLoc,
3666+
Type type, bool implicit)
3667+
: Expr(ExprKind::MaterializePack, implicit, type),
3668+
FromExpr(fromExpr), ElementLoc(elementLoc) {}
3669+
3670+
public:
3671+
static MaterializePackExpr *create(ASTContext &ctx, Expr *fromExpr,
3672+
SourceLoc elementLoc, Type type,
3673+
bool implicit = false);
3674+
3675+
Expr *getFromExpr() const { return FromExpr; }
3676+
3677+
void setFromExpr(Expr *fromExpr) {
3678+
FromExpr = fromExpr;
3679+
}
3680+
3681+
SourceLoc getStartLoc() const {
3682+
return FromExpr->getStartLoc();
3683+
}
3684+
3685+
SourceLoc getEndLoc() const {
3686+
return ElementLoc;
3687+
}
3688+
3689+
static bool classof(const Expr *E) {
3690+
return E->getKind() == ExprKind::MaterializePack;
3691+
}
3692+
};
3693+
36533694
/// SequenceExpr - A list of binary operations which has not yet been
36543695
/// folded into a tree. The operands all have even indices, while the
36553696
/// 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
@@ -2524,6 +2524,12 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
25242524
PrintWithColorRAII(OS, ParenthesisColor) << ')';
25252525
}
25262526

2527+
void visitMaterializePackExpr(MaterializePackExpr *E) {
2528+
printCommon(E, "materialize_pack_expr") << "\n";
2529+
printRec(E->getFromExpr());
2530+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
2531+
}
2532+
25272533
void visitForceTryExpr(ForceTryExpr *E) {
25282534
printCommon(E, "force_try_expr");
25292535
OS << '\n';

lib/AST/ASTPrinter.cpp

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

4966+
void PrintAST::visitMaterializePackExpr(MaterializePackExpr *expr) {
4967+
visit(expr->getFromExpr());
4968+
Printer << ".element";
4969+
}
4970+
49664971
void PrintAST::visitPackElementExpr(PackElementExpr *expr) {
49674972
visit(expr->getPackRefExpr());
49684973
}

lib/AST/ASTWalker.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,14 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
878878
return nullptr;
879879
}
880880

881+
Expr *visitMaterializePackExpr(MaterializePackExpr *E) {
882+
if (Expr *fromExpr = doIt(E->getFromExpr())) {
883+
E->setFromExpr(fromExpr);
884+
return E;
885+
}
886+
return nullptr;
887+
}
888+
881889
Expr *visitSequenceExpr(SequenceExpr *E) {
882890
for (unsigned i = 0, e = E->getNumElements(); i != e; ++i)
883891
if (Expr *Elt = doIt(E->getElement(i)))

lib/AST/Expr.cpp

Lines changed: 11 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);
@@ -767,6 +768,7 @@ bool Expr::canAppendPostfixExpression(bool appendingPostfixOperator) const {
767768
case ExprKind::VarargExpansion:
768769
case ExprKind::PackExpansion:
769770
case ExprKind::PackElement:
771+
case ExprKind::MaterializePack:
770772
return false;
771773

772774
case ExprKind::Call:
@@ -951,6 +953,7 @@ bool Expr::isValidParentOfTypeExpr(Expr *typeExpr) const {
951953
case ExprKind::VarargExpansion:
952954
case ExprKind::PackExpansion:
953955
case ExprKind::PackElement:
956+
case ExprKind::MaterializePack:
954957
case ExprKind::DynamicType:
955958
case ExprKind::RebindSelfInConstructor:
956959
case ExprKind::OpaqueValue:
@@ -1322,6 +1325,14 @@ PackElementExpr::create(ASTContext &ctx, SourceLoc eachLoc, Expr *packRefExpr,
13221325
return new (ctx) PackElementExpr(eachLoc, packRefExpr, implicit, type);
13231326
}
13241327

1328+
MaterializePackExpr *
1329+
MaterializePackExpr::create(ASTContext &ctx, Expr *fromExpr,
1330+
SourceLoc elementLoc,
1331+
Type type, bool implicit) {
1332+
return new (ctx) MaterializePackExpr(fromExpr, elementLoc,
1333+
type, implicit);
1334+
}
1335+
13251336
SequenceExpr *SequenceExpr::create(ASTContext &ctx, ArrayRef<Expr*> elements) {
13261337
assert(elements.size() & 1 && "even number of elements in sequence");
13271338
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 = solution.getResolvedType(expr);
3419+
return cs.cacheType(
3420+
MaterializePackExpr::create(cs.getASTContext(),
3421+
base, expr->getEndLoc(),
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)