Skip to content

Commit e5c7451

Browse files
authored
Rollup merge of #138017 - nnethercote:tighten-assignment-op, r=spastorino
Tighten up assignment operator representations. This is step 3 of [MCP 831](rust-lang/compiler-team#831). r? `@spastorino`
2 parents 82eb03e + ddcb370 commit e5c7451

File tree

29 files changed

+470
-313
lines changed

29 files changed

+470
-313
lines changed

compiler/rustc_ast/src/ast.rs

+70-1
Original file line numberDiff line numberDiff line change
@@ -981,6 +981,75 @@ impl BinOpKind {
981981

982982
pub type BinOp = Spanned<BinOpKind>;
983983

984+
// Sometimes `BinOpKind` and `AssignOpKind` need the same treatment. The
985+
// operations covered by `AssignOpKind` are a subset of those covered by
986+
// `BinOpKind`, so it makes sense to convert `AssignOpKind` to `BinOpKind`.
987+
impl From<AssignOpKind> for BinOpKind {
988+
fn from(op: AssignOpKind) -> BinOpKind {
989+
match op {
990+
AssignOpKind::AddAssign => BinOpKind::Add,
991+
AssignOpKind::SubAssign => BinOpKind::Sub,
992+
AssignOpKind::MulAssign => BinOpKind::Mul,
993+
AssignOpKind::DivAssign => BinOpKind::Div,
994+
AssignOpKind::RemAssign => BinOpKind::Rem,
995+
AssignOpKind::BitXorAssign => BinOpKind::BitXor,
996+
AssignOpKind::BitAndAssign => BinOpKind::BitAnd,
997+
AssignOpKind::BitOrAssign => BinOpKind::BitOr,
998+
AssignOpKind::ShlAssign => BinOpKind::Shl,
999+
AssignOpKind::ShrAssign => BinOpKind::Shr,
1000+
}
1001+
}
1002+
}
1003+
1004+
#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)]
1005+
pub enum AssignOpKind {
1006+
/// The `+=` operator (addition)
1007+
AddAssign,
1008+
/// The `-=` operator (subtraction)
1009+
SubAssign,
1010+
/// The `*=` operator (multiplication)
1011+
MulAssign,
1012+
/// The `/=` operator (division)
1013+
DivAssign,
1014+
/// The `%=` operator (modulus)
1015+
RemAssign,
1016+
/// The `^=` operator (bitwise xor)
1017+
BitXorAssign,
1018+
/// The `&=` operator (bitwise and)
1019+
BitAndAssign,
1020+
/// The `|=` operator (bitwise or)
1021+
BitOrAssign,
1022+
/// The `<<=` operator (shift left)
1023+
ShlAssign,
1024+
/// The `>>=` operator (shift right)
1025+
ShrAssign,
1026+
}
1027+
1028+
impl AssignOpKind {
1029+
pub fn as_str(&self) -> &'static str {
1030+
use AssignOpKind::*;
1031+
match self {
1032+
AddAssign => "+=",
1033+
SubAssign => "-=",
1034+
MulAssign => "*=",
1035+
DivAssign => "/=",
1036+
RemAssign => "%=",
1037+
BitXorAssign => "^=",
1038+
BitAndAssign => "&=",
1039+
BitOrAssign => "|=",
1040+
ShlAssign => "<<=",
1041+
ShrAssign => ">>=",
1042+
}
1043+
}
1044+
1045+
/// AssignOps are always by value.
1046+
pub fn is_by_value(self) -> bool {
1047+
true
1048+
}
1049+
}
1050+
1051+
pub type AssignOp = Spanned<AssignOpKind>;
1052+
9841053
/// Unary operator.
9851054
///
9861055
/// Note that `&data` is not an operator, it's an `AddrOf` expression.
@@ -1593,7 +1662,7 @@ pub enum ExprKind {
15931662
/// An assignment with an operator.
15941663
///
15951664
/// E.g., `a += 1`.
1596-
AssignOp(BinOp, P<Expr>, P<Expr>),
1665+
AssignOp(AssignOp, P<Expr>, P<Expr>),
15971666
/// Access of a named (e.g., `obj.foo`) or unnamed (e.g., `obj.0`) struct field.
15981667
Field(P<Expr>, Ident),
15991668
/// An indexing operation (e.g., `foo[2]`).

compiler/rustc_ast/src/util/parser.rs

+12-12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use rustc_span::kw;
22

3-
use crate::ast::{self, BinOpKind, RangeLimits};
3+
use crate::ast::{self, AssignOpKind, BinOpKind, RangeLimits};
44
use crate::token::{self, Token};
55

66
/// Associative operator.
@@ -9,7 +9,7 @@ pub enum AssocOp {
99
/// A binary op.
1010
Binary(BinOpKind),
1111
/// `?=` where ? is one of the assignable BinOps
12-
AssignOp(BinOpKind),
12+
AssignOp(AssignOpKind),
1313
/// `=`
1414
Assign,
1515
/// `as`
@@ -44,16 +44,16 @@ impl AssocOp {
4444
token::Or => Some(Binary(BinOpKind::BitOr)),
4545
token::Shl => Some(Binary(BinOpKind::Shl)),
4646
token::Shr => Some(Binary(BinOpKind::Shr)),
47-
token::PlusEq => Some(AssignOp(BinOpKind::Add)),
48-
token::MinusEq => Some(AssignOp(BinOpKind::Sub)),
49-
token::StarEq => Some(AssignOp(BinOpKind::Mul)),
50-
token::SlashEq => Some(AssignOp(BinOpKind::Div)),
51-
token::PercentEq => Some(AssignOp(BinOpKind::Rem)),
52-
token::CaretEq => Some(AssignOp(BinOpKind::BitXor)),
53-
token::AndEq => Some(AssignOp(BinOpKind::BitAnd)),
54-
token::OrEq => Some(AssignOp(BinOpKind::BitOr)),
55-
token::ShlEq => Some(AssignOp(BinOpKind::Shl)),
56-
token::ShrEq => Some(AssignOp(BinOpKind::Shr)),
47+
token::PlusEq => Some(AssignOp(AssignOpKind::AddAssign)),
48+
token::MinusEq => Some(AssignOp(AssignOpKind::SubAssign)),
49+
token::StarEq => Some(AssignOp(AssignOpKind::MulAssign)),
50+
token::SlashEq => Some(AssignOp(AssignOpKind::DivAssign)),
51+
token::PercentEq => Some(AssignOp(AssignOpKind::RemAssign)),
52+
token::CaretEq => Some(AssignOp(AssignOpKind::BitXorAssign)),
53+
token::AndEq => Some(AssignOp(AssignOpKind::BitAndAssign)),
54+
token::OrEq => Some(AssignOp(AssignOpKind::BitOrAssign)),
55+
token::ShlEq => Some(AssignOp(AssignOpKind::ShlAssign)),
56+
token::ShrEq => Some(AssignOp(AssignOpKind::ShrAssign)),
5757
token::Lt => Some(Binary(BinOpKind::Lt)),
5858
token::Le => Some(Binary(BinOpKind::Le)),
5959
token::Ge => Some(Binary(BinOpKind::Ge)),

compiler/rustc_ast_lowering/src/expr.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
274274
}
275275
ExprKind::Assign(el, er, span) => self.lower_expr_assign(el, er, *span, e.span),
276276
ExprKind::AssignOp(op, el, er) => hir::ExprKind::AssignOp(
277-
self.lower_binop(*op),
277+
self.lower_assign_op(*op),
278278
self.lower_expr(el),
279279
self.lower_expr(er),
280280
),
@@ -443,6 +443,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
443443
Spanned { node: b.node, span: self.lower_span(b.span) }
444444
}
445445

446+
fn lower_assign_op(&mut self, a: AssignOp) -> AssignOp {
447+
Spanned { node: a.node, span: self.lower_span(a.span) }
448+
}
449+
446450
fn lower_legacy_const_generics(
447451
&mut self,
448452
mut f: Expr,

compiler/rustc_ast_pretty/src/pprust/state/expr.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -274,22 +274,22 @@ impl<'a> State<'a> {
274274

275275
fn print_expr_binary(
276276
&mut self,
277-
op: ast::BinOp,
277+
op: ast::BinOpKind,
278278
lhs: &ast::Expr,
279279
rhs: &ast::Expr,
280280
fixup: FixupContext,
281281
) {
282-
let binop_prec = op.node.precedence();
282+
let binop_prec = op.precedence();
283283
let left_prec = lhs.precedence();
284284
let right_prec = rhs.precedence();
285285

286-
let (mut left_needs_paren, right_needs_paren) = match op.node.fixity() {
286+
let (mut left_needs_paren, right_needs_paren) = match op.fixity() {
287287
Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec),
288288
Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec),
289289
Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec),
290290
};
291291

292-
match (&lhs.kind, op.node) {
292+
match (&lhs.kind, op) {
293293
// These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is
294294
// the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead
295295
// of `(x as i32) < ...`. We need to convince it _not_ to do that.
@@ -312,7 +312,7 @@ impl<'a> State<'a> {
312312

313313
self.print_expr_cond_paren(lhs, left_needs_paren, fixup.leftmost_subexpression());
314314
self.space();
315-
self.word_space(op.node.as_str());
315+
self.word_space(op.as_str());
316316
self.print_expr_cond_paren(rhs, right_needs_paren, fixup.subsequent_subexpression());
317317
}
318318

@@ -410,7 +410,7 @@ impl<'a> State<'a> {
410410
self.print_expr_method_call(seg, receiver, args, fixup);
411411
}
412412
ast::ExprKind::Binary(op, lhs, rhs) => {
413-
self.print_expr_binary(*op, lhs, rhs, fixup);
413+
self.print_expr_binary(op.node, lhs, rhs, fixup);
414414
}
415415
ast::ExprKind::Unary(op, expr) => {
416416
self.print_expr_unary(*op, expr, fixup);
@@ -605,8 +605,7 @@ impl<'a> State<'a> {
605605
fixup.leftmost_subexpression(),
606606
);
607607
self.space();
608-
self.word(op.node.as_str());
609-
self.word_space("=");
608+
self.word_space(op.node.as_str());
610609
self.print_expr_cond_paren(
611610
rhs,
612611
rhs.precedence() < ExprPrecedence::Assign,

compiler/rustc_hir/src/hir.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ use rustc_ast::{
1010
LitKind, TraitObjectSyntax, UintTy, UnsafeBinderCastKind,
1111
};
1212
pub use rustc_ast::{
13-
AttrId, AttrStyle, BinOp, BinOpKind, BindingMode, BorrowKind, BoundConstness, BoundPolarity,
14-
ByRef, CaptureBy, DelimArgs, ImplPolarity, IsAuto, MetaItemInner, MetaItemLit, Movability,
15-
Mutability, UnOp,
13+
AssignOp, AssignOpKind, AttrId, AttrStyle, BinOp, BinOpKind, BindingMode, BorrowKind,
14+
BoundConstness, BoundPolarity, ByRef, CaptureBy, DelimArgs, ImplPolarity, IsAuto,
15+
MetaItemInner, MetaItemLit, Movability, Mutability, UnOp,
1616
};
1717
use rustc_attr_data_structures::AttributeKind;
1818
use rustc_data_structures::fingerprint::Fingerprint;
@@ -2648,7 +2648,7 @@ pub enum ExprKind<'hir> {
26482648
/// An assignment with an operator.
26492649
///
26502650
/// E.g., `a += 1`.
2651-
AssignOp(BinOp, &'hir Expr<'hir>, &'hir Expr<'hir>),
2651+
AssignOp(AssignOp, &'hir Expr<'hir>, &'hir Expr<'hir>),
26522652
/// Access of a named (e.g., `obj.foo`) or unnamed (e.g., `obj.0`) struct or tuple field.
26532653
Field(&'hir Expr<'hir>, Ident),
26542654
/// An indexing operation (`foo[2]`).

compiler/rustc_hir_pretty/src/lib.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -1271,18 +1271,18 @@ impl<'a> State<'a> {
12711271
self.print_call_post(base_args)
12721272
}
12731273

1274-
fn print_expr_binary(&mut self, op: hir::BinOp, lhs: &hir::Expr<'_>, rhs: &hir::Expr<'_>) {
1275-
let binop_prec = op.node.precedence();
1274+
fn print_expr_binary(&mut self, op: hir::BinOpKind, lhs: &hir::Expr<'_>, rhs: &hir::Expr<'_>) {
1275+
let binop_prec = op.precedence();
12761276
let left_prec = lhs.precedence();
12771277
let right_prec = rhs.precedence();
12781278

1279-
let (mut left_needs_paren, right_needs_paren) = match op.node.fixity() {
1279+
let (mut left_needs_paren, right_needs_paren) = match op.fixity() {
12801280
Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec),
12811281
Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec),
12821282
Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec),
12831283
};
12841284

1285-
match (&lhs.kind, op.node) {
1285+
match (&lhs.kind, op) {
12861286
// These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is
12871287
// the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead
12881288
// of `(x as i32) < ...`. We need to convince it _not_ to do that.
@@ -1297,7 +1297,7 @@ impl<'a> State<'a> {
12971297

12981298
self.print_expr_cond_paren(lhs, left_needs_paren);
12991299
self.space();
1300-
self.word_space(op.node.as_str());
1300+
self.word_space(op.as_str());
13011301
self.print_expr_cond_paren(rhs, right_needs_paren);
13021302
}
13031303

@@ -1451,7 +1451,7 @@ impl<'a> State<'a> {
14511451
self.word(".use");
14521452
}
14531453
hir::ExprKind::Binary(op, lhs, rhs) => {
1454-
self.print_expr_binary(op, lhs, rhs);
1454+
self.print_expr_binary(op.node, lhs, rhs);
14551455
}
14561456
hir::ExprKind::Unary(op, expr) => {
14571457
self.print_expr_unary(op, expr);
@@ -1572,8 +1572,7 @@ impl<'a> State<'a> {
15721572
hir::ExprKind::AssignOp(op, lhs, rhs) => {
15731573
self.print_expr_cond_paren(lhs, lhs.precedence() <= ExprPrecedence::Assign);
15741574
self.space();
1575-
self.word(op.node.as_str());
1576-
self.word_space("=");
1575+
self.word_space(op.node.as_str());
15771576
self.print_expr_cond_paren(rhs, rhs.precedence() < ExprPrecedence::Assign);
15781577
}
15791578
hir::ExprKind::Field(expr, ident) => {

compiler/rustc_hir_typeck/src/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
512512
self.check_expr_assign(expr, expected, lhs, rhs, span)
513513
}
514514
ExprKind::AssignOp(op, lhs, rhs) => {
515-
self.check_expr_binop_assign(expr, op, lhs, rhs, expected)
515+
self.check_expr_assign_op(expr, op, lhs, rhs, expected)
516516
}
517517
ExprKind::Unary(unop, oprnd) => self.check_expr_unop(unop, oprnd, expected, expr),
518518
ExprKind::AddrOf(kind, mutbl, oprnd) => {

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

+16-22
Original file line numberDiff line numberDiff line change
@@ -3477,30 +3477,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
34773477
lhs_ty: Ty<'tcx>,
34783478
rhs_expr: &'tcx hir::Expr<'tcx>,
34793479
lhs_expr: &'tcx hir::Expr<'tcx>,
3480-
op: hir::BinOp,
34813480
) {
3482-
match op.node {
3483-
hir::BinOpKind::Eq => {
3484-
if let Some(partial_eq_def_id) = self.infcx.tcx.lang_items().eq_trait()
3485-
&& self
3486-
.infcx
3487-
.type_implements_trait(partial_eq_def_id, [rhs_ty, lhs_ty], self.param_env)
3488-
.must_apply_modulo_regions()
3489-
{
3490-
let sm = self.tcx.sess.source_map();
3491-
if let Ok(rhs_snippet) = sm.span_to_snippet(rhs_expr.span)
3492-
&& let Ok(lhs_snippet) = sm.span_to_snippet(lhs_expr.span)
3493-
{
3494-
err.note(format!("`{rhs_ty}` implements `PartialEq<{lhs_ty}>`"));
3495-
err.multipart_suggestion(
3496-
"consider swapping the equality",
3497-
vec![(lhs_expr.span, rhs_snippet), (rhs_expr.span, lhs_snippet)],
3498-
Applicability::MaybeIncorrect,
3499-
);
3500-
}
3501-
}
3481+
if let Some(partial_eq_def_id) = self.infcx.tcx.lang_items().eq_trait()
3482+
&& self
3483+
.infcx
3484+
.type_implements_trait(partial_eq_def_id, [rhs_ty, lhs_ty], self.param_env)
3485+
.must_apply_modulo_regions()
3486+
{
3487+
let sm = self.tcx.sess.source_map();
3488+
if let Ok(rhs_snippet) = sm.span_to_snippet(rhs_expr.span)
3489+
&& let Ok(lhs_snippet) = sm.span_to_snippet(lhs_expr.span)
3490+
{
3491+
err.note(format!("`{rhs_ty}` implements `PartialEq<{lhs_ty}>`"));
3492+
err.multipart_suggestion(
3493+
"consider swapping the equality",
3494+
vec![(lhs_expr.span, rhs_snippet), (rhs_expr.span, lhs_snippet)],
3495+
Applicability::MaybeIncorrect,
3496+
);
35023497
}
3503-
_ => {}
35043498
}
35053499
}
35063500
}

0 commit comments

Comments
 (0)