Skip to content

Commit 33eac80

Browse files
committed
Change destructuring assignment lowering to use match.
Previously, `(a, b) = t` produced code like `{ let (lhs1, lhs2) = t; a = lhs1; b = lhs2; }`, with this commit instead we produce `match t { (lhs1, lhs2) => { a = lhs1; b = lhs2; } }`. The desired effect is to make sure that temporaries in the expression `t` aren't dropped too early, in order to get better consistency between the behavior of e.g. `x = t` vs. `[x] = [t]` or `(x,) = (t,)` (where `t` is an arbitrary expression).
1 parent d201c81 commit 33eac80

File tree

1 file changed

+11
-16
lines changed
  • compiler/rustc_ast_lowering/src

1 file changed

+11
-16
lines changed

compiler/rustc_ast_lowering/src/expr.rs

+11-16
Original file line numberDiff line numberDiff line change
@@ -938,7 +938,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
938938
}
939939

940940
/// Destructure the LHS of complex assignments.
941-
/// For instance, lower `(a, b) = t` to `{ let (lhs1, lhs2) = t; a = lhs1; b = lhs2; }`.
941+
/// For instance, lower `(a, b) = t` to `match t { (lhs1, lhs2) => { a = lhs1; b = lhs2; } }`.
942942
fn lower_expr_assign(
943943
&mut self,
944944
lhs: &Expr,
@@ -979,22 +979,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
979979
let pat = self.destructure_assign(lhs, eq_sign_span, &mut assignments);
980980
let rhs = self.lower_expr(rhs);
981981

982-
// Introduce a `let` for destructuring: `let (lhs1, lhs2) = t`.
983-
let destructure_let = self.stmt_let_pat(
984-
None,
985-
whole_span,
986-
Some(rhs),
987-
pat,
988-
hir::LocalSource::AssignDesugar(self.lower_span(eq_sign_span)),
989-
);
982+
// Block of statements for the assignments: `{ a = lhs1; b = lhs2; }`.
983+
let stmts = self.arena.alloc_from_iter(assignments);
984+
let block = self.block_all(whole_span, stmts, None);
985+
let assignments_block = self.arena.alloc(self.expr_block(block, ThinVec::new()));
990986

991-
// `a = lhs1; b = lhs2;`.
992-
let stmts = self
993-
.arena
994-
.alloc_from_iter(std::iter::once(destructure_let).chain(assignments.into_iter()));
995-
996-
// Wrap everything in a block.
997-
hir::ExprKind::Block(&self.block_all(whole_span, stmts, None), None)
987+
// Produce the `match` for destructuring: `match t { (lhs1, lhs2) => ... }
988+
hir::ExprKind::Match(
989+
rhs,
990+
arena_vec![self; self.arm(pat, assignments_block)],
991+
hir::MatchSource::Normal, // FIXME: is `Normal` fine here?
992+
)
998993
}
999994

1000995
/// If the given expression is a path to a tuple struct, returns that path.

0 commit comments

Comments
 (0)