Tighten up assignment operator representations.
In the AST, currently we use `BinOpKind` within `ExprKind::AssignOp` and `AssocOp::AssignOp`, even though this allows some nonsensical combinations. E.g. there is no `&&=` operator. Likewise for HIR and THIR. This commit introduces `AssignOpKind` which only includes the ten assignable operators, and uses it in `ExprKind::AssignOp` and `AssocOp::AssignOp`. (And does similar things for `hir::ExprKind` and `thir::ExprKind`.) This avoids the possibility of nonsensical combinations, as seen by the removal of the `bug!` case in `lang_item_for_binop`. The commit is mostly plumbing, including: - Adds an `impl From<AssignOpKind> for BinOpKind` (AST) and `impl From<AssignOp> for BinOp` (MIR/THIR). - `BinOpCategory` can now be created from both `BinOpKind` and `AssignOpKind`. - Replaces the `IsAssign` type with `Op`, which has more information and a few methods. - `suggest_swapping_lhs_and_rhs`: moves the condition to the call site, it's easier that way. - `check_expr_inner`: had to factor out some code into a separate method. I'm on the fence about whether avoiding the nonsensical combinations is worth the extra code.
This commit is contained in:
parent
ac8ccf09b4
commit
ddcb370bc6
26 changed files with 391 additions and 239 deletions
|
@ -78,8 +78,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
// because AssignOp is only legal for Copy types
|
||||
// (overloaded ops should be desugared into a call).
|
||||
let result = unpack!(
|
||||
block =
|
||||
this.build_binary_op(block, op, expr_span, lhs_ty, Operand::Copy(lhs), rhs)
|
||||
block = this.build_binary_op(
|
||||
block,
|
||||
op.into(),
|
||||
expr_span,
|
||||
lhs_ty,
|
||||
Operand::Copy(lhs),
|
||||
rhs
|
||||
)
|
||||
);
|
||||
this.cfg.push_assign(block, source_info, lhs, result);
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ use rustc_middle::hir::place::{
|
|||
Place as HirPlace, PlaceBase as HirPlaceBase, ProjectionKind as HirProjectionKind,
|
||||
};
|
||||
use rustc_middle::middle::region;
|
||||
use rustc_middle::mir::{self, BinOp, BorrowKind, UnOp};
|
||||
use rustc_middle::mir::{self, AssignOp, BinOp, BorrowKind, UnOp};
|
||||
use rustc_middle::thir::*;
|
||||
use rustc_middle::ty::adjustment::{
|
||||
Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, PointerCoercion,
|
||||
|
@ -489,7 +489,7 @@ impl<'tcx> ThirBuildCx<'tcx> {
|
|||
self.overloaded_operator(expr, Box::new([lhs, rhs]))
|
||||
} else {
|
||||
ExprKind::AssignOp {
|
||||
op: bin_op(op.node),
|
||||
op: assign_op(op.node),
|
||||
lhs: self.mirror_expr(lhs),
|
||||
rhs: self.mirror_expr(rhs),
|
||||
}
|
||||
|
@ -1347,3 +1347,18 @@ fn bin_op(op: hir::BinOpKind) -> BinOp {
|
|||
_ => bug!("no equivalent for ast binop {:?}", op),
|
||||
}
|
||||
}
|
||||
|
||||
fn assign_op(op: hir::AssignOpKind) -> AssignOp {
|
||||
match op {
|
||||
hir::AssignOpKind::AddAssign => AssignOp::AddAssign,
|
||||
hir::AssignOpKind::SubAssign => AssignOp::SubAssign,
|
||||
hir::AssignOpKind::MulAssign => AssignOp::MulAssign,
|
||||
hir::AssignOpKind::DivAssign => AssignOp::DivAssign,
|
||||
hir::AssignOpKind::RemAssign => AssignOp::RemAssign,
|
||||
hir::AssignOpKind::BitXorAssign => AssignOp::BitXorAssign,
|
||||
hir::AssignOpKind::BitAndAssign => AssignOp::BitAndAssign,
|
||||
hir::AssignOpKind::BitOrAssign => AssignOp::BitOrAssign,
|
||||
hir::AssignOpKind::ShlAssign => AssignOp::ShlAssign,
|
||||
hir::AssignOpKind::ShrAssign => AssignOp::ShrAssign,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue