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
|
@ -1668,6 +1668,42 @@ pub enum BinOp {
|
|||
Offset,
|
||||
}
|
||||
|
||||
// Assignment operators, e.g. `+=`. See comments on the corresponding variants
|
||||
// in `BinOp` for details.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
|
||||
pub enum AssignOp {
|
||||
AddAssign,
|
||||
SubAssign,
|
||||
MulAssign,
|
||||
DivAssign,
|
||||
RemAssign,
|
||||
BitXorAssign,
|
||||
BitAndAssign,
|
||||
BitOrAssign,
|
||||
ShlAssign,
|
||||
ShrAssign,
|
||||
}
|
||||
|
||||
// Sometimes `BinOp` and `AssignOp` need the same treatment. The operations
|
||||
// covered by `AssignOp` are a subset of those covered by `BinOp`, so it makes
|
||||
// sense to convert `AssignOp` to `BinOp`.
|
||||
impl From<AssignOp> for BinOp {
|
||||
fn from(op: AssignOp) -> BinOp {
|
||||
match op {
|
||||
AssignOp::AddAssign => BinOp::Add,
|
||||
AssignOp::SubAssign => BinOp::Sub,
|
||||
AssignOp::MulAssign => BinOp::Mul,
|
||||
AssignOp::DivAssign => BinOp::Div,
|
||||
AssignOp::RemAssign => BinOp::Rem,
|
||||
AssignOp::BitXorAssign => BinOp::BitXor,
|
||||
AssignOp::BitAndAssign => BinOp::BitAnd,
|
||||
AssignOp::BitOrAssign => BinOp::BitOr,
|
||||
AssignOp::ShlAssign => BinOp::Shl,
|
||||
AssignOp::ShrAssign => BinOp::Shr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
mod size_asserts {
|
||||
|
|
|
@ -27,7 +27,7 @@ use tracing::instrument;
|
|||
|
||||
use crate::middle::region;
|
||||
use crate::mir::interpret::AllocId;
|
||||
use crate::mir::{self, BinOp, BorrowKind, FakeReadCause, UnOp};
|
||||
use crate::mir::{self, AssignOp, BinOp, BorrowKind, FakeReadCause, UnOp};
|
||||
use crate::thir::visit::for_each_immediate_subpat;
|
||||
use crate::ty::adjustment::PointerCoercion;
|
||||
use crate::ty::layout::IntegerExt;
|
||||
|
@ -403,7 +403,7 @@ pub enum ExprKind<'tcx> {
|
|||
},
|
||||
/// A *non-overloaded* operation assignment, e.g. `lhs += rhs`.
|
||||
AssignOp {
|
||||
op: BinOp,
|
||||
op: AssignOp,
|
||||
lhs: ExprId,
|
||||
rhs: ExprId,
|
||||
},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue