mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-31 23:38:45 +00:00
Add mir lower support for tuple destructing assignment
This commit is contained in:
parent
9b636e2326
commit
b96e4f2f4a
2 changed files with 65 additions and 0 deletions
|
@ -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]
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue