Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AST/Sema/SILGen: Implement tuple conversions #23591

Merged
merged 3 commits into from
Mar 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -815,13 +815,6 @@ ERROR(precedence_group_redeclared,none,
NOTE(previous_precedence_group_decl,none,
"previous precedence group declaration here", ())

//------------------------------------------------------------------------------
// MARK: Type Check Coercions
//------------------------------------------------------------------------------

ERROR(tuple_conversion_not_expressible,none,
"cannot express tuple conversion %0 to %1", (Type, Type))

//------------------------------------------------------------------------------
// MARK: Expression Type Checking Errors
//------------------------------------------------------------------------------
Expand Down
61 changes: 38 additions & 23 deletions include/swift/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,10 +290,9 @@ class alignas(8) Expr {

SWIFT_INLINE_BITFIELD_EMPTY(ImplicitConversionExpr, Expr);

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

SWIFT_INLINE_BITFIELD_FULL(ArgumentShuffleExpr, ImplicitConversionExpr, 2+16+16+16,
Expand Down Expand Up @@ -2960,37 +2959,53 @@ class UnevaluatedInstanceExpr : public ImplicitConversionExpr {
}
};

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

size_t numTrailingObjects(OverloadToken<unsigned>) const {
return Bits.TupleShuffleExpr.NumElementMappings;
size_t numTrailingObjects(OverloadToken<OpaqueValueExpr *>) const {
return Bits.DestructureTupleExpr.NumElements;
}

private:
TupleShuffleExpr(Expr *subExpr, ArrayRef<unsigned> elementMapping,
Type ty)
: ImplicitConversionExpr(ExprKind::TupleShuffle, subExpr, ty) {
Bits.TupleShuffleExpr.NumElementMappings = elementMapping.size();
std::uninitialized_copy(elementMapping.begin(), elementMapping.end(),
getTrailingObjects<unsigned>());
Expr *DstExpr;

DestructureTupleExpr(ArrayRef<OpaqueValueExpr *> destructuredElements,
Expr *srcExpr, Expr *dstExpr, Type ty)
: ImplicitConversionExpr(ExprKind::DestructureTuple, srcExpr, ty),
DstExpr(dstExpr) {
Bits.DestructureTupleExpr.NumElements = destructuredElements.size();
std::uninitialized_copy(destructuredElements.begin(),
destructuredElements.end(),
getTrailingObjects<OpaqueValueExpr *>());
}

public:
static TupleShuffleExpr *create(ASTContext &ctx, Expr *subExpr,
ArrayRef<unsigned> elementMapping,
Type ty);
/// Create a tuple destructuring. The type of srcExpr must be a tuple type,
/// and the number of elements must equal the size of destructureElements.
static DestructureTupleExpr *
create(ASTContext &ctx,
ArrayRef<OpaqueValueExpr *> destructuredElements,
Expr *srcExpr, Expr *dstExpr, Type ty);

ArrayRef<unsigned> getElementMapping() const {
return {getTrailingObjects<unsigned>(),
static_cast<size_t>(Bits.TupleShuffleExpr.NumElementMappings)};
ArrayRef<OpaqueValueExpr *> getDestructuredElements() const {
return {getTrailingObjects<OpaqueValueExpr *>(),
static_cast<size_t>(Bits.DestructureTupleExpr.NumElements)};
}

Expr *getResultExpr() const {
return DstExpr;
}

void setResultExpr(Expr *dstExpr) {
DstExpr = dstExpr;
}

static bool classof(const Expr *E) {
return E->getKind() == ExprKind::TupleShuffle;
return E->getKind() == ExprKind::DestructureTuple;
}
};

Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/ExprNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ ABSTRACT_EXPR(Apply, Expr)
EXPR_RANGE(Apply, Call, ConstructorRefCall)
ABSTRACT_EXPR(ImplicitConversion, Expr)
EXPR(Load, ImplicitConversionExpr)
EXPR(TupleShuffle, ImplicitConversionExpr)
EXPR(DestructureTuple, ImplicitConversionExpr)
EXPR(ArgumentShuffle, ImplicitConversionExpr)
EXPR(UnresolvedTypeConversion, ImplicitConversionExpr)
EXPR(FunctionConversion, ImplicitConversionExpr)
Expand Down
19 changes: 12 additions & 7 deletions lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2138,15 +2138,20 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
printRec(E->getBase());
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}
void visitTupleShuffleExpr(TupleShuffleExpr *E) {
printCommon(E, "tuple_shuffle_expr");
OS << " elements=[";
for (unsigned i = 0, e = E->getElementMapping().size(); i != e; ++i) {
if (i) OS << ", ";
OS << E->getElementMapping()[i];
void visitDestructureTupleExpr(DestructureTupleExpr *E) {
printCommon(E, "destructure_tuple_expr");
OS << " destructured=";
PrintWithColorRAII(OS, ParenthesisColor) << '(';
Indent += 2;
for (auto *elt : E->getDestructuredElements()) {
OS << "\n";
printRec(elt);
}
OS << "]\n";
Indent -= 2;
PrintWithColorRAII(OS, ParenthesisColor) << ")\n";
printRec(E->getSubExpr());
OS << "\n";
printRec(E->getResultExpr());
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}
void visitArgumentShuffleExpr(ArgumentShuffleExpr *E) {
Expand Down
48 changes: 38 additions & 10 deletions lib/AST/ASTVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,26 @@ class Verifier : public ASTWalker {
OpaqueValues.erase(expr->getOpaqueValue());
}

// Register the OVEs in a DestructureTupleExpr.
bool shouldVerify(DestructureTupleExpr *expr) {
if (!shouldVerify(cast<Expr>(expr)))
return false;

for (auto *opaqueElt : expr->getDestructuredElements()) {
assert(!OpaqueValues.count(opaqueElt));
OpaqueValues[opaqueElt] = 0;
}

return true;
}

void cleanup(DestructureTupleExpr *expr) {
for (auto *opaqueElt : expr->getDestructuredElements()) {
assert(OpaqueValues.count(opaqueElt));
OpaqueValues.erase(opaqueElt);
}
}

// Keep a stack of the currently-live optional evaluations.
bool shouldVerify(OptionalEvaluationExpr *expr) {
if (!shouldVerify(cast<Expr>(expr)))
Expand Down Expand Up @@ -1988,27 +2008,35 @@ class Verifier : public ASTWalker {
verifyCheckedBase(E);
}

void verifyChecked(TupleShuffleExpr *E) {
PrettyStackTraceExpr debugStack(Ctx, "verifying TupleShuffleExpr", E);
void verifyChecked(DestructureTupleExpr *E) {
PrettyStackTraceExpr debugStack(Ctx, "verifying DestructureTupleExpr", E);

auto getSubElementType = [&](unsigned i) {
auto getInputElementType = [&](unsigned i) {
return (E->getSubExpr()->getType()->castTo<TupleType>()
->getElementType(i));
};

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

for (unsigned i = 0, e = E->getElementMapping().size(); i != e; ++i) {
int subElem = E->getElementMapping()[i];
if (!getOuterElementType(i)->isEqual(getSubElementType(subElem))) {
Out << "Type mismatch in TupleShuffleExpr\n";
for (unsigned i = 0, e = E->getDestructuredElements().size(); i != e; ++i) {
Type inputType = getInputElementType(i);
Type opaqueType = getOpaqueElementType(i);
if (!inputType->isEqual(opaqueType)) {
Out << "Input type mismatch in DestructureTupleExpr\n";
inputType->dump(Out);
opaqueType->dump(Out);
abort();
}
}

if (!E->getResultExpr()->getType()->isEqual(E->getType())) {
Out << "Result type mismatch in DestructureTupleExpr\n";
E->getResultExpr()->getType()->dump(Out);
E->getType()->dump(Out);
}

verifyCheckedBase(E);
}

Expand Down
14 changes: 10 additions & 4 deletions lib/AST/ASTWalker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
// Note that semantic components will generally preserve the
// syntactic order of their children because doing something else
// could illegally change order of evaluation. This is why, for
// example, shuffling a TupleExpr creates a TupleShuffleExpr
// example, shuffling a TupleExpr creates a DestructureTupleExpr
// instead of just making a new TupleExpr with the elements in
// different order.
//
Expand Down Expand Up @@ -639,9 +639,15 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
return E;
}

Expr *visitTupleShuffleExpr(TupleShuffleExpr *E) {
if (Expr *E2 = doIt(E->getSubExpr())) {
E->setSubExpr(E2);
Expr *visitDestructureTupleExpr(DestructureTupleExpr *E) {
if (auto *src = doIt(E->getSubExpr())) {
E->setSubExpr(src);
} else {
return nullptr;
}

if (auto *dst = doIt(E->getResultExpr())) {
E->setResultExpr(dst);
} else {
return nullptr;
}
Expand Down
19 changes: 10 additions & 9 deletions lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ ConcreteDeclRef Expr::getReferencedDecl() const {

PASS_THROUGH_REFERENCE(ConstructorRefCall, getFn);
PASS_THROUGH_REFERENCE(Load, getSubExpr);
NO_REFERENCE(TupleShuffle);
NO_REFERENCE(DestructureTuple);
NO_REFERENCE(ArgumentShuffle);
NO_REFERENCE(UnresolvedTypeConversion);
PASS_THROUGH_REFERENCE(FunctionConversion, getSubExpr);
Expand Down Expand Up @@ -637,7 +637,7 @@ bool Expr::canAppendPostfixExpression(bool appendingPostfixOperator) const {
return false;

case ExprKind::Load:
case ExprKind::TupleShuffle:
case ExprKind::DestructureTuple:
case ExprKind::ArgumentShuffle:
case ExprKind::UnresolvedTypeConversion:
case ExprKind::FunctionConversion:
Expand Down Expand Up @@ -1333,13 +1333,14 @@ CaptureListExpr *CaptureListExpr::create(ASTContext &ctx,
return ::new(mem) CaptureListExpr(captureList, closureBody);
}

TupleShuffleExpr *TupleShuffleExpr::create(ASTContext &ctx,
Expr *subExpr,
ArrayRef<unsigned> elementMapping,
Type ty) {
auto size = totalSizeToAlloc<unsigned>(elementMapping.size());
auto mem = ctx.Allocate(size, alignof(TupleShuffleExpr));
return ::new(mem) TupleShuffleExpr(subExpr, elementMapping, ty);
DestructureTupleExpr *
DestructureTupleExpr::create(ASTContext &ctx,
ArrayRef<OpaqueValueExpr *> destructuredElements,
Expr *srcExpr, Expr *dstExpr, Type ty) {
auto size = totalSizeToAlloc<OpaqueValueExpr *>(destructuredElements.size());
auto mem = ctx.Allocate(size, alignof(DestructureTupleExpr));
return ::new(mem) DestructureTupleExpr(destructuredElements,
srcExpr, dstExpr, ty);
}

ArgumentShuffleExpr *ArgumentShuffleExpr::create(ASTContext &ctx,
Expand Down
6 changes: 3 additions & 3 deletions lib/SILGen/SILGenBridging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -703,11 +703,11 @@ static ManagedValue emitNativeToCBridgedNonoptionalValue(SILGenFunction &SGF,

FormalEvaluationScope scope(SGF);

auto openedExistential = SGF.emitOpenExistential(
loc, v, openedType, SGF.getLoweredType(openedType),
v = SGF.emitOpenExistential(
loc, v, SGF.getLoweredType(openedType),
AccessKind::Read);
v = v.ensurePlusOne(SGF, loc);

v = SGF.manageOpaqueValue(openedExistential, loc, SGFContext());
nativeType = openedType;
}

Expand Down
Loading