Auto merge of #10885 - max-niederman:redundant_local, r=Centri3

new lint: `redundant_locals`

This lint checks for code like the following:

```rs
let x = 1;
let x = x;
```

It checks (afaik) all cases where a binding is shadowed by its own value in the same block, including function parameters. This has no effect and is almost certainly accidental, so it's in the `correctness` category like `self_assignment`.

This also lays the groundwork for a more generalized version of #5102.

changelog: new lint: [`redundant_local`]
This commit is contained in:
bors 2023-07-22 10:54:16 +00:00
commit a44dcf80ef
13 changed files with 403 additions and 45 deletions

View file

@ -5190,6 +5190,7 @@ Released 2018-09-13
[`redundant_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_else [`redundant_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_else
[`redundant_feature_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_feature_names [`redundant_feature_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_feature_names
[`redundant_field_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names [`redundant_field_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names
[`redundant_locals`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_locals
[`redundant_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pattern [`redundant_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pattern
[`redundant_pattern_matching`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pattern_matching [`redundant_pattern_matching`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pattern_matching
[`redundant_pub_crate`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pub_crate [`redundant_pub_crate`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pub_crate

View file

@ -561,6 +561,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::redundant_closure_call::REDUNDANT_CLOSURE_CALL_INFO, crate::redundant_closure_call::REDUNDANT_CLOSURE_CALL_INFO,
crate::redundant_else::REDUNDANT_ELSE_INFO, crate::redundant_else::REDUNDANT_ELSE_INFO,
crate::redundant_field_names::REDUNDANT_FIELD_NAMES_INFO, crate::redundant_field_names::REDUNDANT_FIELD_NAMES_INFO,
crate::redundant_locals::REDUNDANT_LOCALS_INFO,
crate::redundant_pub_crate::REDUNDANT_PUB_CRATE_INFO, crate::redundant_pub_crate::REDUNDANT_PUB_CRATE_INFO,
crate::redundant_slicing::DEREF_BY_SLICING_INFO, crate::redundant_slicing::DEREF_BY_SLICING_INFO,
crate::redundant_slicing::REDUNDANT_SLICING_INFO, crate::redundant_slicing::REDUNDANT_SLICING_INFO,

View file

@ -275,6 +275,7 @@ mod redundant_clone;
mod redundant_closure_call; mod redundant_closure_call;
mod redundant_else; mod redundant_else;
mod redundant_field_names; mod redundant_field_names;
mod redundant_locals;
mod redundant_pub_crate; mod redundant_pub_crate;
mod redundant_slicing; mod redundant_slicing;
mod redundant_static_lifetimes; mod redundant_static_lifetimes;
@ -1091,6 +1092,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
absolute_paths_allowed_crates: absolute_paths_allowed_crates.clone(), absolute_paths_allowed_crates: absolute_paths_allowed_crates.clone(),
}) })
}); });
store.register_late_pass(|_| Box::new(redundant_locals::RedundantLocals));
// add lints here, do not remove this comment, it's used in `new_lint` // add lints here, do not remove this comment, it's used in `new_lint`
} }

View file

