From c2b3f5c767e69a3788efb01633ae53f6adfcd6dd Mon Sep 17 00:00:00 2001 From: Quinn Sinclair Date: Sat, 30 Dec 2023 13:25:33 +0200 Subject: [PATCH] `identity_op` correctly suggests a deference for coerced references When `identity_op` identifies a `no_op`, provides a suggestion, it also checks the type of the type of the variable. If the variable is a reference that's been coerced into a value, e.g. ``` let x = &0i32; let _ = x + 0; ``` the suggestion will now use a derefence. This is done by identifying whether the variable is a reference to an integral value, and then whether it gets dereferenced. changelog: false positive: [`identity_op`]: corrected suggestion for reference coerced to value. fixes: #12050 --- clippy_lints/src/operators/identity_op.rs | 208 +++++++++++++--------- tests/ui/identity_op.fixed | 94 +++++++++- tests/ui/identity_op.rs | 94 +++++++++- tests/ui/identity_op.stderr | 154 +++++++++++----- 4 files changed, 426 insertions(+), 124 deletions(-) diff --git a/clippy_lints/src/operators/identity_op.rs b/clippy_lints/src/operators/identity_op.rs index 8ecb038627f5a..f671517c13461 100644 --- a/clippy_lints/src/operators/identity_op.rs +++ b/clippy_lints/src/operators/identity_op.rs @@ -18,82 +18,118 @@ pub(crate) fn check<'tcx>( right: &'tcx Expr<'_>, ) { if !is_allowed(cx, op, left, right) { - match op { - BinOpKind::Add | BinOpKind::BitOr | BinOpKind::BitXor => { - check_op( - cx, - left, - 0, - expr.span, - peel_hir_expr_refs(right).0.span, - needs_parenthesis(cx, expr, right), - ); - check_op( - cx, - right, - 0, - expr.span, - peel_hir_expr_refs(left).0.span, - Parens::Unneeded, - ); - }, - BinOpKind::Shl | BinOpKind::Shr | BinOpKind::Sub => { - check_op( - cx, - right, - 0, - expr.span, - peel_hir_expr_refs(left).0.span, - Parens::Unneeded, - ); - }, - BinOpKind::Mul => { - check_op( - cx, - left, - 1, - expr.span, - peel_hir_expr_refs(right).0.span, - needs_parenthesis(cx, expr, right), - ); - check_op( - cx, - right, - 1, - expr.span, - peel_hir_expr_refs(left).0.span, - Parens::Unneeded, - ); - }, - BinOpKind::Div => check_op( + return; + } + + // we need to know whether a ref is coerced to a value + // if a ref is coerced, then the suggested lint must deref it + // e.g. `let _: i32 = x+0` with `x: &i32` should be replaced with `let _: i32 = *x`. + // we do this by checking the _kind_ of the type of the expression + // if it's a ref, we then check whether it is erased, and that's it. + let (peeled_left_span, left_is_coerced_to_value) = { + let expr = peel_hir_expr_refs(left).0; + let span = expr.span; + let is_coerced = expr_is_erased_ref(cx, expr); + (span, is_coerced) + }; + + let (peeled_right_span, right_is_coerced_to_value) = { + let expr = peel_hir_expr_refs(right).0; + let span = expr.span; + let is_coerced = expr_is_erased_ref(cx, expr); + (span, is_coerced) + }; + + match op { + BinOpKind::Add | BinOpKind::BitOr | BinOpKind::BitXor => { + check_op( + cx, + left, + 0, + expr.span, + peeled_right_span, + needs_parenthesis(cx, expr, right), + right_is_coerced_to_value, + ); + check_op( + cx, + right, + 0, + expr.span, + peeled_left_span, + Parens::Unneeded, + left_is_coerced_to_value, + ); + }, + BinOpKind::Shl | BinOpKind::Shr | BinOpKind::Sub => { + check_op( + cx, + right, + 0, + expr.span, + peeled_left_span, + Parens::Unneeded, + left_is_coerced_to_value, + ); + }, + BinOpKind::Mul => { + check_op( + cx, + left, + 1, + expr.span, + peeled_right_span, + needs_parenthesis(cx, expr, right), + right_is_coerced_to_value, + ); + check_op( cx, right, 1, expr.span, - peel_hir_expr_refs(left).0.span, + peeled_left_span, Parens::Unneeded, - ), - BinOpKind::BitAnd => { - check_op( - cx, - left, - -1, - expr.span, - peel_hir_expr_refs(right).0.span, - needs_parenthesis(cx, expr, right), - ); - check_op( - cx, - right, - -1, - expr.span, - peel_hir_expr_refs(left).0.span, - Parens::Unneeded, - ); - }, - BinOpKind::Rem => check_remainder(cx, left, right, expr.span, left.span), - _ => (), - } + left_is_coerced_to_value, + ); + }, + BinOpKind::Div => check_op( + cx, + right, + 1, + expr.span, + peeled_left_span, + Parens::Unneeded, + left_is_coerced_to_value, + ), + BinOpKind::BitAnd => { + check_op( + cx, + left, + -1, + expr.span, + peeled_right_span, + needs_parenthesis(cx, expr, right), + right_is_coerced_to_value, + ); + check_op( + cx, + right, + -1, + expr.span, + peeled_left_span, + Parens::Unneeded, + left_is_coerced_to_value, + ); + }, + BinOpKind::Rem => check_remainder(cx, left, right, expr.span, left.span), + _ => (), + } +} + +fn expr_is_erased_ref(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + match cx.typeck_results().expr_ty(expr).kind() { + ty::Ref(r, ..) => r.is_erased(), + _ => false, } } @@ -144,11 +180,11 @@ fn needs_parenthesis(cx: &LateContext<'_>, binary: &Expr<'_>, right: &Expr<'_>) } fn is_allowed(cx: &LateContext<'_>, cmp: BinOpKind, left: &Expr<'_>, right: &Expr<'_>) -> bool { - // This lint applies to integers - !cx.typeck_results().expr_ty(left).peel_refs().is_integral() - || !cx.typeck_results().expr_ty(right).peel_refs().is_integral() + // This lint applies to integers and their references + cx.typeck_results().expr_ty(left).peel_refs().is_integral() + && cx.typeck_results().expr_ty(right).peel_refs().is_integral() // `1 << 0` is a common pattern in bit manipulation code - || (cmp == BinOpKind::Shl + && !(cmp == BinOpKind::Shl && constant_simple(cx, cx.typeck_results(), right) == Some(Constant::Int(0)) && constant_simple(cx, cx.typeck_results(), left) == Some(Constant::Int(1))) } @@ -161,11 +197,11 @@ fn check_remainder(cx: &LateContext<'_>, left: &Expr<'_>, right: &Expr<'_>, span (Some(FullInt::U(lv)), Some(FullInt::U(rv))) => lv < rv, _ => return, } { - span_ineffective_operation(cx, span, arg, Parens::Unneeded); + span_ineffective_operation(cx, span, arg, Parens::Unneeded, false); } } -fn check_op(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span, parens: Parens) { +fn check_op(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span, parens: Parens, is_erased: bool) { if let Some(Constant::Int(v)) = constant_simple(cx, cx.typeck_results(), e).map(Constant::peel_refs) { let check = match *cx.typeck_results().expr_ty(e).peel_refs().kind() { ty::Int(ity) => unsext(cx.tcx, -1_i128, ity), @@ -178,18 +214,28 @@ fn check_op(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span, pa 1 => v == 1, _ => unreachable!(), } { - span_ineffective_operation(cx, span, arg, parens); + span_ineffective_operation(cx, span, arg, parens, is_erased); } } } -fn span_ineffective_operation(cx: &LateContext<'_>, span: Span, arg: Span, parens: Parens) { +fn span_ineffective_operation( + cx: &LateContext<'_>, + span: Span, + arg: Span, + parens: Parens, + is_ref_coerced_to_val: bool, +) { let mut applicability = Applicability::MachineApplicable; let expr_snippet = snippet_with_applicability(cx, arg, "..", &mut applicability); - + let expr_snippet = if is_ref_coerced_to_val { + format!("*{expr_snippet}") + } else { + expr_snippet.into_owned() + }; let suggestion = match parens { Parens::Needed => format!("({expr_snippet})"), - Parens::Unneeded => expr_snippet.into_owned(), + Parens::Unneeded => expr_snippet, }; span_lint_and_sugg( diff --git a/tests/ui/identity_op.fixed b/tests/ui/identity_op.fixed index f3b4b1fffa0b5..660e9a21b181a 100644 --- a/tests/ui/identity_op.fixed +++ b/tests/ui/identity_op.fixed @@ -6,7 +6,9 @@ clippy::unnecessary_operation, clippy::op_ref, clippy::double_parens, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::borrow_deref_ref, + clippy::deref_addrof )] use std::fmt::Write as _; @@ -40,32 +42,45 @@ fn main() { let x = 0; x; + //~^ ERROR: this operation has no effect x; + //~^ ERROR: this operation has no effect x + 1; x; + //~^ ERROR: this operation has no effect 1 + x; x - ZERO; //no error, as we skip lookups (for now) x; + //~^ ERROR: this operation has no effect ((ZERO)) | x; //no error, as we skip lookups (for now) x; + //~^ ERROR: this operation has no effect x; + //~^ ERROR: this operation has no effect x / ONE; //no error, as we skip lookups (for now) x / 2; //no false positive x & NEG_ONE; //no error, as we skip lookups (for now) x; + //~^ ERROR: this operation has no effect let u: u8 = 0; u; + //~^ ERROR: this operation has no effect 1 << 0; // no error, this case is allowed, see issue 3430 42; + //~^ ERROR: this operation has no effect 1; + //~^ ERROR: this operation has no effect 42; + //~^ ERROR: this operation has no effect x; + //~^ ERROR: this operation has no effect x; + //~^ ERROR: this operation has no effect let mut a = A(String::new()); let b = a << 0; // no error: non-integer @@ -73,10 +88,15 @@ fn main() { 1 * Meter; // no error: non-integer 2; + //~^ ERROR: this operation has no effect -2; + //~^ ERROR: this operation has no effect 2 + x; + //~^ ERROR: this operation has no effect -2 + x; + //~^ ERROR: this operation has no effect x + 1; + //~^ ERROR: this operation has no effect (x + 1) % 3; // no error 4 % 3; // no error 4 % -3; // no error @@ -85,38 +105,110 @@ fn main() { let a = 0; let b = true; (if b { 1 } else { 2 }); + //~^ ERROR: this operation has no effect (if b { 1 } else { 2 }) + if b { 3 } else { 4 }; + //~^ ERROR: this operation has no effect (match a { 0 => 10, _ => 20 }); + //~^ ERROR: this operation has no effect (match a { 0 => 10, _ => 20 }) + match a { 0 => 30, _ => 40 }; + //~^ ERROR: this operation has no effect (if b { 1 } else { 2 }) + match a { 0 => 30, _ => 40 }; + //~^ ERROR: this operation has no effect (match a { 0 => 10, _ => 20 }) + if b { 3 } else { 4 }; + //~^ ERROR: this operation has no effect (if b { 1 } else { 2 }); + //~^ ERROR: this operation has no effect ({ a }) + 3; + //~^ ERROR: this operation has no effect ({ a } * 2); + //~^ ERROR: this operation has no effect (loop { let mut c = 0; if c == 10 { break c; } c += 1; }) + { a * 2 }; + //~^ ERROR: this operation has no effect fn f(_: i32) { todo!(); } + f(a + { 8 * 5 }); + //~^ ERROR: this operation has no effect f(if b { 1 } else { 2 } + 3); + //~^ ERROR: this operation has no effect + const _: i32 = { 2 * 4 } + 3; + //~^ ERROR: this operation has no effect const _: i32 = { 1 + 2 * 3 } + 3; + //~^ ERROR: this operation has no effect a as usize; + //~^ ERROR: this operation has no effect let _ = a as usize; + //~^ ERROR: this operation has no effect ({ a } as usize); + //~^ ERROR: this operation has no effect 2 * { a }; + //~^ ERROR: this operation has no effect (({ a } + 4)); + //~^ ERROR: this operation has no effect 1; + //~^ ERROR: this operation has no effect // Issue #9904 let x = 0i32; let _: i32 = x; + //~^ ERROR: this operation has no effect } pub fn decide(a: bool, b: bool) -> u32 { (if a { 1 } else { 2 }) + if b { 3 } else { 5 } } + +/// The following tests are from / for issue #12050 +/// In short, the lint didn't work for coerced references, +/// e.g. let x = &0; let y = x + 0; +/// because the suggested fix was `let y = x;` but +/// it should have been `let y = *x;` +fn issue_12050() { + { + let x = &0i32; + let _: i32 = *x; + //~^ ERROR: this operation has no effect + let _: i32 = *x; + //~^ ERROR: this operation has no effect + } + { + let x = &&0i32; + let _: i32 = **x; + //~^ ERROR: this operation has no effect + let x = &&0i32; + let _: i32 = **x; + //~^ ERROR: this operation has no effect + } + { + // this is just silly + let x = &&&0i32; + let _: i32 = ***x; + //~^ ERROR: this operation has no effect + let _: i32 = ***x; + //~^ ERROR: this operation has no effect + let x = 0i32; + let _: i32 = *&x; + //~^ ERROR: this operation has no effect + let _: i32 = **&&x; + //~^ ERROR: this operation has no effect + let _: i32 = *&*&x; + //~^ ERROR: this operation has no effect + let _: i32 = **&&*&x; + //~^ ERROR: this operation has no effect + } + { + // this is getting ridiculous, but we should still see the same + // error message so let's just keep going + let x = &0i32; + let _: i32 = ***&&*&x; + //~^ ERROR: this operation has no effect + let _: i32 = ***&&*&x; + //~^ ERROR: this operation has no effect + } +} diff --git a/tests/ui/identity_op.rs b/tests/ui/identity_op.rs index 631aa3b0215f2..bbef531e9dc05 100644 --- a/tests/ui/identity_op.rs +++ b/tests/ui/identity_op.rs @@ -6,7 +6,9 @@ clippy::unnecessary_operation, clippy::op_ref, clippy::double_parens, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::borrow_deref_ref, + clippy::deref_addrof )] use std::fmt::Write as _; @@ -40,32 +42,45 @@ fn main() { let x = 0; x + 0; + //~^ ERROR: this operation has no effect x + (1 - 1); + //~^ ERROR: this operation has no effect x + 1; 0 + x; + //~^ ERROR: this operation has no effect 1 + x; x - ZERO; //no error, as we skip lookups (for now) x | (0); + //~^ ERROR: this operation has no effect ((ZERO)) | x; //no error, as we skip lookups (for now) x * 1; + //~^ ERROR: this operation has no effect 1 * x; + //~^ ERROR: this operation has no effect x / ONE; //no error, as we skip lookups (for now) x / 2; //no false positive x & NEG_ONE; //no error, as we skip lookups (for now) -1 & x; + //~^ ERROR: this operation has no effect let u: u8 = 0; u & 255; + //~^ ERROR: this operation has no effect 1 << 0; // no error, this case is allowed, see issue 3430 42 << 0; + //~^ ERROR: this operation has no effect 1 >> 0; + //~^ ERROR: this operation has no effect 42 >> 0; + //~^ ERROR: this operation has no effect &x >> 0; + //~^ ERROR: this operation has no effect x >> &0; + //~^ ERROR: this operation has no effect let mut a = A(String::new()); let b = a << 0; // no error: non-integer @@ -73,10 +88,15 @@ fn main() { 1 * Meter; // no error: non-integer 2 % 3; + //~^ ERROR: this operation has no effect -2 % 3; + //~^ ERROR: this operation has no effect 2 % -3 + x; + //~^ ERROR: this operation has no effect -2 % -3 + x; + //~^ ERROR: this operation has no effect x + 1 % 3; + //~^ ERROR: this operation has no effect (x + 1) % 3; // no error 4 % 3; // no error 4 % -3; // no error @@ -85,38 +105,110 @@ fn main() { let a = 0; let b = true; 0 + if b { 1 } else { 2 }; + //~^ ERROR: this operation has no effect 0 + if b { 1 } else { 2 } + if b { 3 } else { 4 }; + //~^ ERROR: this operation has no effect 0 + match a { 0 => 10, _ => 20 }; + //~^ ERROR: this operation has no effect 0 + match a { 0 => 10, _ => 20 } + match a { 0 => 30, _ => 40 }; + //~^ ERROR: this operation has no effect 0 + if b { 1 } else { 2 } + match a { 0 => 30, _ => 40 }; + //~^ ERROR: this operation has no effect 0 + match a { 0 => 10, _ => 20 } + if b { 3 } else { 4 }; + //~^ ERROR: this operation has no effect (if b { 1 } else { 2 }) + 0; + //~^ ERROR: this operation has no effect 0 + { a } + 3; + //~^ ERROR: this operation has no effect 0 + { a } * 2; + //~^ ERROR: this operation has no effect 0 + loop { let mut c = 0; if c == 10 { break c; } c += 1; } + { a * 2 }; + //~^ ERROR: this operation has no effect fn f(_: i32) { todo!(); } + f(1 * a + { 8 * 5 }); + //~^ ERROR: this operation has no effect f(0 + if b { 1 } else { 2 } + 3); + //~^ ERROR: this operation has no effect + const _: i32 = { 2 * 4 } + 0 + 3; + //~^ ERROR: this operation has no effect const _: i32 = 0 + { 1 + 2 * 3 } + 3; + //~^ ERROR: this operation has no effect 0 + a as usize; + //~^ ERROR: this operation has no effect let _ = 0 + a as usize; + //~^ ERROR: this operation has no effect 0 + { a } as usize; + //~^ ERROR: this operation has no effect 2 * (0 + { a }); + //~^ ERROR: this operation has no effect 1 * ({ a } + 4); + //~^ ERROR: this operation has no effect 1 * 1; + //~^ ERROR: this operation has no effect // Issue #9904 let x = 0i32; let _: i32 = &x + 0; + //~^ ERROR: this operation has no effect } pub fn decide(a: bool, b: bool) -> u32 { 0 + if a { 1 } else { 2 } + if b { 3 } else { 5 } } + +/// The following tests are from / for issue #12050 +/// In short, the lint didn't work for coerced references, +/// e.g. let x = &0; let y = x + 0; +/// because the suggested fix was `let y = x;` but +/// it should have been `let y = *x;` +fn issue_12050() { + { + let x = &0i32; + let _: i32 = *x + 0; + //~^ ERROR: this operation has no effect + let _: i32 = x + 0; + //~^ ERROR: this operation has no effect + } + { + let x = &&0i32; + let _: i32 = **x + 0; + //~^ ERROR: this operation has no effect + let x = &&0i32; + let _: i32 = *x + 0; + //~^ ERROR: this operation has no effect + } + { + // this is just silly + let x = &&&0i32; + let _: i32 = ***x + 0; + //~^ ERROR: this operation has no effect + let _: i32 = **x + 0; + //~^ ERROR: this operation has no effect + let x = 0i32; + let _: i32 = *&x + 0; + //~^ ERROR: this operation has no effect + let _: i32 = **&&x + 0; + //~^ ERROR: this operation has no effect + let _: i32 = *&*&x + 0; + //~^ ERROR: this operation has no effect + let _: i32 = **&&*&x + 0; + //~^ ERROR: this operation has no effect + } + { + // this is getting ridiculous, but we should still see the same + // error message so let's just keep going + let x = &0i32; + let _: i32 = **&&*&x + 0; + //~^ ERROR: this operation has no effect + let _: i32 = **&&*&x + 0; + //~^ ERROR: this operation has no effect + } +} diff --git a/tests/ui/identity_op.stderr b/tests/ui/identity_op.stderr index 2a61327f15f2a..6bb980035c1a4 100644 --- a/tests/ui/identity_op.stderr +++ b/tests/ui/identity_op.stderr @@ -1,5 +1,5 @@ error: this operation has no effect - --> $DIR/identity_op.rs:42:5 + --> $DIR/identity_op.rs:44:5 | LL | x + 0; | ^^^^^ help: consider reducing it to: `x` @@ -8,238 +8,310 @@ LL | x + 0; = help: to override `-D warnings` add `#[allow(clippy::identity_op)]` error: this operation has no effect - --> $DIR/identity_op.rs:43:5 + --> $DIR/identity_op.rs:46:5 | LL | x + (1 - 1); | ^^^^^^^^^^^ help: consider reducing it to: `x` error: this operation has no effect - --> $DIR/identity_op.rs:45:5 + --> $DIR/identity_op.rs:49:5 | LL | 0 + x; | ^^^^^ help: consider reducing it to: `x` error: this operation has no effect - --> $DIR/identity_op.rs:48:5 + --> $DIR/identity_op.rs:53:5 | LL | x | (0); | ^^^^^^^ help: consider reducing it to: `x` error: this operation has no effect - --> $DIR/identity_op.rs:51:5 + --> $DIR/identity_op.rs:57:5 | LL | x * 1; | ^^^^^ help: consider reducing it to: `x` error: this operation has no effect - --> $DIR/identity_op.rs:52:5 + --> $DIR/identity_op.rs:59:5 | LL | 1 * x; | ^^^^^ help: consider reducing it to: `x` error: this operation has no effect - --> $DIR/identity_op.rs:58:5 + --> $DIR/identity_op.rs:66:5 | LL | -1 & x; | ^^^^^^ help: consider reducing it to: `x` error: this operation has no effect - --> $DIR/identity_op.rs:61:5 + --> $DIR/identity_op.rs:70:5 | LL | u & 255; | ^^^^^^^ help: consider reducing it to: `u` error: this operation has no effect - --> $DIR/identity_op.rs:64:5 + --> $DIR/identity_op.rs:74:5 | LL | 42 << 0; | ^^^^^^^ help: consider reducing it to: `42` error: this operation has no effect - --> $DIR/identity_op.rs:65:5 + --> $DIR/identity_op.rs:76:5 | LL | 1 >> 0; | ^^^^^^ help: consider reducing it to: `1` error: this operation has no effect - --> $DIR/identity_op.rs:66:5 + --> $DIR/identity_op.rs:78:5 | LL | 42 >> 0; | ^^^^^^^ help: consider reducing it to: `42` error: this operation has no effect - --> $DIR/identity_op.rs:67:5 + --> $DIR/identity_op.rs:80:5 | LL | &x >> 0; | ^^^^^^^ help: consider reducing it to: `x` error: this operation has no effect - --> $DIR/identity_op.rs:68:5 + --> $DIR/identity_op.rs:82:5 | LL | x >> &0; | ^^^^^^^ help: consider reducing it to: `x` error: this operation has no effect - --> $DIR/identity_op.rs:75:5 + --> $DIR/identity_op.rs:90:5 | LL | 2 % 3; | ^^^^^ help: consider reducing it to: `2` error: this operation has no effect - --> $DIR/identity_op.rs:76:5 + --> $DIR/identity_op.rs:92:5 | LL | -2 % 3; | ^^^^^^ help: consider reducing it to: `-2` error: this operation has no effect - --> $DIR/identity_op.rs:77:5 + --> $DIR/identity_op.rs:94:5 | LL | 2 % -3 + x; | ^^^^^^ help: consider reducing it to: `2` error: this operation has no effect - --> $DIR/identity_op.rs:78:5 + --> $DIR/identity_op.rs:96:5 | LL | -2 % -3 + x; | ^^^^^^^ help: consider reducing it to: `-2` error: this operation has no effect - --> $DIR/identity_op.rs:79:9 + --> $DIR/identity_op.rs:98:9 | LL | x + 1 % 3; | ^^^^^ help: consider reducing it to: `1` error: this operation has no effect - --> $DIR/identity_op.rs:87:5 + --> $DIR/identity_op.rs:107:5 | LL | 0 + if b { 1 } else { 2 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(if b { 1 } else { 2 })` error: this operation has no effect - --> $DIR/identity_op.rs:88:5 + --> $DIR/identity_op.rs:109:5 | LL | 0 + if b { 1 } else { 2 } + if b { 3 } else { 4 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(if b { 1 } else { 2 })` error: this operation has no effect - --> $DIR/identity_op.rs:89:5 + --> $DIR/identity_op.rs:111:5 | LL | 0 + match a { 0 => 10, _ => 20 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(match a { 0 => 10, _ => 20 })` error: this operation has no effect - --> $DIR/identity_op.rs:90:5 + --> $DIR/identity_op.rs:113:5 | LL | 0 + match a { 0 => 10, _ => 20 } + match a { 0 => 30, _ => 40 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(match a { 0 => 10, _ => 20 })` error: this operation has no effect - --> $DIR/identity_op.rs:91:5 + --> $DIR/identity_op.rs:115:5 | LL | 0 + if b { 1 } else { 2 } + match a { 0 => 30, _ => 40 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(if b { 1 } else { 2 })` error: this operation has no effect - --> $DIR/identity_op.rs:92:5 + --> $DIR/identity_op.rs:117:5 | LL | 0 + match a { 0 => 10, _ => 20 } + if b { 3 } else { 4 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(match a { 0 => 10, _ => 20 })` error: this operation has no effect - --> $DIR/identity_op.rs:93:5 + --> $DIR/identity_op.rs:119:5 | LL | (if b { 1 } else { 2 }) + 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(if b { 1 } else { 2 })` error: this operation has no effect - --> $DIR/identity_op.rs:95:5 + --> $DIR/identity_op.rs:122:5 | LL | 0 + { a } + 3; | ^^^^^^^^^ help: consider reducing it to: `({ a })` error: this operation has no effect - --> $DIR/identity_op.rs:96:5 + --> $DIR/identity_op.rs:124:5 | LL | 0 + { a } * 2; | ^^^^^^^^^^^^^ help: consider reducing it to: `({ a } * 2)` error: this operation has no effect - --> $DIR/identity_op.rs:97:5 + --> $DIR/identity_op.rs:126:5 | LL | 0 + loop { let mut c = 0; if c == 10 { break c; } c += 1; } + { a * 2 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(loop { let mut c = 0; if c == 10 { break c; } c += 1; })` error: this operation has no effect - --> $DIR/identity_op.rs:102:7 + --> $DIR/identity_op.rs:133:7 | LL | f(1 * a + { 8 * 5 }); | ^^^^^ help: consider reducing it to: `a` error: this operation has no effect - --> $DIR/identity_op.rs:103:7 + --> $DIR/identity_op.rs:135:7 | LL | f(0 + if b { 1 } else { 2 } + 3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `if b { 1 } else { 2 }` error: this operation has no effect - --> $DIR/identity_op.rs:104:20 + --> $DIR/identity_op.rs:138:20 | LL | const _: i32 = { 2 * 4 } + 0 + 3; | ^^^^^^^^^^^^^ help: consider reducing it to: `{ 2 * 4 }` error: this operation has no effect - --> $DIR/identity_op.rs:105:20 + --> $DIR/identity_op.rs:140:20 | LL | const _: i32 = 0 + { 1 + 2 * 3 } + 3; | ^^^^^^^^^^^^^^^^^ help: consider reducing it to: `{ 1 + 2 * 3 }` error: this operation has no effect - --> $DIR/identity_op.rs:107:5 + --> $DIR/identity_op.rs:143:5 | LL | 0 + a as usize; | ^^^^^^^^^^^^^^ help: consider reducing it to: `a as usize` error: this operation has no effect - --> $DIR/identity_op.rs:108:13 + --> $DIR/identity_op.rs:145:13 | LL | let _ = 0 + a as usize; | ^^^^^^^^^^^^^^ help: consider reducing it to: `a as usize` error: this operation has no effect - --> $DIR/identity_op.rs:109:5 + --> $DIR/identity_op.rs:147:5 | LL | 0 + { a } as usize; | ^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `({ a } as usize)` error: this operation has no effect - --> $DIR/identity_op.rs:111:9 + --> $DIR/identity_op.rs:150:9 | LL | 2 * (0 + { a }); | ^^^^^^^^^^^ help: consider reducing it to: `{ a }` error: this operation has no effect - --> $DIR/identity_op.rs:112:5 + --> $DIR/identity_op.rs:152:5 | LL | 1 * ({ a } + 4); | ^^^^^^^^^^^^^^^ help: consider reducing it to: `(({ a } + 4))` error: this operation has no effect - --> $DIR/identity_op.rs:113:5 + --> $DIR/identity_op.rs:154:5 | LL | 1 * 1; | ^^^^^ help: consider reducing it to: `1` error: this operation has no effect - --> $DIR/identity_op.rs:117:18 + --> $DIR/identity_op.rs:159:18 | LL | let _: i32 = &x + 0; | ^^^^^^ help: consider reducing it to: `x` error: this operation has no effect - --> $DIR/identity_op.rs:121:5 + --> $DIR/identity_op.rs:164:5 | LL | 0 + if a { 1 } else { 2 } + if b { 3 } else { 5 } | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(if a { 1 } else { 2 })` -error: aborting due to 40 previous errors +error: this operation has no effect + --> $DIR/identity_op.rs:175:22 + | +LL | let _: i32 = *x + 0; + | ^^^^^^ help: consider reducing it to: `*x` + +error: this operation has no effect + --> $DIR/identity_op.rs:177:22 + | +LL | let _: i32 = x + 0; + | ^^^^^ help: consider reducing it to: `*x` + +error: this operation has no effect + --> $DIR/identity_op.rs:182:22 + | +LL | let _: i32 = **x + 0; + | ^^^^^^^ help: consider reducing it to: `**x` + +error: this operation has no effect + --> $DIR/identity_op.rs:185:22 + | +LL | let _: i32 = *x + 0; + | ^^^^^^ help: consider reducing it to: `**x` + +error: this operation has no effect + --> $DIR/identity_op.rs:191:22 + | +LL | let _: i32 = ***x + 0; + | ^^^^^^^^ help: consider reducing it to: `***x` + +error: this operation has no effect + --> $DIR/identity_op.rs:193:22 + | +LL | let _: i32 = **x + 0; + | ^^^^^^^ help: consider reducing it to: `***x` + +error: this operation has no effect + --> $DIR/identity_op.rs:196:22 + | +LL | let _: i32 = *&x + 0; + | ^^^^^^^ help: consider reducing it to: `*&x` + +error: this operation has no effect + --> $DIR/identity_op.rs:198:22 + | +LL | let _: i32 = **&&x + 0; + | ^^^^^^^^^ help: consider reducing it to: `**&&x` + +error: this operation has no effect + --> $DIR/identity_op.rs:200:22 + | +LL | let _: i32 = *&*&x + 0; + | ^^^^^^^^^ help: consider reducing it to: `*&*&x` + +error: this operation has no effect + --> $DIR/identity_op.rs:202:22 + | +LL | let _: i32 = **&&*&x + 0; + | ^^^^^^^^^^^ help: consider reducing it to: `**&&*&x` + +error: this operation has no effect + --> $DIR/identity_op.rs:209:22 + | +LL | let _: i32 = **&&*&x + 0; + | ^^^^^^^^^^^ help: consider reducing it to: `***&&*&x` + +error: this operation has no effect + --> $DIR/identity_op.rs:211:22 + | +LL | let _: i32 = **&&*&x + 0; + | ^^^^^^^^^^^ help: consider reducing it to: `***&&*&x` + +error: aborting due to 52 previous errors