From 0063309a002b3436c2f924a6442739efd94aeb3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20CORTIER?= Date: Thu, 29 Jun 2017 13:45:35 +0200 Subject: [PATCH 1/9] Now register needless borrowed ref. --- clippy_lints/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index dc1b147351ae..68e63c33b631 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -267,6 +267,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_late_lint_pass(box mutex_atomic::MutexAtomic); reg.register_late_lint_pass(box needless_update::Pass); reg.register_late_lint_pass(box needless_borrow::NeedlessBorrow); + reg.register_late_lint_pass(box needless_borrowed_ref::NeedlessBorrowedRef); reg.register_late_lint_pass(box no_effect::Pass); reg.register_late_lint_pass(box map_clone::Pass); reg.register_late_lint_pass(box temporary_assignment::Pass); From 246045415593496d64fc0af41db7650b3680c1dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20CORTIER?= Date: Thu, 29 Jun 2017 13:45:54 +0200 Subject: [PATCH 2/9] Improve needless_borrowed_ref lint comments. --- clippy_lints/src/needless_borrowed_ref.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index 6f81c8114149..0167b1712971 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -48,11 +48,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrowedRef { if_let_chain! {[ // Pat is a pattern whose node - // is a binding which "involves" a immutable reference... + // is a binding which "involves" an immutable reference... let PatKind::Binding(BindingAnnotation::Ref, ..) = pat.node, // Pattern's type is a reference. Get the type and mutability of referenced value (tam: TypeAndMut). let ty::TyRef(_, ref tam) = cx.tables.pat_ty(pat).sty, - // This is an immutable reference. + // Only lint immutable refs, because `&mut ref T` may be useful. tam.mutbl == MutImmutable, ], { span_lint(cx, NEEDLESS_BORROWED_REFERENCE, pat.span, "this pattern takes a reference on something that is being de-referenced") From b1d93a595c4a9ea648fee189b13cbdea994f9826 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20CORTIER?= Date: Thu, 29 Jun 2017 13:46:07 +0200 Subject: [PATCH 3/9] Add needless_borrowed_ref example. --- clippy_tests/examples/needless_borrowed_ref.rs | 9 +++++++++ clippy_tests/examples/needless_borrowed_ref.stderr | 8 ++++++++ 2 files changed, 17 insertions(+) create mode 100644 clippy_tests/examples/needless_borrowed_ref.rs create mode 100644 clippy_tests/examples/needless_borrowed_ref.stderr diff --git a/clippy_tests/examples/needless_borrowed_ref.rs b/clippy_tests/examples/needless_borrowed_ref.rs new file mode 100644 index 000000000000..105a1fa48d41 --- /dev/null +++ b/clippy_tests/examples/needless_borrowed_ref.rs @@ -0,0 +1,9 @@ +#![feature(plugin)] +#![plugin(clippy)] + +#[warn(needless_borrowed_reference)] +fn main() { + let mut v = Vec::::new(); + let _ = v.iter_mut().filter(|&ref a| a.is_empty()); +} + diff --git a/clippy_tests/examples/needless_borrowed_ref.stderr b/clippy_tests/examples/needless_borrowed_ref.stderr new file mode 100644 index 000000000000..658318a3c6ab --- /dev/null +++ b/clippy_tests/examples/needless_borrowed_ref.stderr @@ -0,0 +1,8 @@ +warning: this pattern takes a reference on something that is being de-referenced + --> needless_borrowed_ref.rs:7:35 + | +7 | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); + | ^^^^^ + | + = note: #[warn(needless_borrowed_reference)] on by default + = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrowed_reference From d170e765de3d8f84dc2a6f918219c8efed01d862 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20CORTIER?= Date: Fri, 30 Jun 2017 16:07:29 +0200 Subject: [PATCH 4/9] Update needless_borrowed_ref lint example. --- .../examples/needless_borrowed_ref.rs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/clippy_tests/examples/needless_borrowed_ref.rs b/clippy_tests/examples/needless_borrowed_ref.rs index 105a1fa48d41..e463567ee6f0 100644 --- a/clippy_tests/examples/needless_borrowed_ref.rs +++ b/clippy_tests/examples/needless_borrowed_ref.rs @@ -2,8 +2,36 @@ #![plugin(clippy)] #[warn(needless_borrowed_reference)] +#[allow(unused_variables)] fn main() { let mut v = Vec::::new(); let _ = v.iter_mut().filter(|&ref a| a.is_empty()); + // ^ should be linted + + let mut var = 5; + let thingy = Some(&mut var); + if let Some(&mut ref v) = thingy { + // ^ should *not* be linted + // here, var is borrowed as immutable. + // can't do that: + //*v = 10; + } +} + +#[allow(dead_code)] +enum Animal { + Cat(u64), + Dog(u64), +} + +#[allow(unused_variables)] +#[allow(dead_code)] +fn foo(a: &Animal, b: &Animal) { + match (a, b) { + (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' + // ^ and ^ should *not* be linted + (&Animal::Dog(ref a), &Animal::Dog(_)) => () + // ^ should *not* be linted + } } From 60ca61ee660c156e0ff3fe0ee12a8156b5a425fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20CORTIER?= Date: Sat, 1 Jul 2017 12:01:39 +0200 Subject: [PATCH 5/9] Improve needless_borrowed_ref and add suggestion to it. --- clippy_lints/src/needless_borrowed_ref.rs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index 0167b1712971..db2c2cc95f86 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -3,9 +3,14 @@ //! This lint is **warn** by default use rustc::lint::*; +<<<<<<< HEAD use rustc::hir::{MutImmutable, Pat, PatKind, BindingAnnotation}; +======= +use rustc::hir::{MutImmutable, Pat, PatKind}; +>>>>>>> e30bf721... Improve needless_borrowed_ref and add suggestion to it. use rustc::ty; -use utils::{span_lint, in_macro}; +use utils::{span_lint_and_then, in_macro, snippet}; +use syntax_pos::{Span, BytePos}; /// **What it does:** Checks for useless borrowed references. /// @@ -53,9 +58,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrowedRef { // Pattern's type is a reference. Get the type and mutability of referenced value (tam: TypeAndMut). let ty::TyRef(_, ref tam) = cx.tables.pat_ty(pat).sty, // Only lint immutable refs, because `&mut ref T` may be useful. - tam.mutbl == MutImmutable, + let PatKind::Ref(ref sub_pat, MutImmutable) = pat.node, + + // Check sub_pat got a 'ref' keyword. + let ty::TyRef(_, _) = cx.tables.pat_ty(sub_pat).sty, ], { - span_lint(cx, NEEDLESS_BORROWED_REFERENCE, pat.span, "this pattern takes a reference on something that is being de-referenced") + let part_to_keep = Span{ lo: pat.span.lo + BytePos(5), hi: pat.span.hi, ctxt: pat.span.ctxt }; + span_lint_and_then(cx, NEEDLESS_BORROWED_REFERENCE, pat.span, + "this pattern takes a reference on something that is being de-referenced", + |db| { + let hint = snippet(cx, part_to_keep, "..").into_owned(); + db.span_suggestion(pat.span, "try removing the `&ref` part and just keep", hint); + }); }} } } From fe57fdd15e6046720463491359d32c5833ffad9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20CORTIER?= Date: Sat, 1 Jul 2017 12:02:00 +0200 Subject: [PATCH 6/9] Improve needless_borrowed_ref and update its stderr. --- .../examples/needless_borrowed_ref.rs | 21 ++++++--- .../examples/needless_borrowed_ref.stderr | 43 ++++++++++++++++--- 2 files changed, 54 insertions(+), 10 deletions(-) diff --git a/clippy_tests/examples/needless_borrowed_ref.rs b/clippy_tests/examples/needless_borrowed_ref.rs index e463567ee6f0..4e9986561bc1 100644 --- a/clippy_tests/examples/needless_borrowed_ref.rs +++ b/clippy_tests/examples/needless_borrowed_ref.rs @@ -8,13 +8,24 @@ fn main() { let _ = v.iter_mut().filter(|&ref a| a.is_empty()); // ^ should be linted - let mut var = 5; - let thingy = Some(&mut var); - if let Some(&mut ref v) = thingy { + let var = 3; + let thingy = Some(&var); + if let Some(&ref v) = thingy { + // ^ should be linted + } + + let mut var2 = 5; + let thingy2 = Some(&mut var2); + if let Some(&mut ref mut v) = thingy2 { // ^ should *not* be linted - // here, var is borrowed as immutable. + // v is borrowed as mutable. + *v = 10; + } + if let Some(&mut ref v) = thingy2 { + // ^ should *not* be linted + // here, v is borrowed as immutable. // can't do that: - //*v = 10; + //*v = 15; } } diff --git a/clippy_tests/examples/needless_borrowed_ref.stderr b/clippy_tests/examples/needless_borrowed_ref.stderr index 658318a3c6ab..a9befd5767c2 100644 --- a/clippy_tests/examples/needless_borrowed_ref.stderr +++ b/clippy_tests/examples/needless_borrowed_ref.stderr @@ -1,8 +1,41 @@ -warning: this pattern takes a reference on something that is being de-referenced - --> needless_borrowed_ref.rs:7:35 +error: this pattern takes a reference on something that is being de-referenced + --> examples/needless_borrowed_ref.rs:8:34 | -7 | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); - | ^^^^^ +8 | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); + | ^^^^^^ help: try removing the `&ref` part and just keep `a` | - = note: #[warn(needless_borrowed_reference)] on by default + = note: `-D needless-borrowed-reference` implied by `-D warnings` = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrowed_reference + +error: this pattern takes a reference on something that is being de-referenced + --> examples/needless_borrowed_ref.rs:13:17 + | +13 | if let Some(&ref v) = thingy { + | ^^^^^^ help: try removing the `&ref` part and just keep `v` + | + = note: `-D needless-borrowed-reference` implied by `-D warnings` + = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrowed_reference + +error: this pattern takes a reference on something that is being de-referenced + --> examples/needless_borrowed_ref.rs:42:27 + | +42 | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' + | ^^^^^^ help: try removing the `&ref` part and just keep `k` + | + = note: `-D needless-borrowed-reference` implied by `-D warnings` + = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrowed_reference + +error: this pattern takes a reference on something that is being de-referenced + --> examples/needless_borrowed_ref.rs:42:38 + | +42 | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' + | ^^^^^^ help: try removing the `&ref` part and just keep `k` + | + = note: `-D needless-borrowed-reference` implied by `-D warnings` + = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrowed_reference + +error: aborting due to previous error(s) + +error: Could not compile `clippy_tests`. + +To learn more, run the command again with --verbose. From c00393163cf1aae888b654a46b5f400e2ded4d1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20CORTIER?= Date: Sat, 1 Jul 2017 16:56:19 +0200 Subject: [PATCH 7/9] Improve needless_borrowed_ref lint: remove the hand rolled span part. --- clippy_lints/src/needless_borrowed_ref.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index db2c2cc95f86..6e17d23fb0bb 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -7,10 +7,13 @@ use rustc::lint::*; use rustc::hir::{MutImmutable, Pat, PatKind, BindingAnnotation}; ======= use rustc::hir::{MutImmutable, Pat, PatKind}; +<<<<<<< HEAD >>>>>>> e30bf721... Improve needless_borrowed_ref and add suggestion to it. use rustc::ty; +======= +>>>>>>> 4ae45c87... Improve needless_borrowed_ref lint: remove the hand rolled span part. use utils::{span_lint_and_then, in_macro, snippet}; -use syntax_pos::{Span, BytePos}; +use rustc::hir::BindingMode::BindByRef; /// **What it does:** Checks for useless borrowed references. /// @@ -60,14 +63,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrowedRef { // Only lint immutable refs, because `&mut ref T` may be useful. let PatKind::Ref(ref sub_pat, MutImmutable) = pat.node, - // Check sub_pat got a 'ref' keyword. - let ty::TyRef(_, _) = cx.tables.pat_ty(sub_pat).sty, + // Check sub_pat got a `ref` keyword (excluding `ref mut`). + let PatKind::Binding(BindByRef(MutImmutable), _, spanned_name, ..) = sub_pat.node, ], { - let part_to_keep = Span{ lo: pat.span.lo + BytePos(5), hi: pat.span.hi, ctxt: pat.span.ctxt }; span_lint_and_then(cx, NEEDLESS_BORROWED_REFERENCE, pat.span, "this pattern takes a reference on something that is being de-referenced", |db| { - let hint = snippet(cx, part_to_keep, "..").into_owned(); + let hint = snippet(cx, spanned_name.span, "..").into_owned(); db.span_suggestion(pat.span, "try removing the `&ref` part and just keep", hint); }); }} From ee2f54723ae8122b7f7e5cfca48f3f85f7d656ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20CORTIER?= Date: Sat, 1 Jul 2017 18:51:20 +0200 Subject: [PATCH 8/9] Finalize needless_borrowed_ref lint doc. Make sure the needless_borrowed_ref.stderr in examples is up to date too. --- clippy_lints/src/needless_borrowed_ref.rs | 33 ++++++++++++------- .../examples/needless_borrowed_ref.stderr | 11 +++---- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index 6e17d23fb0bb..1451b19aecad 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -3,25 +3,33 @@ //! This lint is **warn** by default use rustc::lint::*; -<<<<<<< HEAD -use rustc::hir::{MutImmutable, Pat, PatKind, BindingAnnotation}; -======= -use rustc::hir::{MutImmutable, Pat, PatKind}; -<<<<<<< HEAD ->>>>>>> e30bf721... Improve needless_borrowed_ref and add suggestion to it. +use rustc::hir::{MutImmutable, Pat, PatKind, BindByRef}; use rustc::ty; -======= ->>>>>>> 4ae45c87... Improve needless_borrowed_ref lint: remove the hand rolled span part. use utils::{span_lint_and_then, in_macro, snippet}; -use rustc::hir::BindingMode::BindByRef; /// **What it does:** Checks for useless borrowed references. /// -/// **Why is this bad?** It is completely useless and make the code look more -/// complex than it +/// **Why is this bad?** It is mostly useless and make the code look more complex than it /// actually is. /// -/// **Known problems:** None. +/// **Known problems:** It seems that the `&ref` pattern is sometimes useful. +/// For instance in the following snippet: +/// ```rust +/// enum Animal { +/// Cat(u64), +/// Dog(u64), +/// } +/// +/// fn foo(a: &Animal, b: &Animal) { +/// match (a, b) { +/// (&Animal::Cat(v), k) | (k, &Animal::Cat(v)) => (), // lifetime mismatch error +/// (&Animal::Dog(ref c), &Animal::Dog(_)) => () +/// } +/// } +/// ``` +/// There is a lifetime mismatch error for `k` (indeed a and b have distinct lifetime). +/// This can be fixed by using the `&ref` pattern. +/// However, the code can also be fixed by much cleaner ways /// /// **Example:** /// ```rust @@ -75,3 +83,4 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrowedRef { }} } } + diff --git a/clippy_tests/examples/needless_borrowed_ref.stderr b/clippy_tests/examples/needless_borrowed_ref.stderr index a9befd5767c2..2b506af88f5a 100644 --- a/clippy_tests/examples/needless_borrowed_ref.stderr +++ b/clippy_tests/examples/needless_borrowed_ref.stderr @@ -1,5 +1,5 @@ error: this pattern takes a reference on something that is being de-referenced - --> examples/needless_borrowed_ref.rs:8:34 + --> needless_borrowed_ref.rs:8:34 | 8 | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); | ^^^^^^ help: try removing the `&ref` part and just keep `a` @@ -8,30 +8,27 @@ error: this pattern takes a reference on something that is being de-referenced = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrowed_reference error: this pattern takes a reference on something that is being de-referenced - --> examples/needless_borrowed_ref.rs:13:17 + --> needless_borrowed_ref.rs:13:17 | 13 | if let Some(&ref v) = thingy { | ^^^^^^ help: try removing the `&ref` part and just keep `v` | - = note: `-D needless-borrowed-reference` implied by `-D warnings` = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrowed_reference error: this pattern takes a reference on something that is being de-referenced - --> examples/needless_borrowed_ref.rs:42:27 + --> needless_borrowed_ref.rs:42:27 | 42 | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' | ^^^^^^ help: try removing the `&ref` part and just keep `k` | - = note: `-D needless-borrowed-reference` implied by `-D warnings` = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrowed_reference error: this pattern takes a reference on something that is being de-referenced - --> examples/needless_borrowed_ref.rs:42:38 + --> needless_borrowed_ref.rs:42:38 | 42 | (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref' | ^^^^^^ help: try removing the `&ref` part and just keep `k` | - = note: `-D needless-borrowed-reference` implied by `-D warnings` = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_borrowed_reference error: aborting due to previous error(s) From c3ef220bba7521427016f7422994cb8dfa24e1f2 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 21 Aug 2017 14:22:41 +0200 Subject: [PATCH 9/9] Rebase and update ui test --- clippy_lints/src/needless_borrowed_ref.rs | 10 ++-------- tests/ui/needless_borrow.stderr | 16 +++++++++++++++- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index 1451b19aecad..3f7ccca23b42 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -3,8 +3,7 @@ //! This lint is **warn** by default use rustc::lint::*; -use rustc::hir::{MutImmutable, Pat, PatKind, BindByRef}; -use rustc::ty; +use rustc::hir::{MutImmutable, Pat, PatKind, BindingAnnotation}; use utils::{span_lint_and_then, in_macro, snippet}; /// **What it does:** Checks for useless borrowed references. @@ -63,16 +62,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrowedRef { } if_let_chain! {[ - // Pat is a pattern whose node - // is a binding which "involves" an immutable reference... - let PatKind::Binding(BindingAnnotation::Ref, ..) = pat.node, - // Pattern's type is a reference. Get the type and mutability of referenced value (tam: TypeAndMut). - let ty::TyRef(_, ref tam) = cx.tables.pat_ty(pat).sty, // Only lint immutable refs, because `&mut ref T` may be useful. let PatKind::Ref(ref sub_pat, MutImmutable) = pat.node, // Check sub_pat got a `ref` keyword (excluding `ref mut`). - let PatKind::Binding(BindByRef(MutImmutable), _, spanned_name, ..) = sub_pat.node, + let PatKind::Binding(BindingAnnotation::Ref, _, spanned_name, ..) = sub_pat.node, ], { span_lint_and_then(cx, NEEDLESS_BORROWED_REFERENCE, pat.span, "this pattern takes a reference on something that is being de-referenced", diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr index cc5b1b6c33c6..d90c396645e9 100644 --- a/tests/ui/needless_borrow.stderr +++ b/tests/ui/needless_borrow.stderr @@ -18,11 +18,25 @@ error: this expression borrows a reference that is immediately dereferenced by t 27 | 46 => &&a, | ^^^ +error: this pattern takes a reference on something that is being de-referenced + --> $DIR/needless_borrow.rs:49:34 + | +49 | let _ = v.iter_mut().filter(|&ref a| a.is_empty()); + | ^^^^^^ help: try removing the `&ref` part and just keep: `a` + | + = note: `-D needless-borrowed-reference` implied by `-D warnings` + +error: this pattern takes a reference on something that is being de-referenced + --> $DIR/needless_borrow.rs:50:30 + | +50 | let _ = v.iter().filter(|&ref a| a.is_empty()); + | ^^^^^^ help: try removing the `&ref` part and just keep: `a` + error: this pattern creates a reference to a reference --> $DIR/needless_borrow.rs:50:31 | 50 | let _ = v.iter().filter(|&ref a| a.is_empty()); | ^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 6 previous errors