Add mir lower support for tuple destructing assignment

This commit is contained in:
hkalbasi 2023-08-07 02:12:35 +03:30
parent 9b636e2326
commit b96e4f2f4a
2 changed files with 65 additions and 0 deletions

View file

@ -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]

View file

@ -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 {