@ -0,0 +1,103 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::is_from_proc_macro;
use clippy_utils::ty::needs_ordered_drop;
use rustc_hir::def::Res;
use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, HirId, Local, Node, Pat, PatKind, QPath};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::Ident;
declare_clippy_lint! {
/// ### What it does
/// Checks for redundant redefinitions of local bindings.
///
/// ### Why is this bad?
/// Redundant redefinitions of local bindings do not change behavior and are likely to be unintended.
///
/// Note that although these bindings do not affect your code's meaning, they _may_ affect `rustc`'s stack allocation.
///
/// ### Example
/// ```rust
/// let a = 0;
/// let a = a;
///
/// fn foo(b: i32) {
/// let b = b;
/// }
/// ```
/// Use instead:
/// ```rust
/// let a = 0;
/// // no redefinition with the same name
///
/// fn foo(b: i32) {
/// // no redefinition with the same name
/// }
/// ```
#[clippy::version = "1.72.0"]
pub REDUNDANT_LOCALS,
correctness,
"redundant redefinition of a local binding"
}
declare_lint_pass!(RedundantLocals => [REDUNDANT_LOCALS]);
impl<'tcx> LateLintPass<'tcx> for RedundantLocals {
fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) {
if_chain! {
// the pattern is a single by-value binding
if let PatKind::Binding(BindingAnnotation(ByRef::No, mutability), _, ident, None) = local.pat.kind;
// the binding is not type-ascribed
if local.ty.is_none();
// the expression is a resolved path
if let Some(expr) = local.init;
if let ExprKind::Path(qpath @ QPath::Resolved(None, path)) = expr.kind;
// the path is a single segment equal to the local's name
if let [last_segment] = path.segments;
if last_segment.ident == ident;
// resolve the path to its defining binding pattern
if let Res::Local(binding_id) = cx.qpath_res(&qpath, expr.hir_id);
if let Node::Pat(binding_pat) = cx.tcx.hir().get(binding_id);
// the previous binding has the same mutability
if find_binding(binding_pat, ident).unwrap().1 == mutability;
// the local does not affect the code's drop behavior
if !affects_drop_behavior(cx, binding_id, local.hir_id, expr);
// the local is user-controlled
if !in_external_macro(cx.sess(), local.span);
if !is_from_proc_macro(cx, expr);
then {
span_lint_and_help(
cx,
REDUNDANT_LOCALS,
vec![binding_pat.span, local.span],
"redundant redefinition of a binding",
None,
&format!("remove the redefinition of `{ident}`"),
);
}
}
}
}
/// Find the annotation of a binding introduced by a pattern, or `None` if it's not introduced.
fn find_binding(pat: &Pat<'_>, name: Ident) -> Option<BindingAnnotation> {
let mut ret = None;
pat.each_binding_or_first(&mut |annotation, _, _, ident| {
if ident == name {
ret = Some(annotation);
}
});
ret
}
/// Check if a rebinding of a local affects the code's drop behavior.
fn affects_drop_behavior<'tcx>(cx: &LateContext<'tcx>, bind: HirId, rebind: HirId, rebind_expr: &Expr<'tcx>) -> bool {
let hir = cx.tcx.hir();
// the rebinding is in a different scope than the original binding
// and the type of the binding cares about drop order
hir.get_enclosing_scope(bind) != hir.get_enclosing_scope(rebind)
&& needs_ordered_drop(cx, cx.typeck_results().expr_ty(rebind_expr))
}

View file

