Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-ty/src/consteval/tests.rs21
-rw-r--r--crates/hir-ty/src/mir/lower.rs44
2 files changed, 65 insertions, 0 deletions
diff --git a/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs
index 666955fa1c..666a7e81e3 100644
--- a/crates/hir-ty/src/consteval/tests.rs
+++ b/crates/hir-ty/src/consteval/tests.rs
@@ -1203,6 +1203,27 @@ fn destructing_assignment() {
"#,
5,
);
+ check_number(
+ r#"
+ const GOAL: u8 = {
+ let (mut a, mut b) = (2, 5);
+ (a, b) = (b, a);
+ a * 10 + b
+ };
+ "#,
+ 52,
+ );
+ check_number(
+ r#"
+ struct Point { x: i32, y: i32 }
+ const GOAL: i32 = {
+ let mut p = Point { x: 5, y: 6 };
+ (p.x, _) = (p.y, p.x);
+ p.x * 10 + p.y
+ };
+ "#,
+ 66,
+ );
}
#[test]
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index 718df8331e..9eaa9e1c2f 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -1244,6 +1244,41 @@ impl<'ctx> MirLowerCtx<'ctx> {
}
}
+ fn lower_destructing_assignment(
+ &mut self,
+ mut current: BasicBlockId,
+ lhs: ExprId,
+ rhs: Place,
+ span: MirSpan,
+ ) -> Result<Option<BasicBlockId>> {
+ match &self.body.exprs[lhs] {
+ Expr::Tuple { exprs, is_assignee_expr: _ } => {
+ for (i, expr) in exprs.iter().enumerate() {
+ let Some(c) = self.lower_destructing_assignment(
+ current,
+ *expr,
+ rhs.project(ProjectionElem::TupleOrClosureField(i)),
+ span,
+ )? else {
+ return Ok(None);
+ };
+ current = c;
+ }
+ Ok(Some(current))
+ }
+ Expr::Underscore => Ok(Some(current)),
+ _ => {
+ let Some((lhs_place, current)) =
+ self.lower_expr_as_place(current, lhs, false)?
+ else {
+ return Ok(None);
+ };
+ self.push_assignment(current, lhs_place, Operand::Copy(rhs).into(), span);
+ Ok(Some(current))
+ }
+ }
+ }
+
fn lower_assignment(
&mut self,
current: BasicBlockId,
@@ -1259,6 +1294,15 @@ impl<'ctx> MirLowerCtx<'ctx> {
if matches!(&self.body.exprs[lhs], Expr::Underscore) {
return Ok(Some(current));
}
+ if matches!(
+ &self.body.exprs[lhs],
+ Expr::Tuple { .. } | Expr::RecordLit { .. } | Expr::Call { .. }
+ ) {
+ let temp = self.temp(self.expr_ty_after_adjustments(rhs), current, rhs.into())?;
+ let temp = Place::from(temp);
+ self.push_assignment(current, temp.clone(), rhs_op.into(), span);
+ return self.lower_destructing_assignment(current, lhs, temp, span);
+ }
let Some((lhs_place, current)) =
self.lower_expr_as_place(current, lhs, false)?
else {