Use BinOpKind instead of BinOp for function args where possible.

Because it's nice to avoid passing in unnecessary data.
This commit is contained in:
Nicholas Nethercote 2024-12-20 08:33:43 +11:00
parent 076cccd412
commit ac8ccf09b4
7 changed files with 77 additions and 78 deletions

View File

@ -274,22 +274,22 @@ impl<'a> State<'a> {
fn print_expr_binary( fn print_expr_binary(
&mut self, &mut self,
op: ast::BinOp, op: ast::BinOpKind,
lhs: &ast::Expr, lhs: &ast::Expr,
rhs: &ast::Expr, rhs: &ast::Expr,
fixup: FixupContext, fixup: FixupContext,
) { ) {
let binop_prec = op.node.precedence(); let binop_prec = op.precedence();
let left_prec = lhs.precedence(); let left_prec = lhs.precedence();
let right_prec = rhs.precedence(); let right_prec = rhs.precedence();
let (mut left_needs_paren, right_needs_paren) = match op.node.fixity() { let (mut left_needs_paren, right_needs_paren) = match op.fixity() {
Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec), Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec),
Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec), Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec),
Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec), Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec),
}; };
match (&lhs.kind, op.node) { match (&lhs.kind, op) {
// These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is
// the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead
// of `(x as i32) < ...`. We need to convince it _not_ to do that. // of `(x as i32) < ...`. We need to convince it _not_ to do that.
@ -312,7 +312,7 @@ impl<'a> State<'a> {
self.print_expr_cond_paren(lhs, left_needs_paren, fixup.leftmost_subexpression()); self.print_expr_cond_paren(lhs, left_needs_paren, fixup.leftmost_subexpression());
self.space(); self.space();
self.word_space(op.node.as_str()); self.word_space(op.as_str());
self.print_expr_cond_paren(rhs, right_needs_paren, fixup.subsequent_subexpression()); self.print_expr_cond_paren(rhs, right_needs_paren, fixup.subsequent_subexpression());
} }
@ -410,7 +410,7 @@ impl<'a> State<'a> {
self.print_expr_method_call(seg, receiver, args, fixup); self.print_expr_method_call(seg, receiver, args, fixup);
} }
ast::ExprKind::Binary(op, lhs, rhs) => { ast::ExprKind::Binary(op, lhs, rhs) => {
self.print_expr_binary(*op, lhs, rhs, fixup); self.print_expr_binary(op.node, lhs, rhs, fixup);
} }
ast::ExprKind::Unary(op, expr) => { ast::ExprKind::Unary(op, expr) => {
self.print_expr_unary(*op, expr, fixup); self.print_expr_unary(*op, expr, fixup);

View File

@ -1271,18 +1271,18 @@ impl<'a> State<'a> {
self.print_call_post(base_args) self.print_call_post(base_args)
} }
fn print_expr_binary(&mut self, op: hir::BinOp, lhs: &hir::Expr<'_>, rhs: &hir::Expr<'_>) { fn print_expr_binary(&mut self, op: hir::BinOpKind, lhs: &hir::Expr<'_>, rhs: &hir::Expr<'_>) {
let binop_prec = op.node.precedence(); let binop_prec = op.precedence();
let left_prec = lhs.precedence(); let left_prec = lhs.precedence();
let right_prec = rhs.precedence(); let right_prec = rhs.precedence();
let (mut left_needs_paren, right_needs_paren) = match op.node.fixity() { let (mut left_needs_paren, right_needs_paren) = match op.fixity() {
Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec), Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec),
Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec), Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec),
Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec), Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec),
}; };
match (&lhs.kind, op.node) { match (&lhs.kind, op) {
// These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is
// the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead
// of `(x as i32) < ...`. We need to convince it _not_ to do that. // of `(x as i32) < ...`. We need to convince it _not_ to do that.
@ -1297,7 +1297,7 @@ impl<'a> State<'a> {
self.print_expr_cond_paren(lhs, left_needs_paren); self.print_expr_cond_paren(lhs, left_needs_paren);
self.space(); self.space();
self.word_space(op.node.as_str()); self.word_space(op.as_str());
self.print_expr_cond_paren(rhs, right_needs_paren); self.print_expr_cond_paren(rhs, right_needs_paren);
} }
@ -1451,7 +1451,7 @@ impl<'a> State<'a> {
self.word(".use"); self.word(".use");
} }
hir::ExprKind::Binary(op, lhs, rhs) => { hir::ExprKind::Binary(op, lhs, rhs) => {
self.print_expr_binary(op, lhs, rhs); self.print_expr_binary(op.node, lhs, rhs);
} }
hir::ExprKind::Unary(op, expr) => { hir::ExprKind::Unary(op, expr) => {
self.print_expr_unary(op, expr); self.print_expr_unary(op, expr);

View File

@ -3477,9 +3477,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
lhs_ty: Ty<'tcx>, lhs_ty: Ty<'tcx>,
rhs_expr: &'tcx hir::Expr<'tcx>, rhs_expr: &'tcx hir::Expr<'tcx>,
lhs_expr: &'tcx hir::Expr<'tcx>, lhs_expr: &'tcx hir::Expr<'tcx>,
op: hir::BinOp, op: hir::BinOpKind,
) { ) {
match op.node { match op {
hir::BinOpKind::Eq => { hir::BinOpKind::Eq => {
if let Some(partial_eq_def_id) = self.infcx.tcx.lang_items().eq_trait() if let Some(partial_eq_def_id) = self.infcx.tcx.lang_items().eq_trait()
&& self && self

View File

@ -35,9 +35,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let (lhs_ty, rhs_ty, return_ty) = let (lhs_ty, rhs_ty, return_ty) =
self.check_overloaded_binop(expr, lhs, rhs, op, IsAssign::Yes, expected); self.check_overloaded_binop(expr, lhs, rhs, op, IsAssign::Yes, expected);
let ty = let ty = if !lhs_ty.is_ty_var()
if !lhs_ty.is_ty_var() && !rhs_ty.is_ty_var() && is_builtin_binop(lhs_ty, rhs_ty, op) { && !rhs_ty.is_ty_var()
self.enforce_builtin_binop_types(lhs.span, lhs_ty, rhs.span, rhs_ty, op); && is_builtin_binop(lhs_ty, rhs_ty, op.node)
{
self.enforce_builtin_binop_types(lhs.span, lhs_ty, rhs.span, rhs_ty, op.node);
self.tcx.types.unit self.tcx.types.unit
} else { } else {
return_ty return_ty
@ -49,7 +51,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.lookup_op_method( .lookup_op_method(
(lhs, lhs_deref_ty), (lhs, lhs_deref_ty),
Some((rhs, rhs_ty)), Some((rhs, rhs_ty)),
lang_item_for_binop(self.tcx, op, IsAssign::Yes), lang_item_for_binop(self.tcx, op.node, IsAssign::Yes),
op.span, op.span,
expected, expected,
) )
@ -61,7 +63,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.lookup_op_method( .lookup_op_method(
(lhs, lhs_ty), (lhs, lhs_ty),
Some((rhs, rhs_ty)), Some((rhs, rhs_ty)),
lang_item_for_binop(self.tcx, op, IsAssign::Yes), lang_item_for_binop(self.tcx, op.node, IsAssign::Yes),
op.span, op.span,
expected, expected,
) )
@ -100,7 +102,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr.hir_id, expr, op, lhs_expr, rhs_expr expr.hir_id, expr, op, lhs_expr, rhs_expr
); );
match BinOpCategory::from(op) { match BinOpCategory::from(op.node) {
BinOpCategory::Shortcircuit => { BinOpCategory::Shortcircuit => {
// && and || are a simple case. // && and || are a simple case.
self.check_expr_coercible_to_type(lhs_expr, tcx.types.bool, None); self.check_expr_coercible_to_type(lhs_expr, tcx.types.bool, None);
@ -139,14 +141,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// can't pin this down to a specific impl. // can't pin this down to a specific impl.
if !lhs_ty.is_ty_var() if !lhs_ty.is_ty_var()
&& !rhs_ty.is_ty_var() && !rhs_ty.is_ty_var()
&& is_builtin_binop(lhs_ty, rhs_ty, op) && is_builtin_binop(lhs_ty, rhs_ty, op.node)
{ {
let builtin_return_ty = self.enforce_builtin_binop_types( let builtin_return_ty = self.enforce_builtin_binop_types(
lhs_expr.span, lhs_expr.span,
lhs_ty, lhs_ty,
rhs_expr.span, rhs_expr.span,
rhs_ty, rhs_ty,
op, op.node,
); );
self.demand_eqtype(expr.span, builtin_return_ty, return_ty); self.demand_eqtype(expr.span, builtin_return_ty, return_ty);
builtin_return_ty builtin_return_ty
@ -163,7 +165,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
lhs_ty: Ty<'tcx>, lhs_ty: Ty<'tcx>,
rhs_span: Span, rhs_span: Span,
rhs_ty: Ty<'tcx>, rhs_ty: Ty<'tcx>,
op: hir::BinOp, op: hir::BinOpKind,
) -> Ty<'tcx> { ) -> Ty<'tcx> {
debug_assert!(is_builtin_binop(lhs_ty, rhs_ty, op)); debug_assert!(is_builtin_binop(lhs_ty, rhs_ty, op));
@ -244,7 +246,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let result = self.lookup_op_method( let result = self.lookup_op_method(
(lhs_expr, lhs_ty), (lhs_expr, lhs_ty),
Some((rhs_expr, rhs_ty_var)), Some((rhs_expr, rhs_ty_var)),
lang_item_for_binop(self.tcx, op, is_assign), lang_item_for_binop(self.tcx, op.node, is_assign),
op.span, op.span,
expected, expected,
); );
@ -255,7 +257,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
rhs_ty_var, rhs_ty_var,
Some(lhs_expr), Some(lhs_expr),
|err, ty| { |err, ty| {
self.suggest_swapping_lhs_and_rhs(err, ty, lhs_ty, rhs_expr, lhs_expr, op); self.suggest_swapping_lhs_and_rhs(err, ty, lhs_ty, rhs_expr, lhs_expr, op.node);
}, },
); );
let rhs_ty = self.resolve_vars_with_obligations(rhs_ty); let rhs_ty = self.resolve_vars_with_obligations(rhs_ty);
@ -304,7 +306,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Ty::new_misc_error(self.tcx) Ty::new_misc_error(self.tcx)
} }
Err(errors) => { Err(errors) => {
let (_, trait_def_id) = lang_item_for_binop(self.tcx, op, is_assign); let (_, trait_def_id) = lang_item_for_binop(self.tcx, op.node, is_assign);
let missing_trait = trait_def_id let missing_trait = trait_def_id
.map(|def_id| with_no_trimmed_paths!(self.tcx.def_path_str(def_id))); .map(|def_id| with_no_trimmed_paths!(self.tcx.def_path_str(def_id)));
let mut path = None; let mut path = None;
@ -411,7 +413,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.lookup_op_method( .lookup_op_method(
(lhs_expr, lhs_deref_ty), (lhs_expr, lhs_deref_ty),
Some((rhs_expr, rhs_ty)), Some((rhs_expr, rhs_ty)),
lang_item_for_binop(self.tcx, op, is_assign), lang_item_for_binop(self.tcx, op.node, is_assign),
op.span, op.span,
expected, expected,
) )
@ -445,7 +447,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.lookup_op_method( .lookup_op_method(
(lhs_expr, lhs_adjusted_ty), (lhs_expr, lhs_adjusted_ty),
Some((rhs_expr, rhs_adjusted_ty)), Some((rhs_expr, rhs_adjusted_ty)),
lang_item_for_binop(self.tcx, op, is_assign), lang_item_for_binop(self.tcx, op.node, is_assign),
op.span, op.span,
expected, expected,
) )
@ -503,7 +505,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.lookup_op_method( self.lookup_op_method(
(lhs_expr, lhs_ty), (lhs_expr, lhs_ty),
Some((rhs_expr, rhs_ty)), Some((rhs_expr, rhs_ty)),
lang_item_for_binop(self.tcx, op, is_assign), lang_item_for_binop(self.tcx, op.node, is_assign),
op.span, op.span,
expected, expected,
) )
@ -597,7 +599,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.lookup_op_method( .lookup_op_method(
(lhs_expr, lhs_ty), (lhs_expr, lhs_ty),
Some((rhs_expr, rhs_ty)), Some((rhs_expr, rhs_ty)),
lang_item_for_binop(self.tcx, op, is_assign), lang_item_for_binop(self.tcx, op.node, is_assign),
op.span, op.span,
expected, expected,
) )
@ -991,12 +993,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn lang_item_for_binop( fn lang_item_for_binop(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
op: hir::BinOp, op: hir::BinOpKind,
is_assign: IsAssign, is_assign: IsAssign,
) -> (Symbol, Option<hir::def_id::DefId>) { ) -> (Symbol, Option<hir::def_id::DefId>) {
let lang = tcx.lang_items(); let lang = tcx.lang_items();
if is_assign == IsAssign::Yes { if is_assign == IsAssign::Yes {
match op.node { match op {
hir::BinOpKind::Add => (sym::add_assign, lang.add_assign_trait()), hir::BinOpKind::Add => (sym::add_assign, lang.add_assign_trait()),
hir::BinOpKind::Sub => (sym::sub_assign, lang.sub_assign_trait()), hir::BinOpKind::Sub => (sym::sub_assign, lang.sub_assign_trait()),
hir::BinOpKind::Mul => (sym::mul_assign, lang.mul_assign_trait()), hir::BinOpKind::Mul => (sym::mul_assign, lang.mul_assign_trait()),
@ -1015,11 +1017,11 @@ fn lang_item_for_binop(
| hir::BinOpKind::Ne | hir::BinOpKind::Ne
| hir::BinOpKind::And | hir::BinOpKind::And
| hir::BinOpKind::Or => { | hir::BinOpKind::Or => {
bug!("impossible assignment operation: {}=", op.node.as_str()) bug!("impossible assignment operation: {}=", op.as_str())
} }
} }
} else { } else {
match op.node { match op {
hir::BinOpKind::Add => (sym::add, lang.add_trait()), hir::BinOpKind::Add => (sym::add, lang.add_trait()),
hir::BinOpKind::Sub => (sym::sub, lang.sub_trait()), hir::BinOpKind::Sub => (sym::sub, lang.sub_trait()),
hir::BinOpKind::Mul => (sym::mul, lang.mul_trait()), hir::BinOpKind::Mul => (sym::mul, lang.mul_trait()),
@ -1076,8 +1078,8 @@ enum BinOpCategory {
} }
impl BinOpCategory { impl BinOpCategory {
fn from(op: hir::BinOp) -> BinOpCategory { fn from(op: hir::BinOpKind) -> BinOpCategory {
match op.node { match op {
hir::BinOpKind::Shl | hir::BinOpKind::Shr => BinOpCategory::Shift, hir::BinOpKind::Shl | hir::BinOpKind::Shr => BinOpCategory::Shift,
hir::BinOpKind::Add hir::BinOpKind::Add
@ -1133,7 +1135,7 @@ fn deref_ty_if_possible(ty: Ty<'_>) -> Ty<'_> {
/// Reason #2 is the killer. I tried for a while to always use /// Reason #2 is the killer. I tried for a while to always use
/// overloaded logic and just check the types in constants/codegen after /// overloaded logic and just check the types in constants/codegen after
/// the fact, and it worked fine, except for SIMD types. -nmatsakis /// the fact, and it worked fine, except for SIMD types. -nmatsakis
fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>, rhs: Ty<'tcx>, op: hir::BinOp) -> bool { fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>, rhs: Ty<'tcx>, op: hir::BinOpKind) -> bool {
// Special-case a single layer of referencing, so that things like `5.0 + &6.0f32` work. // Special-case a single layer of referencing, so that things like `5.0 + &6.0f32` work.
// (See https://github.com/rust-lang/rust/issues/57447.) // (See https://github.com/rust-lang/rust/issues/57447.)
let (lhs, rhs) = (deref_ty_if_possible(lhs), deref_ty_if_possible(rhs)); let (lhs, rhs) = (deref_ty_if_possible(lhs), deref_ty_if_possible(rhs));

View File

@ -14,7 +14,7 @@ use rustc_middle::ty::{
}; };
use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass}; use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass};
use rustc_span::def_id::LocalDefId; use rustc_span::def_id::LocalDefId;
use rustc_span::{Span, Symbol, source_map, sym}; use rustc_span::{Span, Symbol, sym};
use tracing::debug; use tracing::debug;
use {rustc_ast as ast, rustc_hir as hir}; use {rustc_ast as ast, rustc_hir as hir};
@ -223,7 +223,7 @@ impl TypeLimits {
fn lint_nan<'tcx>( fn lint_nan<'tcx>(
cx: &LateContext<'tcx>, cx: &LateContext<'tcx>,
e: &'tcx hir::Expr<'tcx>, e: &'tcx hir::Expr<'tcx>,
binop: hir::BinOp, binop: hir::BinOpKind,
l: &'tcx hir::Expr<'tcx>, l: &'tcx hir::Expr<'tcx>,
r: &'tcx hir::Expr<'tcx>, r: &'tcx hir::Expr<'tcx>,
) { ) {
@ -262,19 +262,19 @@ fn lint_nan<'tcx>(
InvalidNanComparisons::EqNe { suggestion } InvalidNanComparisons::EqNe { suggestion }
} }
let lint = match binop.node { let lint = match binop {
hir::BinOpKind::Eq | hir::BinOpKind::Ne if is_nan(cx, l) => { hir::BinOpKind::Eq | hir::BinOpKind::Ne if is_nan(cx, l) => {
eq_ne(e, l, r, |l_span, r_span| InvalidNanComparisonsSuggestion::Spanful { eq_ne(e, l, r, |l_span, r_span| InvalidNanComparisonsSuggestion::Spanful {
nan_plus_binop: l_span.until(r_span), nan_plus_binop: l_span.until(r_span),
float: r_span.shrink_to_hi(), float: r_span.shrink_to_hi(),
neg: (binop.node == hir::BinOpKind::Ne).then(|| r_span.shrink_to_lo()), neg: (binop == hir::BinOpKind::Ne).then(|| r_span.shrink_to_lo()),
}) })
} }
hir::BinOpKind::Eq | hir::BinOpKind::Ne if is_nan(cx, r) => { hir::BinOpKind::Eq | hir::BinOpKind::Ne if is_nan(cx, r) => {
eq_ne(e, l, r, |l_span, r_span| InvalidNanComparisonsSuggestion::Spanful { eq_ne(e, l, r, |l_span, r_span| InvalidNanComparisonsSuggestion::Spanful {
nan_plus_binop: l_span.shrink_to_hi().to(r_span), nan_plus_binop: l_span.shrink_to_hi().to(r_span),
float: l_span.shrink_to_hi(), float: l_span.shrink_to_hi(),
neg: (binop.node == hir::BinOpKind::Ne).then(|| l_span.shrink_to_lo()), neg: (binop == hir::BinOpKind::Ne).then(|| l_span.shrink_to_lo()),
}) })
} }
hir::BinOpKind::Lt | hir::BinOpKind::Le | hir::BinOpKind::Gt | hir::BinOpKind::Ge hir::BinOpKind::Lt | hir::BinOpKind::Le | hir::BinOpKind::Gt | hir::BinOpKind::Ge
@ -560,11 +560,11 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
} }
} }
hir::ExprKind::Binary(binop, ref l, ref r) => { hir::ExprKind::Binary(binop, ref l, ref r) => {
if is_comparison(binop) { if is_comparison(binop.node) {
if !check_limits(cx, binop, l, r) { if !check_limits(cx, binop.node, l, r) {
cx.emit_span_lint(UNUSED_COMPARISONS, e.span, UnusedComparisons); cx.emit_span_lint(UNUSED_COMPARISONS, e.span, UnusedComparisons);
} else { } else {
lint_nan(cx, e, binop, l, r); lint_nan(cx, e, binop.node, l, r);
let cmpop = ComparisonOp::BinOp(binop.node); let cmpop = ComparisonOp::BinOp(binop.node);
lint_wide_pointer(cx, e, cmpop, l, r); lint_wide_pointer(cx, e, cmpop, l, r);
lint_fn_pointer(cx, e, cmpop, l, r); lint_fn_pointer(cx, e, cmpop, l, r);
@ -591,8 +591,8 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
_ => {} _ => {}
}; };
fn is_valid<T: PartialOrd>(binop: hir::BinOp, v: T, min: T, max: T) -> bool { fn is_valid<T: PartialOrd>(binop: hir::BinOpKind, v: T, min: T, max: T) -> bool {
match binop.node { match binop {
hir::BinOpKind::Lt => v > min && v <= max, hir::BinOpKind::Lt => v > min && v <= max,
hir::BinOpKind::Le => v >= min && v < max, hir::BinOpKind::Le => v >= min && v < max,
hir::BinOpKind::Gt => v >= min && v < max, hir::BinOpKind::Gt => v >= min && v < max,
@ -602,22 +602,19 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
} }
} }
fn rev_binop(binop: hir::BinOp) -> hir::BinOp { fn rev_binop(binop: hir::BinOpKind) -> hir::BinOpKind {
source_map::respan( match binop {
binop.span,
match binop.node {
hir::BinOpKind::Lt => hir::BinOpKind::Gt, hir::BinOpKind::Lt => hir::BinOpKind::Gt,
hir::BinOpKind::Le => hir::BinOpKind::Ge, hir::BinOpKind::Le => hir::BinOpKind::Ge,
hir::BinOpKind::Gt => hir::BinOpKind::Lt, hir::BinOpKind::Gt => hir::BinOpKind::Lt,
hir::BinOpKind::Ge => hir::BinOpKind::Le, hir::BinOpKind::Ge => hir::BinOpKind::Le,
_ => return binop, _ => binop,
}, }
)
} }
fn check_limits( fn check_limits(
cx: &LateContext<'_>, cx: &LateContext<'_>,
binop: hir::BinOp, binop: hir::BinOpKind,
l: &hir::Expr<'_>, l: &hir::Expr<'_>,
r: &hir::Expr<'_>, r: &hir::Expr<'_>,
) -> bool { ) -> bool {
@ -659,9 +656,9 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
} }
} }
fn is_comparison(binop: hir::BinOp) -> bool { fn is_comparison(binop: hir::BinOpKind) -> bool {
matches!( matches!(
binop.node, binop,
hir::BinOpKind::Eq hir::BinOpKind::Eq
| hir::BinOpKind::Lt | hir::BinOpKind::Lt
| hir::BinOpKind::Le | hir::BinOpKind::Le

View File

@ -10,7 +10,7 @@ use rustc_ast::{LitKind, RangeLimits};
use rustc_data_structures::packed::Pu128; use rustc_data_structures::packed::Pu128;
use rustc_data_structures::unhash::UnindexMap; use rustc_data_structures::unhash::UnindexMap;
use rustc_errors::{Applicability, Diag}; use rustc_errors::{Applicability, Diag};
use rustc_hir::{BinOp, Block, Body, Expr, ExprKind, UnOp}; use rustc_hir::{BinOpKind, Block, Body, Expr, ExprKind, UnOp};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass; use rustc_session::declare_lint_pass;
use rustc_span::source_map::Spanned; use rustc_span::source_map::Spanned;
@ -97,7 +97,7 @@ enum LengthComparison {
/// ///
/// E.g. for `v.len() > 5` this returns `Some((LengthComparison::IntLessThanLength, 5, v.len()))` /// E.g. for `v.len() > 5` this returns `Some((LengthComparison::IntLessThanLength, 5, v.len()))`
fn len_comparison<'hir>( fn len_comparison<'hir>(
bin_op: BinOp, bin_op: BinOpKind,
left: &'hir Expr<'hir>, left: &'hir Expr<'hir>,
right: &'hir Expr<'hir>, right: &'hir Expr<'hir>,
) -> Option<(LengthComparison, usize, &'hir Expr<'hir>)> { ) -> Option<(LengthComparison, usize, &'hir Expr<'hir>)> {
@ -112,7 +112,7 @@ fn len_comparison<'hir>(
// normalize comparison, `v.len() > 4` becomes `4 < v.len()` // normalize comparison, `v.len() > 4` becomes `4 < v.len()`
// this simplifies the logic a bit // this simplifies the logic a bit
let (op, left, right) = normalize_comparison(bin_op.node, left, right)?; let (op, left, right) = normalize_comparison(bin_op, left, right)?;
match (op, left.kind, right.kind) { match (op, left.kind, right.kind) {
(Rel::Lt, int_lit_pat!(left), _) => Some((LengthComparison::IntLessThanLength, left as usize, right)), (Rel::Lt, int_lit_pat!(left), _) => Some((LengthComparison::IntLessThanLength, left as usize, right)),
(Rel::Lt, _, int_lit_pat!(right)) => Some((LengthComparison::LengthLessThanInt, right as usize, left)), (Rel::Lt, _, int_lit_pat!(right)) => Some((LengthComparison::LengthLessThanInt, right as usize, left)),
@ -138,7 +138,7 @@ fn assert_len_expr<'hir>(
&& let ExprKind::Unary(UnOp::Not, condition) = &cond.kind && let ExprKind::Unary(UnOp::Not, condition) = &cond.kind
&& let ExprKind::Binary(bin_op, left, right) = &condition.kind && let ExprKind::Binary(bin_op, left, right) = &condition.kind
&& let Some((cmp, asserted_len, slice_len)) = len_comparison(*bin_op, left, right) && let Some((cmp, asserted_len, slice_len)) = len_comparison(bin_op.node, left, right)
&& let ExprKind::MethodCall(method, recv, [], _) = &slice_len.kind && let ExprKind::MethodCall(method, recv, [], _) = &slice_len.kind
&& cx.typeck_results().expr_ty_adjusted(recv).peel_refs().is_slice() && cx.typeck_results().expr_ty_adjusted(recv).peel_refs().is_slice()
&& method.ident.name == sym::len && method.ident.name == sym::len

View File

@ -15,7 +15,7 @@ use rustc_apfloat::ieee::{Half, Quad};
use rustc_ast::ast::{self, LitFloatType, LitKind}; use rustc_ast::ast::{self, LitFloatType, LitKind};
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::{ use rustc_hir::{
BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, PatExpr, PatExprKind, QPath, UnOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, PatExpr, PatExprKind, QPath, UnOp,
}; };
use rustc_lexer::tokenize; use rustc_lexer::tokenize;
use rustc_lint::LateContext; use rustc_lint::LateContext;
@ -506,7 +506,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
UnOp::Deref => Some(if let Constant::Ref(r) = o { *r } else { o }), UnOp::Deref => Some(if let Constant::Ref(r) = o { *r } else { o }),
}), }),
ExprKind::If(cond, then, ref otherwise) => self.ifthenelse(cond, then, *otherwise), ExprKind::If(cond, then, ref otherwise) => self.ifthenelse(cond, then, *otherwise),
ExprKind::Binary(op, left, right) => self.binop(op, left, right), ExprKind::Binary(op, left, right) => self.binop(op.node, left, right),
ExprKind::Call(callee, []) => { ExprKind::Call(callee, []) => {
// We only handle a few const functions for now. // We only handle a few const functions for now.
if let ExprKind::Path(qpath) = &callee.kind if let ExprKind::Path(qpath) = &callee.kind
@ -744,7 +744,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
} }
} }
fn binop(&self, op: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> Option<Constant<'tcx>> { fn binop(&self, op: BinOpKind, left: &Expr<'_>, right: &Expr<'_>) -> Option<Constant<'tcx>> {
let l = self.expr(left)?; let l = self.expr(left)?;
let r = self.expr(right); let r = self.expr(right);
match (l, r) { match (l, r) {
@ -757,7 +757,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
// Using / or %, where the left-hand argument is the smallest integer of a signed integer type and // Using / or %, where the left-hand argument is the smallest integer of a signed integer type and
// the right-hand argument is -1 always panics, even with overflow-checks disabled // the right-hand argument is -1 always panics, even with overflow-checks disabled
if let BinOpKind::Div | BinOpKind::Rem = op.node if let BinOpKind::Div | BinOpKind::Rem = op
&& l == ty_min_value && l == ty_min_value
&& r == -1 && r == -1
{ {
@ -765,7 +765,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
} }
let zext = |n: i128| Constant::Int(unsext(self.tcx, n, ity)); let zext = |n: i128| Constant::Int(unsext(self.tcx, n, ity));
match op.node { match op {
// When +, * or binary - create a value greater than the maximum value, or less than // When +, * or binary - create a value greater than the maximum value, or less than
// the minimum value that can be stored, it panics. // the minimum value that can be stored, it panics.
BinOpKind::Add => l.checked_add(r).and_then(|n| ity.ensure_fits(n)).map(zext), BinOpKind::Add => l.checked_add(r).and_then(|n| ity.ensure_fits(n)).map(zext),
@ -792,7 +792,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
ty::Uint(ity) => { ty::Uint(ity) => {
let bits = ity.bits(); let bits = ity.bits();
match op.node { match op {
BinOpKind::Add => l.checked_add(r).and_then(|n| ity.ensure_fits(n)).map(Constant::Int), BinOpKind::Add => l.checked_add(r).and_then(|n| ity.ensure_fits(n)).map(Constant::Int),
BinOpKind::Sub => l.checked_sub(r).and_then(|n| ity.ensure_fits(n)).map(Constant::Int), BinOpKind::Sub => l.checked_sub(r).and_then(|n| ity.ensure_fits(n)).map(Constant::Int),
BinOpKind::Mul => l.checked_mul(r).and_then(|n| ity.ensure_fits(n)).map(Constant::Int), BinOpKind::Mul => l.checked_mul(r).and_then(|n| ity.ensure_fits(n)).map(Constant::Int),
@ -815,7 +815,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
_ => None, _ => None,
}, },
// FIXME(f16_f128): add these types when binary operations are available on all platforms // FIXME(f16_f128): add these types when binary operations are available on all platforms
(Constant::F32(l), Some(Constant::F32(r))) => match op.node { (Constant::F32(l), Some(Constant::F32(r))) => match op {
BinOpKind::Add => Some(Constant::F32(l + r)), BinOpKind::Add => Some(Constant::F32(l + r)),
BinOpKind::Sub => Some(Constant::F32(l - r)), BinOpKind::Sub => Some(Constant::F32(l - r)),
BinOpKind::Mul => Some(Constant::F32(l * r)), BinOpKind::Mul => Some(Constant::F32(l * r)),
@ -829,7 +829,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
BinOpKind::Gt => Some(Constant::Bool(l > r)), BinOpKind::Gt => Some(Constant::Bool(l > r)),
_ => None, _ => None,
}, },
(Constant::F64(l), Some(Constant::F64(r))) => match op.node { (Constant::F64(l), Some(Constant::F64(r))) => match op {
BinOpKind::Add => Some(Constant::F64(l + r)), BinOpKind::Add => Some(Constant::F64(l + r)),
BinOpKind::Sub => Some(Constant::F64(l - r)), BinOpKind::Sub => Some(Constant::F64(l - r)),
BinOpKind::Mul => Some(Constant::F64(l * r)), BinOpKind::Mul => Some(Constant::F64(l * r)),
@ -843,7 +843,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
BinOpKind::Gt => Some(Constant::Bool(l > r)), BinOpKind::Gt => Some(Constant::Bool(l > r)),
_ => None, _ => None,
}, },
(l, r) => match (op.node, l, r) { (l, r) => match (op, l, r) {
(BinOpKind::And, Constant::Bool(false), _) => Some(Constant::Bool(false)), (BinOpKind::And, Constant::Bool(false), _) => Some(Constant::Bool(false)),
(BinOpKind::Or, Constant::Bool(true), _) => Some(Constant::Bool(true)), (BinOpKind::Or, Constant::Bool(true), _) => Some(Constant::Bool(true)),
(BinOpKind::And, Constant::Bool(true), Some(r)) | (BinOpKind::Or, Constant::Bool(false), Some(r)) => { (BinOpKind::And, Constant::Bool(true), Some(r)) | (BinOpKind::Or, Constant::Bool(false), Some(r)) => {