From 33ec4e4bb0e332072b5dbd31f8f024dff4e3f44e Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 24 May 2023 16:05:42 +0000 Subject: [PATCH 1/3] make `noop_method_call` warn by default --- compiler/rustc_lint/src/noop_method_call.rs | 3 +-- tests/ui/issues/issue-11820.rs | 2 ++ tests/ui/lint/noop-method-call.rs | 1 - tests/ui/lint/noop-method-call.stderr | 22 +++++++++------------ tests/ui/underscore-imports/cycle.rs | 2 ++ tests/ui/underscore-imports/hygiene.rs | 1 + 6 files changed, 15 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs index 13f650c200826..2817a665bb0a8 100644 --- a/compiler/rustc_lint/src/noop_method_call.rs +++ b/compiler/rustc_lint/src/noop_method_call.rs @@ -18,7 +18,6 @@ declare_lint! { /// /// ```rust /// # #![allow(unused)] - /// #![warn(noop_method_call)] /// struct Foo; /// let foo = &Foo; /// let clone: &Foo = foo.clone(); @@ -34,7 +33,7 @@ declare_lint! { /// calling `clone` on a `&T` where `T` does not implement clone, actually doesn't do anything /// as references are copy. This lint detects these calls and warns the user about them. pub NOOP_METHOD_CALL, - Allow, + Warn, "detects the use of well-known noop methods" } diff --git a/tests/ui/issues/issue-11820.rs b/tests/ui/issues/issue-11820.rs index 7ffe9652797cf..dc6349b10ee58 100644 --- a/tests/ui/issues/issue-11820.rs +++ b/tests/ui/issues/issue-11820.rs @@ -1,6 +1,8 @@ // run-pass // pretty-expanded FIXME #23616 +#![allow(noop_method_call)] + struct NoClone; fn main() { diff --git a/tests/ui/lint/noop-method-call.rs b/tests/ui/lint/noop-method-call.rs index dbcf2a5131b5b..8ce6c859b2480 100644 --- a/tests/ui/lint/noop-method-call.rs +++ b/tests/ui/lint/noop-method-call.rs @@ -1,7 +1,6 @@ // check-pass #![allow(unused)] -#![warn(noop_method_call)] use std::borrow::Borrow; use std::ops::Deref; diff --git a/tests/ui/lint/noop-method-call.stderr b/tests/ui/lint/noop-method-call.stderr index 37cd1a0fc18ea..ae61913f99381 100644 --- a/tests/ui/lint/noop-method-call.stderr +++ b/tests/ui/lint/noop-method-call.stderr @@ -1,18 +1,14 @@ warning: call to `.clone()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:16:71 + --> $DIR/noop-method-call.rs:15:71 | LL | let non_clone_type_ref_clone: &PlainType = non_clone_type_ref.clone(); | ^^^^^^^^ unnecessary method call | = note: the type `&PlainType` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed -note: the lint level is defined here - --> $DIR/noop-method-call.rs:4:9 - | -LL | #![warn(noop_method_call)] - | ^^^^^^^^^^^^^^^^ + = note: `#[warn(noop_method_call)]` on by default warning: using `.clone()` on a double reference, which returns `&CloneType` instead of cloning the inner type - --> $DIR/noop-method-call.rs:23:63 + --> $DIR/noop-method-call.rs:22:63 | LL | let clone_type_ref_clone: &CloneType = clone_type_ref.clone(); | ^^^^^^^^ @@ -20,7 +16,7 @@ LL | let clone_type_ref_clone: &CloneType = clone_type_ref.clone(); = note: `#[warn(suspicious_double_ref_op)]` on by default warning: call to `.deref()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:27:63 + --> $DIR/noop-method-call.rs:26:63 | LL | let non_deref_type_deref: &PlainType = non_deref_type.deref(); | ^^^^^^^^ unnecessary method call @@ -28,13 +24,13 @@ LL | let non_deref_type_deref: &PlainType = non_deref_type.deref(); = note: the type `&PlainType` which `deref` is being called on is the same as the type returned from `deref`, so the method call does not do anything and can be removed warning: using `.deref()` on a double reference, which returns `&PlainType` instead of dereferencing the inner type - --> $DIR/noop-method-call.rs:31:63 + --> $DIR/noop-method-call.rs:30:63 | LL | let non_deref_type_deref: &PlainType = non_deref_type.deref(); | ^^^^^^^^ warning: call to `.borrow()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:35:66 + --> $DIR/noop-method-call.rs:34:66 | LL | let non_borrow_type_borrow: &PlainType = non_borrow_type.borrow(); | ^^^^^^^^^ unnecessary method call @@ -42,13 +38,13 @@ LL | let non_borrow_type_borrow: &PlainType = non_borrow_type.borrow(); = note: the type `&PlainType` which `borrow` is being called on is the same as the type returned from `borrow`, so the method call does not do anything and can be removed warning: using `.clone()` on a double reference, which returns `&str` instead of cloning the inner type - --> $DIR/noop-method-call.rs:43:44 + --> $DIR/noop-method-call.rs:42:44 | LL | let _v: Vec<&str> = xs.iter().map(|x| x.clone()).collect(); // could use `*x` instead | ^^^^^^^^ warning: call to `.clone()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:48:19 + --> $DIR/noop-method-call.rs:47:19 | LL | non_clone_type.clone(); | ^^^^^^^^ unnecessary method call @@ -56,7 +52,7 @@ LL | non_clone_type.clone(); = note: the type `&PlainType` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed warning: call to `.clone()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:53:19 + --> $DIR/noop-method-call.rs:52:19 | LL | non_clone_type.clone(); | ^^^^^^^^ unnecessary method call diff --git a/tests/ui/underscore-imports/cycle.rs b/tests/ui/underscore-imports/cycle.rs index bacf9b2d5a96a..c8a293687878f 100644 --- a/tests/ui/underscore-imports/cycle.rs +++ b/tests/ui/underscore-imports/cycle.rs @@ -2,6 +2,8 @@ // check-pass +#![allow(noop_method_call)] + mod x { pub use crate::y::*; pub use std::ops::Deref as _; diff --git a/tests/ui/underscore-imports/hygiene.rs b/tests/ui/underscore-imports/hygiene.rs index c4db65245386f..7795ccb797199 100644 --- a/tests/ui/underscore-imports/hygiene.rs +++ b/tests/ui/underscore-imports/hygiene.rs @@ -3,6 +3,7 @@ // check-pass #![feature(decl_macro)] +#![allow(noop_method_call)] mod x { pub use std::ops::Deref as _; From 626efab67f184658eb966d3a69c31d7f1deb47e4 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Thu, 25 May 2023 05:21:44 +0000 Subject: [PATCH 2/3] fix --- compiler/rustc_lint/messages.ftl | 2 +- compiler/rustc_lint/src/lints.rs | 3 ++- compiler/rustc_lint/src/noop_method_call.rs | 11 +++++---- .../src/traits/error_reporting/suggestions.rs | 3 +-- library/core/benches/iter.rs | 1 + .../tests/ui/explicit_deref_methods.fixed | 1 + .../clippy/tests/ui/explicit_deref_methods.rs | 1 + .../tests/ui/explicit_deref_methods.stderr | 24 +++++++++---------- src/tools/compiletest/src/lib.rs | 2 +- tests/ui/lint/noop-method-call.stderr | 10 ++++---- tests/ui/lint/suspicious-double-ref-op.stderr | 4 ++-- 11 files changed, 33 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 2c92277b50d21..598373a8301e2 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -413,7 +413,7 @@ lint_non_upper_case_global = {$sort} `{$name}` should have an upper case name lint_noop_method_call = call to `.{$method}()` on a reference in this situation does nothing .label = unnecessary method call - .note = the type `{$receiver_ty}` which `{$method}` is being called on is the same as the type returned from `{$method}`, so the method call does not do anything and can be removed + .note = the type `{$orig_ty}` does not implement `{$trait_}`, so calling `{$method}` on `&{$orig_ty}` copies the reference, which does not do anything and can be removed lint_only_cast_u8_to_char = only `u8` can be cast into `char` .suggestion = use a `char` literal instead diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 1dea758bb294b..322a3b6583dd1 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1231,7 +1231,8 @@ pub enum NonUpperCaseGlobalSub { #[note] pub struct NoopMethodCallDiag<'a> { pub method: Symbol, - pub receiver_ty: Ty<'a>, + pub orig_ty: Ty<'a>, + pub trait_: Symbol, #[label] pub label: Span, } diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs index 2817a665bb0a8..bc0b9d6d81871 100644 --- a/compiler/rustc_lint/src/noop_method_call.rs +++ b/compiler/rustc_lint/src/noop_method_call.rs @@ -85,10 +85,9 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall { let Some(trait_id) = cx.tcx.trait_of_item(did) else { return }; - if !matches!( - cx.tcx.get_diagnostic_name(trait_id), - Some(sym::Borrow | sym::Clone | sym::Deref) - ) { + let Some(trait_) = cx.tcx.get_diagnostic_name(trait_id) else { return }; + + if !matches!(trait_, sym::Borrow | sym::Clone | sym::Deref) { return; }; @@ -113,11 +112,13 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall { let expr_span = expr.span; let span = expr_span.with_lo(receiver.span.hi()); + let orig_ty = expr_ty.peel_refs(); + if receiver_ty == expr_ty { cx.emit_spanned_lint( NOOP_METHOD_CALL, span, - NoopMethodCallDiag { method: call.ident.name, receiver_ty, label: span }, + NoopMethodCallDiag { method: call.ident.name, orig_ty, trait_, label: span }, ); } else { match name { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 05d2934d4c53b..52484413f76b9 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -41,7 +41,6 @@ use rustc_span::{BytePos, DesugaringKind, ExpnKind, MacroKind, Span, DUMMY_SP}; use rustc_target::spec::abi; use std::borrow::Cow; use std::iter; -use std::ops::Deref; use super::InferCtxtPrivExt; use crate::infer::InferCtxtExt as _; @@ -3580,7 +3579,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // to an associated type (as seen from `trait_pred`) in the predicate. Like in // trait_pred `S: Sum<::Item>` and predicate `i32: Sum<&()>` let mut type_diffs = vec![]; - if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = parent_code.deref() + if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = parent_code && let Some(node_args) = typeck_results.node_args_opt(call_hir_id) && let where_clauses = self.tcx.predicates_of(def_id).instantiate(self.tcx, node_args) && let Some(where_pred) = where_clauses.predicates.get(*idx) diff --git a/library/core/benches/iter.rs b/library/core/benches/iter.rs index 5ec22e5147b16..05fec0c4b9d26 100644 --- a/library/core/benches/iter.rs +++ b/library/core/benches/iter.rs @@ -473,6 +473,7 @@ fn bench_next_chunk_copied(b: &mut Bencher) { /// Exercises the TrustedRandomAccess specialization in ArrayChunks #[bench] +#[allow(noop_method_call)] fn bench_next_chunk_trusted_random_access(b: &mut Bencher) { let v = vec![1u8; 1024]; diff --git a/src/tools/clippy/tests/ui/explicit_deref_methods.fixed b/src/tools/clippy/tests/ui/explicit_deref_methods.fixed index 4d72b58cdf867..4c0b0d8f275e0 100644 --- a/src/tools/clippy/tests/ui/explicit_deref_methods.fixed +++ b/src/tools/clippy/tests/ui/explicit_deref_methods.fixed @@ -4,6 +4,7 @@ #![allow( clippy::borrow_deref_ref, suspicious_double_ref_op, + noop_method_call, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::no_effect, diff --git a/src/tools/clippy/tests/ui/explicit_deref_methods.rs b/src/tools/clippy/tests/ui/explicit_deref_methods.rs index fcd945de33860..bc5da35e52e3f 100644 --- a/src/tools/clippy/tests/ui/explicit_deref_methods.rs +++ b/src/tools/clippy/tests/ui/explicit_deref_methods.rs @@ -4,6 +4,7 @@ #![allow( clippy::borrow_deref_ref, suspicious_double_ref_op, + noop_method_call, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::no_effect, diff --git a/src/tools/clippy/tests/ui/explicit_deref_methods.stderr b/src/tools/clippy/tests/ui/explicit_deref_methods.stderr index 362e559b21a57..e4d2fe3a1c3d5 100644 --- a/src/tools/clippy/tests/ui/explicit_deref_methods.stderr +++ b/src/tools/clippy/tests/ui/explicit_deref_methods.stderr @@ -1,5 +1,5 @@ error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:54:19 + --> $DIR/explicit_deref_methods.rs:55:19 | LL | let b: &str = a.deref(); | ^^^^^^^^^ help: try: `&*a` @@ -7,67 +7,67 @@ LL | let b: &str = a.deref(); = note: `-D clippy::explicit-deref-methods` implied by `-D warnings` error: explicit `deref_mut` method call - --> $DIR/explicit_deref_methods.rs:56:23 + --> $DIR/explicit_deref_methods.rs:57:23 | LL | let b: &mut str = a.deref_mut(); | ^^^^^^^^^^^^^ help: try: `&mut **a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:59:39 + --> $DIR/explicit_deref_methods.rs:60:39 | LL | let b: String = format!("{}, {}", a.deref(), a.deref()); | ^^^^^^^^^ help: try: `&*a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:59:50 + --> $DIR/explicit_deref_methods.rs:60:50 | LL | let b: String = format!("{}, {}", a.deref(), a.deref()); | ^^^^^^^^^ help: try: `&*a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:61:20 + --> $DIR/explicit_deref_methods.rs:62:20 | LL | println!("{}", a.deref()); | ^^^^^^^^^ help: try: `&*a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:64:11 + --> $DIR/explicit_deref_methods.rs:65:11 | LL | match a.deref() { | ^^^^^^^^^ help: try: `&*a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:68:28 + --> $DIR/explicit_deref_methods.rs:69:28 | LL | let b: String = concat(a.deref()); | ^^^^^^^^^ help: try: `&*a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:70:13 + --> $DIR/explicit_deref_methods.rs:71:13 | LL | let b = just_return(a).deref(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `just_return(a)` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:72:28 + --> $DIR/explicit_deref_methods.rs:73:28 | LL | let b: String = concat(just_return(a).deref()); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `just_return(a)` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:74:19 + --> $DIR/explicit_deref_methods.rs:75:19 | LL | let b: &str = a.deref().deref(); | ^^^^^^^^^^^^^^^^^ help: try: `&**a` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:77:13 + --> $DIR/explicit_deref_methods.rs:78:13 | LL | let b = opt_a.unwrap().deref(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*opt_a.unwrap()` error: explicit `deref` method call - --> $DIR/explicit_deref_methods.rs:114:31 + --> $DIR/explicit_deref_methods.rs:115:31 | LL | let b: &str = expr_deref!(a.deref()); | ^^^^^^^^^ help: try: `&*a` diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index fc48d0159905b..1a765477fe501 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -1119,7 +1119,7 @@ fn check_overlapping_tests(found_paths: &BTreeSet) { for path in found_paths { for ancestor in path.ancestors().skip(1) { if found_paths.contains(ancestor) { - collisions.push((path, ancestor.clone())); + collisions.push((path, ancestor)); } } } diff --git a/tests/ui/lint/noop-method-call.stderr b/tests/ui/lint/noop-method-call.stderr index ae61913f99381..fb02c6f361e0a 100644 --- a/tests/ui/lint/noop-method-call.stderr +++ b/tests/ui/lint/noop-method-call.stderr @@ -4,7 +4,7 @@ warning: call to `.clone()` on a reference in this situation does nothing LL | let non_clone_type_ref_clone: &PlainType = non_clone_type_ref.clone(); | ^^^^^^^^ unnecessary method call | - = note: the type `&PlainType` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed + = note: the type `PlainType` does not implement `Clone`, so calling `clone` on `&PlainType` copies the reference, which does not do anything and can be removed = note: `#[warn(noop_method_call)]` on by default warning: using `.clone()` on a double reference, which returns `&CloneType` instead of cloning the inner type @@ -21,7 +21,7 @@ warning: call to `.deref()` on a reference in this situation does nothing LL | let non_deref_type_deref: &PlainType = non_deref_type.deref(); | ^^^^^^^^ unnecessary method call | - = note: the type `&PlainType` which `deref` is being called on is the same as the type returned from `deref`, so the method call does not do anything and can be removed + = note: the type `PlainType` does not implement `Deref`, so calling `deref` on `&PlainType` copies the reference, which does not do anything and can be removed warning: using `.deref()` on a double reference, which returns `&PlainType` instead of dereferencing the inner type --> $DIR/noop-method-call.rs:30:63 @@ -35,7 +35,7 @@ warning: call to `.borrow()` on a reference in this situation does nothing LL | let non_borrow_type_borrow: &PlainType = non_borrow_type.borrow(); | ^^^^^^^^^ unnecessary method call | - = note: the type `&PlainType` which `borrow` is being called on is the same as the type returned from `borrow`, so the method call does not do anything and can be removed + = note: the type `PlainType` does not implement `Borrow`, so calling `borrow` on `&PlainType` copies the reference, which does not do anything and can be removed warning: using `.clone()` on a double reference, which returns `&str` instead of cloning the inner type --> $DIR/noop-method-call.rs:42:44 @@ -49,7 +49,7 @@ warning: call to `.clone()` on a reference in this situation does nothing LL | non_clone_type.clone(); | ^^^^^^^^ unnecessary method call | - = note: the type `&PlainType` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed + = note: the type `PlainType` does not implement `Clone`, so calling `clone` on `&PlainType` copies the reference, which does not do anything and can be removed warning: call to `.clone()` on a reference in this situation does nothing --> $DIR/noop-method-call.rs:52:19 @@ -57,7 +57,7 @@ warning: call to `.clone()` on a reference in this situation does nothing LL | non_clone_type.clone(); | ^^^^^^^^ unnecessary method call | - = note: the type `&PlainType` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed + = note: the type `PlainType` does not implement `Clone`, so calling `clone` on `&PlainType` copies the reference, which does not do anything and can be removed warning: 8 warnings emitted diff --git a/tests/ui/lint/suspicious-double-ref-op.stderr b/tests/ui/lint/suspicious-double-ref-op.stderr index d15487ca23865..f2128f2a0edad 100644 --- a/tests/ui/lint/suspicious-double-ref-op.stderr +++ b/tests/ui/lint/suspicious-double-ref-op.stderr @@ -16,7 +16,7 @@ error: call to `.clone()` on a reference in this situation does nothing LL | let _ = &mut encoded.clone(); | ^^^^^^^^ unnecessary method call | - = note: the type `&[u8]` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed + = note: the type `[u8]` does not implement `Clone`, so calling `clone` on `&[u8]` copies the reference, which does not do anything and can be removed note: the lint level is defined here --> $DIR/suspicious-double-ref-op.rs:2:35 | @@ -29,7 +29,7 @@ error: call to `.clone()` on a reference in this situation does nothing LL | let _ = &encoded.clone(); | ^^^^^^^^ unnecessary method call | - = note: the type `&[u8]` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed + = note: the type `[u8]` does not implement `Clone`, so calling `clone` on `&[u8]` copies the reference, which does not do anything and can be removed error: aborting due to 3 previous errors From 2a76c570d6115230af9df0888a721de9fb2c88bc Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sun, 23 Jul 2023 09:56:56 +0000 Subject: [PATCH 3/3] add suggestion --- compiler/rustc_lint/messages.ftl | 2 +- compiler/rustc_lint/src/lints.rs | 2 +- tests/ui/lint/noop-method-call.fixed | 51 +++++++++++++++++ tests/ui/lint/noop-method-call.rs | 29 +++++----- tests/ui/lint/noop-method-call.stderr | 56 +++++++++---------- tests/ui/lint/suspicious-double-ref-op.rs | 27 ++++++--- tests/ui/lint/suspicious-double-ref-op.stderr | 33 +++++------ 7 files changed, 127 insertions(+), 73 deletions(-) create mode 100644 tests/ui/lint/noop-method-call.fixed diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 598373a8301e2..797504c0e8e47 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -412,7 +412,7 @@ lint_non_upper_case_global = {$sort} `{$name}` should have an upper case name .label = should have an UPPER_CASE name lint_noop_method_call = call to `.{$method}()` on a reference in this situation does nothing - .label = unnecessary method call + .suggestion = remove this redundant call .note = the type `{$orig_ty}` does not implement `{$trait_}`, so calling `{$method}` on `&{$orig_ty}` copies the reference, which does not do anything and can be removed lint_only_cast_u8_to_char = only `u8` can be cast into `char` diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 322a3b6583dd1..981b39ba1c8fd 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1233,7 +1233,7 @@ pub struct NoopMethodCallDiag<'a> { pub method: Symbol, pub orig_ty: Ty<'a>, pub trait_: Symbol, - #[label] + #[suggestion(code = "", applicability = "machine-applicable")] pub label: Span, } diff --git a/tests/ui/lint/noop-method-call.fixed b/tests/ui/lint/noop-method-call.fixed new file mode 100644 index 0000000000000..eeb80279fd816 --- /dev/null +++ b/tests/ui/lint/noop-method-call.fixed @@ -0,0 +1,51 @@ +// check-pass +// run-rustfix + +#![allow(unused)] + +use std::borrow::Borrow; +use std::ops::Deref; + +struct PlainType(T); + +#[derive(Clone)] +struct CloneType(T); + +fn check(mut encoded: &[u8]) { + let _ = &mut encoded; + //~^ WARN call to `.clone()` on a reference in this situation does nothing + let _ = &encoded; + //~^ WARN call to `.clone()` on a reference in this situation does nothing +} + +fn main() { + let non_clone_type_ref = &PlainType(1u32); + let non_clone_type_ref_clone: &PlainType = non_clone_type_ref; + //~^ WARN call to `.clone()` on a reference in this situation does nothing + + let clone_type_ref = &CloneType(1u32); + let clone_type_ref_clone: CloneType = clone_type_ref.clone(); + + + let non_deref_type = &PlainType(1u32); + let non_deref_type_deref: &PlainType = non_deref_type; + //~^ WARN call to `.deref()` on a reference in this situation does nothing + + let non_borrow_type = &PlainType(1u32); + let non_borrow_type_borrow: &PlainType = non_borrow_type; + //~^ WARN call to `.borrow()` on a reference in this situation does nothing + + // Borrowing a &&T does not warn since it has collapsed the double reference + let non_borrow_type = &&PlainType(1u32); + let non_borrow_type_borrow: &PlainType = non_borrow_type.borrow(); +} + +fn generic(non_clone_type: &PlainType) { + non_clone_type; + //~^ WARN call to `.clone()` on a reference in this situation does nothing +} + +fn non_generic(non_clone_type: &PlainType) { + non_clone_type; + //~^ WARN call to `.clone()` on a reference in this situation does nothing +} diff --git a/tests/ui/lint/noop-method-call.rs b/tests/ui/lint/noop-method-call.rs index 8ce6c859b2480..9569a0dfc617e 100644 --- a/tests/ui/lint/noop-method-call.rs +++ b/tests/ui/lint/noop-method-call.rs @@ -1,4 +1,5 @@ // check-pass +// run-rustfix #![allow(unused)] @@ -10,45 +11,41 @@ struct PlainType(T); #[derive(Clone)] struct CloneType(T); +fn check(mut encoded: &[u8]) { + let _ = &mut encoded.clone(); + //~^ WARN call to `.clone()` on a reference in this situation does nothing + let _ = &encoded.clone(); + //~^ WARN call to `.clone()` on a reference in this situation does nothing +} + fn main() { let non_clone_type_ref = &PlainType(1u32); let non_clone_type_ref_clone: &PlainType = non_clone_type_ref.clone(); - //~^ WARNING call to `.clone()` on a reference in this situation does nothing + //~^ WARN call to `.clone()` on a reference in this situation does nothing let clone_type_ref = &CloneType(1u32); let clone_type_ref_clone: CloneType = clone_type_ref.clone(); - let clone_type_ref = &&CloneType(1u32); - let clone_type_ref_clone: &CloneType = clone_type_ref.clone(); - //~^ WARNING using `.clone()` on a double reference, which returns `&CloneType` let non_deref_type = &PlainType(1u32); let non_deref_type_deref: &PlainType = non_deref_type.deref(); - //~^ WARNING call to `.deref()` on a reference in this situation does nothing - - let non_deref_type = &&PlainType(1u32); - let non_deref_type_deref: &PlainType = non_deref_type.deref(); - //~^ WARNING using `.deref()` on a double reference, which returns `&PlainType` + //~^ WARN call to `.deref()` on a reference in this situation does nothing let non_borrow_type = &PlainType(1u32); let non_borrow_type_borrow: &PlainType = non_borrow_type.borrow(); - //~^ WARNING call to `.borrow()` on a reference in this situation does nothing + //~^ WARN call to `.borrow()` on a reference in this situation does nothing // Borrowing a &&T does not warn since it has collapsed the double reference let non_borrow_type = &&PlainType(1u32); let non_borrow_type_borrow: &PlainType = non_borrow_type.borrow(); - - let xs = ["a", "b", "c"]; - let _v: Vec<&str> = xs.iter().map(|x| x.clone()).collect(); // could use `*x` instead - //~^ WARNING using `.clone()` on a double reference, which returns `&str` } fn generic(non_clone_type: &PlainType) { non_clone_type.clone(); - //~^ WARNING call to `.clone()` on a reference in this situation does nothing + //~^ WARN call to `.clone()` on a reference in this situation does nothing } fn non_generic(non_clone_type: &PlainType) { non_clone_type.clone(); - //~^ WARNING call to `.clone()` on a reference in this situation does nothing + //~^ WARN call to `.clone()` on a reference in this situation does nothing } diff --git a/tests/ui/lint/noop-method-call.stderr b/tests/ui/lint/noop-method-call.stderr index fb02c6f361e0a..aefc2706fd529 100644 --- a/tests/ui/lint/noop-method-call.stderr +++ b/tests/ui/lint/noop-method-call.stderr @@ -1,63 +1,59 @@ warning: call to `.clone()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:15:71 + --> $DIR/noop-method-call.rs:15:25 | -LL | let non_clone_type_ref_clone: &PlainType = non_clone_type_ref.clone(); - | ^^^^^^^^ unnecessary method call +LL | let _ = &mut encoded.clone(); + | ^^^^^^^^ help: remove this redundant call | - = note: the type `PlainType` does not implement `Clone`, so calling `clone` on `&PlainType` copies the reference, which does not do anything and can be removed + = note: the type `[u8]` does not implement `Clone`, so calling `clone` on `&[u8]` copies the reference, which does not do anything and can be removed = note: `#[warn(noop_method_call)]` on by default -warning: using `.clone()` on a double reference, which returns `&CloneType` instead of cloning the inner type - --> $DIR/noop-method-call.rs:22:63 +warning: call to `.clone()` on a reference in this situation does nothing + --> $DIR/noop-method-call.rs:17:21 | -LL | let clone_type_ref_clone: &CloneType = clone_type_ref.clone(); - | ^^^^^^^^ +LL | let _ = &encoded.clone(); + | ^^^^^^^^ help: remove this redundant call | - = note: `#[warn(suspicious_double_ref_op)]` on by default + = note: the type `[u8]` does not implement `Clone`, so calling `clone` on `&[u8]` copies the reference, which does not do anything and can be removed -warning: call to `.deref()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:26:63 +warning: call to `.clone()` on a reference in this situation does nothing + --> $DIR/noop-method-call.rs:23:71 | -LL | let non_deref_type_deref: &PlainType = non_deref_type.deref(); - | ^^^^^^^^ unnecessary method call +LL | let non_clone_type_ref_clone: &PlainType = non_clone_type_ref.clone(); + | ^^^^^^^^ help: remove this redundant call | - = note: the type `PlainType` does not implement `Deref`, so calling `deref` on `&PlainType` copies the reference, which does not do anything and can be removed + = note: the type `PlainType` does not implement `Clone`, so calling `clone` on `&PlainType` copies the reference, which does not do anything and can be removed -warning: using `.deref()` on a double reference, which returns `&PlainType` instead of dereferencing the inner type - --> $DIR/noop-method-call.rs:30:63 +warning: call to `.deref()` on a reference in this situation does nothing + --> $DIR/noop-method-call.rs:31:63 | LL | let non_deref_type_deref: &PlainType = non_deref_type.deref(); - | ^^^^^^^^ + | ^^^^^^^^ help: remove this redundant call + | + = note: the type `PlainType` does not implement `Deref`, so calling `deref` on `&PlainType` copies the reference, which does not do anything and can be removed warning: call to `.borrow()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:34:66 + --> $DIR/noop-method-call.rs:35:66 | LL | let non_borrow_type_borrow: &PlainType = non_borrow_type.borrow(); - | ^^^^^^^^^ unnecessary method call + | ^^^^^^^^^ help: remove this redundant call | = note: the type `PlainType` does not implement `Borrow`, so calling `borrow` on `&PlainType` copies the reference, which does not do anything and can be removed -warning: using `.clone()` on a double reference, which returns `&str` instead of cloning the inner type - --> $DIR/noop-method-call.rs:42:44 - | -LL | let _v: Vec<&str> = xs.iter().map(|x| x.clone()).collect(); // could use `*x` instead - | ^^^^^^^^ - warning: call to `.clone()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:47:19 + --> $DIR/noop-method-call.rs:44:19 | LL | non_clone_type.clone(); - | ^^^^^^^^ unnecessary method call + | ^^^^^^^^ help: remove this redundant call | = note: the type `PlainType` does not implement `Clone`, so calling `clone` on `&PlainType` copies the reference, which does not do anything and can be removed warning: call to `.clone()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:52:19 + --> $DIR/noop-method-call.rs:49:19 | LL | non_clone_type.clone(); - | ^^^^^^^^ unnecessary method call + | ^^^^^^^^ help: remove this redundant call | = note: the type `PlainType` does not implement `Clone`, so calling `clone` on `&PlainType` copies the reference, which does not do anything and can be removed -warning: 8 warnings emitted +warning: 7 warnings emitted diff --git a/tests/ui/lint/suspicious-double-ref-op.rs b/tests/ui/lint/suspicious-double-ref-op.rs index b9bcd31c2a8b0..bc8c23c7b895a 100644 --- a/tests/ui/lint/suspicious-double-ref-op.rs +++ b/tests/ui/lint/suspicious-double-ref-op.rs @@ -1,6 +1,14 @@ #![feature(lazy_cell)] #![deny(suspicious_double_ref_op, noop_method_call)] +use std::borrow::Borrow; +use std::ops::Deref; + +struct PlainType(T); + +#[derive(Clone)] +struct CloneType(T); + pub fn clone_on_double_ref() { let x = vec![1]; let y = &&x; @@ -20,11 +28,16 @@ fn rust_clippy_issue_9272() { println!("{str}") } -fn check(mut encoded: &[u8]) { - let _ = &mut encoded.clone(); - //~^ ERROR call to `.clone()` on a reference in this situation does nothing - let _ = &encoded.clone(); - //~^ ERROR call to `.clone()` on a reference in this situation does nothing -} +fn main() { + let clone_type_ref = &&CloneType(1u32); + let clone_type_ref_clone: &CloneType = clone_type_ref.clone(); + //~^ ERROR using `.clone()` on a double reference, which returns `&CloneType` + + let non_deref_type = &&PlainType(1u32); + let non_deref_type_deref: &PlainType = non_deref_type.deref(); + //~^ ERROR using `.deref()` on a double reference, which returns `&PlainType` -fn main() {} + let xs = ["a", "b", "c"]; + let _v: Vec<&str> = xs.iter().map(|x| x.clone()).collect(); // could use `*x` instead + //~^ ERROR using `.clone()` on a double reference, which returns `&str` +} diff --git a/tests/ui/lint/suspicious-double-ref-op.stderr b/tests/ui/lint/suspicious-double-ref-op.stderr index f2128f2a0edad..f5a71d40fc132 100644 --- a/tests/ui/lint/suspicious-double-ref-op.stderr +++ b/tests/ui/lint/suspicious-double-ref-op.stderr @@ -1,5 +1,5 @@ error: using `.clone()` on a double reference, which returns `&Vec` instead of cloning the inner type - --> $DIR/suspicious-double-ref-op.rs:7:23 + --> $DIR/suspicious-double-ref-op.rs:15:23 | LL | let z: &Vec<_> = y.clone(); | ^^^^^^^^ @@ -10,26 +10,23 @@ note: the lint level is defined here LL | #![deny(suspicious_double_ref_op, noop_method_call)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: call to `.clone()` on a reference in this situation does nothing - --> $DIR/suspicious-double-ref-op.rs:24:25 +error: using `.clone()` on a double reference, which returns `&CloneType` instead of cloning the inner type + --> $DIR/suspicious-double-ref-op.rs:33:63 | -LL | let _ = &mut encoded.clone(); - | ^^^^^^^^ unnecessary method call - | - = note: the type `[u8]` does not implement `Clone`, so calling `clone` on `&[u8]` copies the reference, which does not do anything and can be removed -note: the lint level is defined here - --> $DIR/suspicious-double-ref-op.rs:2:35 - | -LL | #![deny(suspicious_double_ref_op, noop_method_call)] - | ^^^^^^^^^^^^^^^^ +LL | let clone_type_ref_clone: &CloneType = clone_type_ref.clone(); + | ^^^^^^^^ -error: call to `.clone()` on a reference in this situation does nothing - --> $DIR/suspicious-double-ref-op.rs:26:21 +error: using `.deref()` on a double reference, which returns `&PlainType` instead of dereferencing the inner type + --> $DIR/suspicious-double-ref-op.rs:37:63 | -LL | let _ = &encoded.clone(); - | ^^^^^^^^ unnecessary method call +LL | let non_deref_type_deref: &PlainType = non_deref_type.deref(); + | ^^^^^^^^ + +error: using `.clone()` on a double reference, which returns `&str` instead of cloning the inner type + --> $DIR/suspicious-double-ref-op.rs:41:44 | - = note: the type `[u8]` does not implement `Clone`, so calling `clone` on `&[u8]` copies the reference, which does not do anything and can be removed +LL | let _v: Vec<&str> = xs.iter().map(|x| x.clone()).collect(); // could use `*x` instead + | ^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors