Skip to content

Commit 181e5d5

Browse files
authored
Merge pull request #23591 from slavapestov/tuple-conversions
AST/Sema/SILGen: Implement tuple conversions
2 parents 18da170 + e2c9c52 commit 181e5d5

21 files changed

+354
-507
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -815,13 +815,6 @@ ERROR(precedence_group_redeclared,none,
815815
NOTE(previous_precedence_group_decl,none,
816816
"previous precedence group declaration here", ())
817817

818-
//------------------------------------------------------------------------------
819-
// MARK: Type Check Coercions
820-
//------------------------------------------------------------------------------
821-
822-
ERROR(tuple_conversion_not_expressible,none,
823-
"cannot express tuple conversion %0 to %1", (Type, Type))
824-
825818
//------------------------------------------------------------------------------
826819
// MARK: Expression Type Checking Errors
827820
//------------------------------------------------------------------------------

include/swift/AST/Expr.h

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -290,10 +290,9 @@ class alignas(8) Expr {
290290

291291
SWIFT_INLINE_BITFIELD_EMPTY(ImplicitConversionExpr, Expr);
292292

293-
SWIFT_INLINE_BITFIELD_FULL(TupleShuffleExpr, ImplicitConversionExpr, 16,
294-
/// This contains an entry for each element in the Expr type. Each element
295-
/// specifies which index from the SubExpr that the destination element gets.
296-
NumElementMappings : 16
293+
SWIFT_INLINE_BITFIELD_FULL(DestructureTupleExpr, ImplicitConversionExpr, 16,
294+
/// The number of elements in the tuple type being destructured.
295+
NumElements : 16
297296
);
298297

299298
SWIFT_INLINE_BITFIELD_FULL(ArgumentShuffleExpr, ImplicitConversionExpr, 2+16+16+16,
@@ -2960,37 +2959,53 @@ class UnevaluatedInstanceExpr : public ImplicitConversionExpr {
29602959
}
29612960
};
29622961

2963-
/// TupleShuffleExpr - This represents a permutation of a tuple value to a new
2964-
/// tuple type.
2965-
class TupleShuffleExpr final : public ImplicitConversionExpr,
2966-
private llvm::TrailingObjects<TupleShuffleExpr, unsigned> {
2962+
/// DestructureTupleExpr - Destructure a tuple value produced by a source
2963+
/// expression, binding the elements to OpaqueValueExprs, then evaluate the
2964+
/// result expression written in terms of the OpaqueValueExprs.
2965+
class DestructureTupleExpr final : public ImplicitConversionExpr,
2966+
private llvm::TrailingObjects<DestructureTupleExpr, OpaqueValueExpr *> {
29672967
friend TrailingObjects;
29682968

2969-
size_t numTrailingObjects(OverloadToken<unsigned>) const {
2970-
return Bits.TupleShuffleExpr.NumElementMappings;
2969+
size_t numTrailingObjects(OverloadToken<OpaqueValueExpr *>) const {
2970+
return Bits.DestructureTupleExpr.NumElements;
29712971
}
29722972

29732973
private:
2974-
TupleShuffleExpr(Expr *subExpr, ArrayRef<unsigned> elementMapping,
2975-
Type ty)
2976-
: ImplicitConversionExpr(ExprKind::TupleShuffle, subExpr, ty) {
2977-
Bits.TupleShuffleExpr.NumElementMappings = elementMapping.size();
2978-
std::uninitialized_copy(elementMapping.begin(), elementMapping.end(),
2979-
getTrailingObjects<unsigned>());
2974+
Expr *DstExpr;
2975+
2976+
DestructureTupleExpr(ArrayRef<OpaqueValueExpr *> destructuredElements,
2977+
Expr *srcExpr, Expr *dstExpr, Type ty)
2978+
: ImplicitConversionExpr(ExprKind::DestructureTuple, srcExpr, ty),
2979+
DstExpr(dstExpr) {
2980+
Bits.DestructureTupleExpr.NumElements = destructuredElements.size();
2981+
std::uninitialized_copy(destructuredElements.begin(),
2982+
destructuredElements.end(),
2983+
getTrailingObjects<OpaqueValueExpr *>());
29802984
}
29812985

29822986
public:
2983-
static TupleShuffleExpr *create(ASTContext &ctx, Expr *subExpr,
2984-
ArrayRef<unsigned> elementMapping,
2985-
Type ty);
2987+
/// Create a tuple destructuring. The type of srcExpr must be a tuple type,
2988+
/// and the number of elements must equal the size of destructureElements.
2989+
static DestructureTupleExpr *
2990+
create(ASTContext &ctx,
2991+
ArrayRef<OpaqueValueExpr *> destructuredElements,
2992+
Expr *srcExpr, Expr *dstExpr, Type ty);
29862993

2987-
ArrayRef<unsigned> getElementMapping() const {
2988-
return {getTrailingObjects<unsigned>(),
2989-
static_cast<size_t>(Bits.TupleShuffleExpr.NumElementMappings)};
2994+
ArrayRef<OpaqueValueExpr *> getDestructuredElements() const {
2995+
return {getTrailingObjects<OpaqueValueExpr *>(),
2996+
static_cast<size_t>(Bits.DestructureTupleExpr.NumElements)};
2997+
}
2998+
2999+
Expr *getResultExpr() const {
3000+
return DstExpr;
3001+
}
3002+
3003+
void setResultExpr(Expr *dstExpr) {
3004+
DstExpr = dstExpr;
29903005
}
29913006

29923007
static bool classof(const Expr *E) {
2993-
return E->getKind() == ExprKind::TupleShuffle;
3008+
return E->getKind() == ExprKind::DestructureTuple;
29943009
}
29953010
};
29963011

include/swift/AST/ExprNodes.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ ABSTRACT_EXPR(Apply, Expr)
143143
EXPR_RANGE(Apply, Call, ConstructorRefCall)
144144
ABSTRACT_EXPR(ImplicitConversion, Expr)
145145
EXPR(Load, ImplicitConversionExpr)
146-
EXPR(TupleShuffle, ImplicitConversionExpr)
146+
EXPR(DestructureTuple, ImplicitConversionExpr)
147147
EXPR(ArgumentShuffle, ImplicitConversionExpr)
148148
EXPR(UnresolvedTypeConversion, ImplicitConversionExpr)
149149
EXPR(FunctionConversion, ImplicitConversionExpr)

lib/AST/ASTDumper.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2138,15 +2138,20 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
21382138
printRec(E->getBase());
21392139
PrintWithColorRAII(OS, ParenthesisColor) << ')';
21402140
}
2141-
void visitTupleShuffleExpr(TupleShuffleExpr *E) {
2142-
printCommon(E, "tuple_shuffle_expr");
2143-
OS << " elements=[";
2144-
for (unsigned i = 0, e = E->getElementMapping().size(); i != e; ++i) {
2145-
if (i) OS << ", ";
2146-
OS << E->getElementMapping()[i];
2141+
void visitDestructureTupleExpr(DestructureTupleExpr *E) {
2142+
printCommon(E, "destructure_tuple_expr");
2143+
OS << " destructured=";
2144+
PrintWithColorRAII(OS, ParenthesisColor) << '(';
2145+
Indent += 2;
2146+
for (auto *elt : E->getDestructuredElements()) {
2147+
OS << "\n";
2148+
printRec(elt);
21472149
}
2148-
OS << "]\n";
2150+
Indent -= 2;
2151+
PrintWithColorRAII(OS, ParenthesisColor) << ")\n";
21492152
printRec(E->getSubExpr());
2153+
OS << "\n";
2154+
printRec(E->getResultExpr());
21502155
PrintWithColorRAII(OS, ParenthesisColor) << ')';
21512156
}
21522157
void visitArgumentShuffleExpr(ArgumentShuffleExpr *E) {

lib/AST/ASTVerifier.cpp

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,26 @@ class Verifier : public ASTWalker {
820820
OpaqueValues.erase(expr->getOpaqueValue());
821821
}
822822

823+
// Register the OVEs in a DestructureTupleExpr.
824+
bool shouldVerify(DestructureTupleExpr *expr) {
825+
if (!shouldVerify(cast<Expr>(expr)))
826+
return false;
827+
828+
for (auto *opaqueElt : expr->getDestructuredElements()) {
829+
assert(!OpaqueValues.count(opaqueElt));
830+
OpaqueValues[opaqueElt] = 0;
831+
}
832+
833+
return true;
834+
}
835+
836+
void cleanup(DestructureTupleExpr *expr) {
837+
for (auto *opaqueElt : expr->getDestructuredElements()) {
838+
assert(OpaqueValues.count(opaqueElt));
839+
OpaqueValues.erase(opaqueElt);
840+
}
841+
}
842+
823843
// Keep a stack of the currently-live optional evaluations.
824844
bool shouldVerify(OptionalEvaluationExpr *expr) {
825845
if (!shouldVerify(cast<Expr>(expr)))
@@ -1988,27 +2008,35 @@ class Verifier : public ASTWalker {
19882008
verifyCheckedBase(E);
19892009
}
19902010

1991-
void verifyChecked(TupleShuffleExpr *E) {
1992-
PrettyStackTraceExpr debugStack(Ctx, "verifying TupleShuffleExpr", E);
2011+
void verifyChecked(DestructureTupleExpr *E) {
2012+
PrettyStackTraceExpr debugStack(Ctx, "verifying DestructureTupleExpr", E);
19932013

1994-
auto getSubElementType = [&](unsigned i) {
2014+
auto getInputElementType = [&](unsigned i) {
19952015
return (E->getSubExpr()->getType()->castTo<TupleType>()
19962016
->getElementType(i));
19972017
};
19982018

1999-
/// Retrieve the ith element type from the resulting tuple type.
2000-
auto getOuterElementType = [&](unsigned i) -> Type {
2001-
return E->getType()->castTo<TupleType>()->getElementType(i);
2019+
auto getOpaqueElementType = [&](unsigned i) -> Type {
2020+
return E->getDestructuredElements()[i]->getType();
20022021
};
20032022

2004-
for (unsigned i = 0, e = E->getElementMapping().size(); i != e; ++i) {
2005-
int subElem = E->getElementMapping()[i];
2006-
if (!getOuterElementType(i)->isEqual(getSubElementType(subElem))) {
2007-
Out << "Type mismatch in TupleShuffleExpr\n";
2023+
for (unsigned i = 0, e = E->getDestructuredElements().size(); i != e; ++i) {
2024+
Type inputType = getInputElementType(i);
2025+
Type opaqueType = getOpaqueElementType(i);
2026+
if (!inputType->isEqual(opaqueType)) {
2027+
Out << "Input type mismatch in DestructureTupleExpr\n";
2028+
inputType->dump(Out);
2029+
opaqueType->dump(Out);
20082030
abort();
20092031
}
20102032
}
20112033

2034+
if (!E->getResultExpr()->getType()->isEqual(E->getType())) {
2035+
Out << "Result type mismatch in DestructureTupleExpr\n";
2036+
E->getResultExpr()->getType()->dump(Out);
2037+
E->getType()->dump(Out);
2038+
}
2039+
20122040
verifyCheckedBase(E);
20132041
}
20142042

lib/AST/ASTWalker.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
// Note that semantic components will generally preserve the
3838
// syntactic order of their children because doing something else
3939
// could illegally change order of evaluation. This is why, for
40-
// example, shuffling a TupleExpr creates a TupleShuffleExpr
40+
// example, shuffling a TupleExpr creates a DestructureTupleExpr
4141
// instead of just making a new TupleExpr with the elements in
4242
// different order.
4343
//
@@ -639,9 +639,15 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
639639
return E;
640640
}
641641

642-
Expr *visitTupleShuffleExpr(TupleShuffleExpr *E) {
643-
if (Expr *E2 = doIt(E->getSubExpr())) {
644-
E->setSubExpr(E2);
642+
Expr *visitDestructureTupleExpr(DestructureTupleExpr *E) {
643+
if (auto *src = doIt(E->getSubExpr())) {
644+
E->setSubExpr(src);
645+
} else {
646+
return nullptr;
647+
}
648+
649+
if (auto *dst = doIt(E->getResultExpr())) {
650+
E->setResultExpr(dst);
645651
} else {
646652
return nullptr;
647653
}

lib/AST/Expr.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ ConcreteDeclRef Expr::getReferencedDecl() const {
322322

323323
PASS_THROUGH_REFERENCE(ConstructorRefCall, getFn);
324324
PASS_THROUGH_REFERENCE(Load, getSubExpr);
325-
NO_REFERENCE(TupleShuffle);
325+
NO_REFERENCE(DestructureTuple);
326326
NO_REFERENCE(ArgumentShuffle);
327327
NO_REFERENCE(UnresolvedTypeConversion);
328328
PASS_THROUGH_REFERENCE(FunctionConversion, getSubExpr);
@@ -637,7 +637,7 @@ bool Expr::canAppendPostfixExpression(bool appendingPostfixOperator) const {
637637
return false;
638638

639639
case ExprKind::Load:
640-
case ExprKind::TupleShuffle:
640+
case ExprKind::DestructureTuple:
641641
case ExprKind::ArgumentShuffle:
642642
case ExprKind::UnresolvedTypeConversion:
643643
case ExprKind::FunctionConversion:
@@ -1333,13 +1333,14 @@ CaptureListExpr *CaptureListExpr::create(ASTContext &ctx,
13331333
return ::new(mem) CaptureListExpr(captureList, closureBody);
13341334
}
13351335

1336-
TupleShuffleExpr *TupleShuffleExpr::create(ASTContext &ctx,
1337-
Expr *subExpr,
1338-
ArrayRef<unsigned> elementMapping,
1339-
Type ty) {
1340-
auto size = totalSizeToAlloc<unsigned>(elementMapping.size());
1341-
auto mem = ctx.Allocate(size, alignof(TupleShuffleExpr));
1342-
return ::new(mem) TupleShuffleExpr(subExpr, elementMapping, ty);
1336+
DestructureTupleExpr *
1337+
DestructureTupleExpr::create(ASTContext &ctx,
1338+
ArrayRef<OpaqueValueExpr *> destructuredElements,
1339+
Expr *srcExpr, Expr *dstExpr, Type ty) {
1340+
auto size = totalSizeToAlloc<OpaqueValueExpr *>(destructuredElements.size());
1341+
auto mem = ctx.Allocate(size, alignof(DestructureTupleExpr));
1342+
return ::new(mem) DestructureTupleExpr(destructuredElements,
1343+
srcExpr, dstExpr, ty);
13431344
}
13441345

13451346
ArgumentShuffleExpr *ArgumentShuffleExpr::create(ASTContext &ctx,

lib/SILGen/SILGenBridging.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -703,11 +703,11 @@ static ManagedValue emitNativeToCBridgedNonoptionalValue(SILGenFunction &SGF,
703703

704704
FormalEvaluationScope scope(SGF);
705705

706-
auto openedExistential = SGF.emitOpenExistential(
707-
loc, v, openedType, SGF.getLoweredType(openedType),
706+
v = SGF.emitOpenExistential(
707+
loc, v, SGF.getLoweredType(openedType),
708708
AccessKind::Read);
709+
v = v.ensurePlusOne(SGF, loc);
709710

710-
v = SGF.manageOpaqueValue(openedExistential, loc, SGFContext());
711711
nativeType = openedType;
712712
}
713713

0 commit comments

Comments
 (0)