@ -5,7 +5,8 @@
clippy::redundant_closure, clippy::redundant_closure,
clippy::ref_option_ref, clippy::ref_option_ref,
clippy::equatable_if_let, clippy::equatable_if_let,
clippy::let_unit_value clippy::let_unit_value,
clippy::redundant_locals
)] )]
fn bad1(string: Option<&str>) -> (bool, &str) { fn bad1(string: Option<&str>) -> (bool, &str) {

View file

@ -5,7 +5,8 @@
clippy::redundant_closure, clippy::redundant_closure,
clippy::ref_option_ref, clippy::ref_option_ref,
clippy::equatable_if_let, clippy::equatable_if_let,
clippy::let_unit_value clippy::let_unit_value,
clippy::redundant_locals
)] )]
fn bad1(string: Option<&str>) -> (bool, &str) { fn bad1(string: Option<&str>) -> (bool, &str) {

View file

@ -1,5 +1,5 @@
error: use Option::map_or instead of an if let/else error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:12:5 --> $DIR/option_if_let_else.rs:13:5
| |
LL | / if let Some(x) = string { LL | / if let Some(x) = string {
LL | | (true, x) LL | | (true, x)
@ -11,19 +11,19 @@ LL | | }
= note: `-D clippy::option-if-let-else` implied by `-D warnings` = note: `-D clippy::option-if-let-else` implied by `-D warnings`
error: use Option::map_or instead of an if let/else error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:30:13 --> $DIR/option_if_let_else.rs:31:13
| |
LL | let _ = if let Some(s) = *string { s.len() } else { 0 }; LL | let _ = if let Some(s) = *string { s.len() } else { 0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `string.map_or(0, |s| s.len())` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `string.map_or(0, |s| s.len())`
error: use Option::map_or instead of an if let/else error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:31:13 --> $DIR/option_if_let_else.rs:32:13
| |
LL | let _ = if let Some(s) = &num { s } else { &0 }; LL | let _ = if let Some(s) = &num { s } else { &0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)`
error: use Option::map_or instead of an if let/else error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:32:13 --> $DIR/option_if_let_else.rs:33:13
| |
LL | let _ = if let Some(s) = &mut num { LL | let _ = if let Some(s) = &mut num {
| _____________^ | _____________^
@ -43,13 +43,13 @@ LL ~ });
| |
error: use Option::map_or instead of an if let/else error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:38:13 --> $DIR/option_if_let_else.rs:39:13
| |
LL | let _ = if let Some(ref s) = num { s } else { &0 }; LL | let _ = if let Some(ref s) = num { s } else { &0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)`
error: use Option::map_or instead of an if let/else error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:39:13 --> $DIR/option_if_let_else.rs:40:13
| |
LL | let _ = if let Some(mut s) = num { LL | let _ = if let Some(mut s) = num {
| _____________^ | _____________^
@ -69,7 +69,7 @@ LL ~ });
| |
error: use Option::map_or instead of an if let/else error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:45:13 --> $DIR/option_if_let_else.rs:46:13
| |
LL | let _ = if let Some(ref mut s) = num { LL | let _ = if let Some(ref mut s) = num {
| _____________^ | _____________^
@ -89,7 +89,7 @@ LL ~ });
| |
error: use Option::map_or instead of an if let/else error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:54:5 --> $DIR/option_if_let_else.rs:55:5
| |
LL | / if let Some(x) = arg { LL | / if let Some(x) = arg {
LL | | let y = x * x; LL | | let y = x * x;
@ -108,7 +108,7 @@ LL + })
| |
error: use Option::map_or_else instead of an if let/else error: use Option::map_or_else instead of an if let/else
--> $DIR/option_if_let_else.rs:67:13 --> $DIR/option_if_let_else.rs:68:13
| |
LL | let _ = if let Some(x) = arg { LL | let _ = if let Some(x) = arg {
| _____________^ | _____________^
@ -120,7 +120,7 @@ LL | | };
| |_____^ help: try: `arg.map_or_else(|| side_effect(), |x| x)` | |_____^ help: try: `arg.map_or_else(|| side_effect(), |x| x)`
error: use Option::map_or_else instead of an if let/else error: use Option::map_or_else instead of an if let/else
--> $DIR/option_if_let_else.rs:76:13 --> $DIR/option_if_let_else.rs:77:13
| |
LL | let _ = if let Some(x) = arg { LL | let _ = if let Some(x) = arg {
| _____________^ | _____________^
@ -143,7 +143,7 @@ LL ~ }, |x| x * x * x * x);
| |
error: use Option::map_or_else instead of an if let/else error: use Option::map_or_else instead of an if let/else
--> $DIR/option_if_let_else.rs:109:13 --> $DIR/option_if_let_else.rs:110:13
| |
LL | / if let Some(idx) = s.find('.') { LL | / if let Some(idx) = s.find('.') {
LL | | vec![s[..idx].to_string(), s[idx..].to_string()] LL | | vec![s[..idx].to_string(), s[idx..].to_string()]
@ -153,7 +153,7 @@ LL | | }
| |_____________^ help: try: `s.find('.').map_or_else(|| vec![s.to_string()], |idx| vec![s[..idx].to_string(), s[idx..].to_string()])` | |_____________^ help: try: `s.find('.').map_or_else(|| vec![s.to_string()], |idx| vec![s[..idx].to_string(), s[idx..].to_string()])`
error: use Option::map_or_else instead of an if let/else error: use Option::map_or_else instead of an if let/else
--> $DIR/option_if_let_else.rs:120:5 --> $DIR/option_if_let_else.rs:121:5
| |
LL | / if let Ok(binding) = variable { LL | / if let Ok(binding) = variable {
LL | | println!("Ok {binding}"); LL | | println!("Ok {binding}");
@ -172,13 +172,13 @@ LL + })
| |
error: use Option::map_or instead of an if let/else error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:142:13 --> $DIR/option_if_let_else.rs:143:13
| |
LL | let _ = if let Some(x) = optional { x + 2 } else { 5 }; LL | let _ = if let Some(x) = optional { x + 2 } else { 5 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)`
error: use Option::map_or instead of an if let/else error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:152:13 --> $DIR/option_if_let_else.rs:153:13
| |
LL | let _ = if let Some(x) = Some(0) { LL | let _ = if let Some(x) = Some(0) {
| _____________^ | _____________^
@ -200,13 +200,13 @@ LL ~ });
| |
error: use Option::map_or instead of an if let/else error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:180:13 --> $DIR/option_if_let_else.rs:181:13
| |
LL | let _ = if let Some(x) = Some(0) { s.len() + x } else { s.len() }; LL | let _ = if let Some(x) = Some(0) { s.len() + x } else { s.len() };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(0).map_or(s.len(), |x| s.len() + x)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(0).map_or(s.len(), |x| s.len() + x)`
error: use Option::map_or instead of an if let/else error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:184:13 --> $DIR/option_if_let_else.rs:185:13
| |
LL | let _ = if let Some(x) = Some(0) { LL | let _ = if let Some(x) = Some(0) {
| _____________^ | _____________^
@ -226,7 +226,7 @@ LL ~ });
| |
error: use Option::map_or instead of an if let/else error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:223:13 --> $DIR/option_if_let_else.rs:224:13
| |
LL | let _ = match s { LL | let _ = match s {
| _____________^ | _____________^
@ -236,7 +236,7 @@ LL | | };
| |_____^ help: try: `s.map_or(1, |string| string.len())` | |_____^ help: try: `s.map_or(1, |string| string.len())`
error: use Option::map_or instead of an if let/else error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:227:13 --> $DIR/option_if_let_else.rs:228:13
| |
LL | let _ = match Some(10) { LL | let _ = match Some(10) {
| _____________^ | _____________^
@ -246,7 +246,7 @@ LL | | };
| |_____^ help: try: `Some(10).map_or(5, |a| a + 1)` | |_____^ help: try: `Some(10).map_or(5, |a| a + 1)`
error: use Option::map_or instead of an if let/else error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:233:13 --> $DIR/option_if_let_else.rs:234:13
| |
LL | let _ = match res { LL | let _ = match res {
| _____________^ | _____________^
@ -256,7 +256,7 @@ LL | | };
| |_____^ help: try: `res.map_or(1, |a| a + 1)` | |_____^ help: try: `res.map_or(1, |a| a + 1)`
error: use Option::map_or instead of an if let/else error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:237:13 --> $DIR/option_if_let_else.rs:238:13
| |
LL | let _ = match res { LL | let _ = match res {
| _____________^ | _____________^
@ -266,13 +266,13 @@ LL | | };
| |_____^ help: try: `res.map_or(1, |a| a + 1)` | |_____^ help: try: `res.map_or(1, |a| a + 1)`
error: use Option::map_or instead of an if let/else error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:241:13 --> $DIR/option_if_let_else.rs:242:13
| |
LL | let _ = if let Ok(a) = res { a + 1 } else { 5 }; LL | let _ = if let Ok(a) = res { a + 1 } else { 5 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `res.map_or(5, |a| a + 1)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `res.map_or(5, |a| a + 1)`
error: use Option::map_or instead of an if let/else error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:258:9 --> $DIR/option_if_let_else.rs:259:9
| |
LL | / match initial { LL | / match initial {
LL | | Some(value) => do_something(value), LL | | Some(value) => do_something(value),
@ -281,7 +281,7 @@ LL | | }
| |_________^ help: try: `initial.as_ref().map_or({}, |value| do_something(value))` | |_________^ help: try: `initial.as_ref().map_or({}, |value| do_something(value))`
error: use Option::map_or instead of an if let/else error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:265:9 --> $DIR/option_if_let_else.rs:266:9
| |
LL | / match initial { LL | / match initial {
LL | | Some(value) => do_something2(value), LL | | Some(value) => do_something2(value),

View file

@ -0,0 +1,111 @@
//@aux-build:proc_macros.rs:proc-macro
#![allow(unused, clippy::no_effect, clippy::needless_pass_by_ref_mut)]
#![warn(clippy::redundant_locals)]
extern crate proc_macros;
use proc_macros::{external, with_span};
fn main() {}
fn immutable() {
let x = 1;
let x = x;
}
fn mutable() {
let mut x = 1;
let mut x = x;
}
fn upgraded_mutability() {
let x = 1;
let mut x = x;
}
fn downgraded_mutability() {
let mut x = 1;
let x = x;
}
fn coercion(par: &mut i32) {
let par: &i32 = par;
let x: &mut i32 = &mut 1;
let x: &i32 = x;
}
fn parameter(x: i32) {
let x = x;
}
fn many() {
let x = 1;
let x = x;
let x = x;
let x = x;
let x = x;
}
fn interleaved() {
let a = 1;
let b = 2;
let a = a;
let b = b;
}
fn block() {
{
let x = 1;
let x = x;
}
}
fn closure() {
|| {
let x = 1;
let x = x;
};
|x: i32| {
let x = x;
};
}
fn consequential_drop_order() {
use std::sync::Mutex;
let mutex = Mutex::new(1);
let guard = mutex.lock().unwrap();
{
let guard = guard;
}
}
fn inconsequential_drop_order() {
let x = 1;
{
let x = x;
}
}
fn macros() {
macro_rules! rebind {
($x:ident) => {
let $x = 1;
let $x = $x;
};
}
rebind!(x);
external! {
let x = 1;
let x = x;
}
with_span! {
span
let x = 1;
let x = x;
}
}

View file

@ -0,0 +1,136 @@
error: redundant redefinition of a binding
--> $DIR/redundant_locals.rs:11:9
|
LL | let x = 1;
| ^
LL | let x = x;
| ^^^^^^^^^^
|
= help: remove the redefinition of `x`
= note: `-D clippy::redundant-locals` implied by `-D warnings`
error: redundant redefinition of a binding
--> $DIR/redundant_locals.rs:16:9
|
LL | let mut x = 1;
| ^^^^^
LL | let mut x = x;
| ^^^^^^^^^^^^^^
|
= help: remove the redefinition of `x`
error: redundant redefinition of a binding
--> $DIR/redundant_locals.rs:37:14
|
LL | fn parameter(x: i32) {
| ^
LL | let x = x;
| ^^^^^^^^^^
|
= help: remove the redefinition of `x`
error: redundant redefinition of a binding
--> $DIR/redundant_locals.rs:42:9
|
LL | let x = 1;
| ^
LL | let x = x;
| ^^^^^^^^^^
|
= help: remove the redefinition of `x`
error: redundant redefinition of a binding
--> $DIR/redundant_locals.rs:43:9
|
LL | let x = x;
| ^
LL | let x = x;
| ^^^^^^^^^^
|
= help: remove the redefinition of `x`
error: redundant redefinition of a binding
--> $DIR/redundant_locals.rs:44:9
|
LL | let x = x;
| ^
LL | let x = x;
| ^^^^^^^^^^
|
= help: remove the redefinition of `x`
error: redundant redefinition of a binding
--> $DIR/redundant_locals.rs:45:9
|
LL | let x = x;
| ^
LL | let x = x;
| ^^^^^^^^^^
|
= help: remove the redefinition of `x`
error: redundant redefinition of a binding
--> $DIR/redundant_locals.rs:50:9
|
LL | let a = 1;
| ^
LL | let b = 2;
LL | let a = a;
| ^^^^^^^^^^
|
= help: remove the redefinition of `a`
error: redundant redefinition of a binding
--> $DIR/redundant_locals.rs:51:9
|
LL | let b = 2;
| ^
LL | let a = a;
LL | let b = b;
| ^^^^^^^^^^
|
= help: remove the redefinition of `b`
error: redundant redefinition of a binding
--> $DIR/redundant_locals.rs:58:13
|
LL | let x = 1;
| ^
LL | let x = x;
| ^^^^^^^^^^
|
= help: remove the redefinition of `x`
error: redundant redefinition of a binding
--> $DIR/redundant_locals.rs:65:13
|
LL | let x = 1;
| ^
LL | let x = x;
| ^^^^^^^^^^
|
= help: remove the redefinition of `x`
error: redundant redefinition of a binding
--> $DIR/redundant_locals.rs:68:6
|
LL | |x: i32| {
| ^
LL | let x = x;
| ^^^^^^^^^^
|
= help: remove the redefinition of `x`
error: redundant redefinition of a binding
--> $DIR/redundant_locals.rs:85:9
|
LL | let x = 1;
| ^
...
LL | let x = x;
| ^^^^^^^^^^
|
= help: remove the redefinition of `x`
error: aborting due to 13 previous errors

View file

@ -1,7 +1,7 @@
//@aux-build:proc_macro_derive.rs:proc-macro //@aux-build:proc_macro_derive.rs:proc-macro
#![warn(clippy::shadow_same, clippy::shadow_reuse, clippy::shadow_unrelated)] #![warn(clippy::shadow_same, clippy::shadow_reuse, clippy::shadow_unrelated)]
#![allow(clippy::let_unit_value, clippy::needless_if)] #![allow(clippy::let_unit_value, clippy::needless_if, clippy::redundant_locals)]
extern crate proc_macro_derive; extern crate proc_macro_derive;

View file

@ -11,7 +11,8 @@
unused_assignments, unused_assignments,
unused_variables, unused_variables,
clippy::let_and_return, clippy::let_and_return,
clippy::useless_vec clippy::useless_vec,
clippy::redundant_locals
)] )]
struct Foo(u32); struct Foo(u32);

View file

@ -11,7 +11,8 @@
unused_assignments, unused_assignments,
unused_variables, unused_variables,
clippy::let_and_return, clippy::let_and_return,
clippy::useless_vec clippy::useless_vec,
clippy::redundant_locals
)] )]
struct Foo(u32); struct Foo(u32);

View file

@ -1,5 +1,5 @@
error: this looks like you are swapping `bar.a` and `bar.b` manually error: this looks like you are swapping `bar.a` and `bar.b` manually
--> $DIR/swap.rs:28:5 --> $DIR/swap.rs:29:5
| |
LL | / let temp = bar.a; LL | / let temp = bar.a;
LL | | bar.a = bar.b; LL | | bar.a = bar.b;
@ -10,7 +10,7 @@ LL | | bar.b = temp;
= note: `-D clippy::manual-swap` implied by `-D warnings` = note: `-D clippy::manual-swap` implied by `-D warnings`
error: this looks like you are swapping elements of `foo` manually error: this looks like you are swapping elements of `foo` manually
--> $DIR/swap.rs:40:5 --> $DIR/swap.rs:41:5
| |
LL | / let temp = foo[0]; LL | / let temp = foo[0];
LL | | foo[0] = foo[1]; LL | | foo[0] = foo[1];
@ -18,7 +18,7 @@ LL | | foo[1] = temp;
| |__________________^ help: try: `foo.swap(0, 1);` | |__________________^ help: try: `foo.swap(0, 1);`
error: this looks like you are swapping elements of `foo` manually error: this looks like you are swapping elements of `foo` manually
--> $DIR/swap.rs:49:5 --> $DIR/swap.rs:50:5
| |
LL | / let temp = foo[0]; LL | / let temp = foo[0];
LL | | foo[0] = foo[1]; LL | | foo[0] = foo[1];
@ -26,7 +26,7 @@ LL | | foo[1] = temp;
| |__________________^ help: try: `foo.swap(0, 1);` | |__________________^ help: try: `foo.swap(0, 1);`
error: this looks like you are swapping elements of `foo` manually error: this looks like you are swapping elements of `foo` manually
--> $DIR/swap.rs:68:5 --> $DIR/swap.rs:69:5
| |
LL | / let temp = foo[0]; LL | / let temp = foo[0];
LL | | foo[0] = foo[1]; LL | | foo[0] = foo[1];
@ -34,7 +34,7 @@ LL | | foo[1] = temp;
| |__________________^ help: try: `foo.swap(0, 1);` | |__________________^ help: try: `foo.swap(0, 1);`
error: this looks like you are swapping `a` and `b` manually error: this looks like you are swapping `a` and `b` manually
--> $DIR/swap.rs:79:5 --> $DIR/swap.rs:80:5
| |
LL | / a ^= b; LL | / a ^= b;
LL | | b ^= a; LL | | b ^= a;
@ -42,7 +42,7 @@ LL | | a ^= b;
| |___________^ help: try: `std::mem::swap(&mut a, &mut b);` | |___________^ help: try: `std::mem::swap(&mut a, &mut b);`
error: this looks like you are swapping `bar.a` and `bar.b` manually error: this looks like you are swapping `bar.a` and `bar.b` manually
--> $DIR/swap.rs:87:5 --> $DIR/swap.rs:88:5
| |
LL | / bar.a ^= bar.b; LL | / bar.a ^= bar.b;
LL | | bar.b ^= bar.a; LL | | bar.b ^= bar.a;
@ -50,7 +50,7 @@ LL | | bar.a ^= bar.b;
| |___________________^ help: try: `std::mem::swap(&mut bar.a, &mut bar.b);` | |___________________^ help: try: `std::mem::swap(&mut bar.a, &mut bar.b);`
error: this looks like you are swapping elements of `foo` manually error: this looks like you are swapping elements of `foo` manually
--> $DIR/swap.rs:95:5 --> $DIR/swap.rs:96:5
| |
LL | / foo[0] ^= foo[1]; LL | / foo[0] ^= foo[1];
LL | | foo[1] ^= foo[0]; LL | | foo[1] ^= foo[0];
@ -58,7 +58,7 @@ LL | | foo[0] ^= foo[1];
| |_____________________^ help: try: `foo.swap(0, 1);` | |_____________________^ help: try: `foo.swap(0, 1);`
error: this looks like you are swapping `foo[0][1]` and `bar[1][0]` manually error: this looks like you are swapping `foo[0][1]` and `bar[1][0]` manually
--> $DIR/swap.rs:124:5 --> $DIR/swap.rs:125:5
| |
LL | / let temp = foo[0][1]; LL | / let temp = foo[0][1];
LL | | foo[0][1] = bar[1][0]; LL | | foo[0][1] = bar[1][0];
@ -68,7 +68,7 @@ LL | | bar[1][0] = temp;
= note: or maybe you should use `std::mem::replace`? = note: or maybe you should use `std::mem::replace`?
error: this looks like you are swapping `a` and `b` manually error: this looks like you are swapping `a` and `b` manually
--> $DIR/swap.rs:138:7 --> $DIR/swap.rs:139:7
| |
LL | ; let t = a; LL | ; let t = a;
| _______^ | _______^
@ -79,7 +79,7 @@ LL | | b = t;
= note: or maybe you should use `std::mem::replace`? = note: or maybe you should use `std::mem::replace`?
error: this looks like you are swapping `c.0` and `a` manually error: this looks like you are swapping `c.0` and `a` manually
--> $DIR/swap.rs:147:7 --> $DIR/swap.rs:148:7
| |
LL | ; let t = c.0; LL | ; let t = c.0;
| _______^ | _______^
@ -90,7 +90,7 @@ LL | | a = t;
= note: or maybe you should use `std::mem::replace`? = note: or maybe you should use `std::mem::replace`?
error: this looks like you are swapping `b` and `a` manually error: this looks like you are swapping `b` and `a` manually
--> $DIR/swap.rs:173:5 --> $DIR/swap.rs:174:5
| |
LL | / let t = b; LL | / let t = b;
LL | | b = a; LL | | b = a;
@ -100,7 +100,7 @@ LL | | a = t;
= note: or maybe you should use `std::mem::replace`? = note: or maybe you should use `std::mem::replace`?
error: this looks like you are trying to swap `a` and `b` error: this looks like you are trying to swap `a` and `b`
--> $DIR/swap.rs:135:5 --> $DIR/swap.rs:136:5
| |
LL | / a = b; LL | / a = b;
LL | | b = a; LL | | b = a;
@ -110,7 +110,7 @@ LL | | b = a;
= note: `-D clippy::almost-swapped` implied by `-D warnings` = note: `-D clippy::almost-swapped` implied by `-D warnings`
error: this looks like you are trying to swap `c.0` and `a` error: this looks like you are trying to swap `c.0` and `a`
--> $DIR/swap.rs:144:5 --> $DIR/swap.rs:145:5
| |
LL | / c.0 = a; LL | / c.0 = a;
LL | | a = c.0; LL | | a = c.0;
@ -119,7 +119,7 @@ LL | | a = c.0;
= note: or maybe you should use `std::mem::replace`? = note: or maybe you should use `std::mem::replace`?
error: this looks like you are trying to swap `a` and `b` error: this looks like you are trying to swap `a` and `b`
--> $DIR/swap.rs:151:5 --> $DIR/swap.rs:152:5
| |
LL | / let a = b; LL | / let a = b;
LL | | let b = a; LL | | let b = a;
@ -128,7 +128,7 @@ LL | | let b = a;
= note: or maybe you should use `std::mem::replace`? = note: or maybe you should use `std::mem::replace`?
error: this looks like you are trying to swap `d` and `c` error: this looks like you are trying to swap `d` and `c`
--> $DIR/swap.rs:156:5 --> $DIR/swap.rs:157:5
| |
LL | / d = c; LL | / d = c;
LL | | c = d; LL | | c = d;
@ -137,7 +137,7 @@ LL | | c = d;
= note: or maybe you should use `std::mem::replace`? = note: or maybe you should use `std::mem::replace`?
error: this looks like you are trying to swap `a` and `b` error: this looks like you are trying to swap `a` and `b`
--> $DIR/swap.rs:160:5 --> $DIR/swap.rs:161:5
| |
LL | / let a = b; LL | / let a = b;
LL | | b = a; LL | | b = a;
@ -146,7 +146,7 @@ LL | | b = a;
= note: or maybe you should use `std::mem::replace`? = note: or maybe you should use `std::mem::replace`?
error: this looks like you are swapping `s.0.x` and `s.0.y` manually error: this looks like you are swapping `s.0.x` and `s.0.y` manually
--> $DIR/swap.rs:208:5 --> $DIR/swap.rs:209:5
| |
LL | / let t = s.0.x; LL | / let t = s.0.x;
LL | | s.0.x = s.0.y; LL | | s.0.x = s.0.y;