[arithmetic-side-effects] Consider references

This commit is contained in:
Caio 2022-09-21 15:02:37 -03:00
parent 7248d06384
commit 4c5f23082a
3 changed files with 172 additions and 41 deletions

View File

@ -9,7 +9,6 @@
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::Ty;
use rustc_session::impl_lint_pass;
use rustc_span::source_map::{Span, Spanned};
@ -78,28 +77,47 @@ fn is_allowed_ty(&self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
)
}
/// Explicit integers like `1` or `i32::MAX`. Does not take into consideration references.
fn is_literal_integer(expr: &hir::Expr<'_>, expr_refs: Ty<'_>) -> bool {
let is_integral = expr_refs.is_integral();
let is_literal = matches!(expr.kind, hir::ExprKind::Lit(_));
is_integral && is_literal
}
// Common entry-point to avoid code duplication.
fn issue_lint(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
let msg = "arithmetic operation that can potentially result in unexpected side-effects";
span_lint(cx, ARITHMETIC_SIDE_EFFECTS, expr.span, msg);
self.expr_span = Some(expr.span);
}
/// * If `expr` is a literal integer like `1` or `i32::MAX`, returns itself.
/// * Is `expr` is a literal integer reference like `&199`, returns the literal integer without
/// references.
/// * If `expr` is anything else, returns `None`.
fn literal_integer<'expr, 'tcx>(
cx: &LateContext<'tcx>,
expr: &'expr hir::Expr<'tcx>,
) -> Option<&'expr hir::Expr<'tcx>> {
let expr_refs = cx.typeck_results().expr_ty(expr).peel_refs();
if !expr_refs.is_integral() {
return None;
}
if matches!(expr.kind, hir::ExprKind::Lit(_)) {
return Some(expr);
}
if let hir::ExprKind::AddrOf(.., inn) = expr.kind && let hir::ExprKind::Lit(_) = inn.kind {
return Some(inn)
}
None
}
/// Manages when the lint should be triggered. Operations in constant environments, hard coded
/// types, custom allowed types and non-constant operations that won't overflow are ignored.
fn manage_bin_ops(
fn manage_bin_ops<'tcx>(
&mut self,
cx: &LateContext<'_>,
expr: &hir::Expr<'_>,
cx: &LateContext<'tcx>,
expr: &hir::Expr<'tcx>,
op: &Spanned<hir::BinOpKind>,
lhs: &hir::Expr<'_>,
rhs: &hir::Expr<'_>,
lhs: &hir::Expr<'tcx>,
rhs: &hir::Expr<'tcx>,
) {
if constant_simple(cx, cx.typeck_results(), expr).is_some() {
return;
@ -119,14 +137,11 @@ fn manage_bin_ops(
if self.is_allowed_ty(cx, lhs) || self.is_allowed_ty(cx, rhs) {
return;
}
let has_valid_op = match (
Self::is_literal_integer(lhs, cx.typeck_results().expr_ty(lhs).peel_refs()),
Self::is_literal_integer(rhs, cx.typeck_results().expr_ty(rhs).peel_refs()),
) {
(true, true) => true,
(true, false) => Self::has_valid_op(op, lhs),
(false, true) => Self::has_valid_op(op, rhs),
(false, false) => false,
let has_valid_op = match (Self::literal_integer(cx, lhs), Self::literal_integer(cx, rhs)) {
(None, None) => false,
(None, Some(local_expr)) => Self::has_valid_op(op, local_expr),
(Some(local_expr), None) => Self::has_valid_op(op, local_expr),
(Some(_), Some(_)) => true,
};
if !has_valid_op {
self.issue_lint(cx, expr);
@ -135,7 +150,7 @@ fn manage_bin_ops(
}
impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'tcx>) {
if self.expr_span.is_some() || self.const_span.map_or(false, |sp| sp.contains(expr.span)) {
return;
}

View File

@ -2,11 +2,12 @@
clippy::assign_op_pattern,
clippy::erasing_op,
clippy::identity_op,
clippy::op_ref,
clippy::unnecessary_owned_empty_strings,
arithmetic_overflow,
unconditional_panic
)]
#![feature(inline_const, saturating_int_impl)]
#![feature(const_mut_refs, inline_const, saturating_int_impl)]
#![warn(clippy::arithmetic_side_effects)]
use core::num::{Saturating, Wrapping};
@ -79,33 +80,50 @@ pub fn const_ops_should_not_trigger_the_lint() {
const _: i32 = 1 + 1;
let _ = const { 1 + 1 };
const _: i32 = { let mut n = -1; n = -(-1); n = -n; n };
let _ = const { let mut n = -1; n = -(-1); n = -n; n };
const _: i32 = { let mut n = 1; n = -1; n = -(-1); n = -n; n };
let _ = const { let mut n = 1; n = -1; n = -(-1); n = -n; n };
}
pub fn non_overflowing_runtime_ops_or_ops_already_handled_by_the_compiler() {
pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_trigger_the_lint() {
let mut _n = i32::MAX;
// Assign
_n += 0;
_n += &0;
_n -= 0;
_n -= &0;
_n /= 99;
_n /= &99;
_n %= 99;
_n %= &99;
_n *= 0;
_n *= &0;
_n *= 1;
_n *= &1;
// Binary
_n = _n + 0;
_n = _n + &0;
_n = 0 + _n;
_n = &0 + _n;
_n = _n - 0;
_n = _n - &0;
_n = 0 - _n;
_n = &0 - _n;
_n = _n / 99;
_n = _n / &99;
_n = _n % 99;
_n = _n % &99;
_n = _n * 0;
_n = _n * &0;
_n = 0 * _n;
_n = &0 * _n;
_n = _n * 1;
_n = _n * &1;
_n = 1 * _n;
_n = &1 * _n;
_n = 23 + 85;
_n = &23 + &85;
// Unary
_n = -1;
@ -117,23 +135,37 @@ pub fn overflowing_runtime_ops() {
// Assign
_n += 1;
_n += &1;
_n -= 1;
_n -= &1;
_n /= 0;
_n /= &0;
_n %= 0;
_n %= &0;
_n *= 2;
_n *= &2;
// Binary
_n = _n + 1;
_n = _n + &1;
_n = 1 + _n;
_n = &1 + _n;
_n = _n - 1;
_n = _n - &1;
_n = 1 - _n;
_n = &1 - _n;
_n = _n / 0;
_n = _n / &0;
_n = _n % 0;
_n = _n % &0;
_n = _n * 2;
_n = _n * &2;
_n = 2 * _n;
_n = &2 * _n;
// Unary
_n = -_n;
_n = -&_n;
}
fn main() {}

View File

@ -1,5 +1,5 @@
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:119:5
--> $DIR/arithmetic_side_effects.rs:137:5
|
LL | _n += 1;
| ^^^^^^^
@ -7,82 +7,166 @@ LL | _n += 1;
= note: `-D clippy::arithmetic-side-effects` implied by `-D warnings`
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:120:5
--> $DIR/arithmetic_side_effects.rs:138:5
|
LL | _n += &1;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:139:5
|
LL | _n -= 1;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:121:5
--> $DIR/arithmetic_side_effects.rs:140:5
|
LL | _n -= &1;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:141:5
|
LL | _n /= 0;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:122:5
--> $DIR/arithmetic_side_effects.rs:142:5
|
LL | _n /= &0;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:143:5
|
LL | _n %= 0;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:123:5
--> $DIR/arithmetic_side_effects.rs:144:5
|
LL | _n %= &0;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:145:5
|
LL | _n *= 2;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:126:10
--> $DIR/arithmetic_side_effects.rs:146:5
|
LL | _n *= &2;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:149:10
|
LL | _n = _n + 1;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:127:10
--> $DIR/arithmetic_side_effects.rs:150:10
|
LL | _n = _n + &1;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:151:10
|
LL | _n = 1 + _n;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:128:10
--> $DIR/arithmetic_side_effects.rs:152:10
|
LL | _n = &1 + _n;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:153:10
|
LL | _n = _n - 1;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:129:10
--> $DIR/arithmetic_side_effects.rs:154:10
|
LL | _n = _n - &1;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:155:10
|
LL | _n = 1 - _n;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:130:10
--> $DIR/arithmetic_side_effects.rs:156:10
|
LL | _n = &1 - _n;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:157:10
|
LL | _n = _n / 0;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:131:10
--> $DIR/arithmetic_side_effects.rs:158:10
|
LL | _n = _n / &0;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:159:10
|
LL | _n = _n % 0;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:132:10
--> $DIR/arithmetic_side_effects.rs:160:10
|
LL | _n = _n % &0;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:161:10
|
LL | _n = _n * 2;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:133:10
--> $DIR/arithmetic_side_effects.rs:162:10
|
LL | _n = _n * &2;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:163:10
|
LL | _n = 2 * _n;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:136:10
--> $DIR/arithmetic_side_effects.rs:164:10
|
LL | _n = &2 * _n;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:167:10
|
LL | _n = -_n;
| ^^^
error: aborting due to 14 previous errors
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:168:10
|
LL | _n = -&_n;
| ^^^^
error: aborting due to 28 previous errors