From 552e950080f4fa2a4570e9719f2b4f7effed047e Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 18 Jan 2018 14:19:19 +0530 Subject: [PATCH] needless_pass_by_value: Whitelist RangeArgument (fixes #2357) --- clippy_lints/src/needless_pass_by_value.rs | 5 +- clippy_lints/src/utils/paths.rs | 1 + tests/ui/needless_pass_by_value.rs | 7 ++ tests/ui/needless_pass_by_value.stderr | 100 ++++++++++----------- 4 files changed, 61 insertions(+), 52 deletions(-) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 92dc33077..f5ff0ef82 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -102,10 +102,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { // Allow `Borrow` or functions to be taken by value let borrow_trait = need!(get_trait_def_id(cx, &paths::BORROW_TRAIT)); - let fn_traits = [ + let whitelisted_traits = [ need!(cx.tcx.lang_items().fn_trait()), need!(cx.tcx.lang_items().fn_once_trait()), need!(cx.tcx.lang_items().fn_mut_trait()), + need!(get_trait_def_id(cx, &paths::RANGE_ARGUMENT_TRAIT)) ]; let sized_trait = need!(cx.tcx.lang_items().sized_trait()); @@ -189,7 +190,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { if !is_self(arg); if !ty.is_mutable_pointer(); if !is_copy(cx, ty); - if !fn_traits.iter().any(|&t| implements_trait(cx, ty, t, &[])); + if !whitelisted_traits.iter().any(|&t| implements_trait(cx, ty, t, &[])); if !implements_borrow_trait; if !all_borrowable_trait; diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 95e146091..20244a19f 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -55,6 +55,7 @@ pub const OPTION_SOME: [&str; 4] = ["core", "option", "Option", "Some"]; pub const PTR_NULL: [&str; 2] = ["ptr", "null"]; pub const PTR_NULL_MUT: [&str; 2] = ["ptr", "null_mut"]; pub const RANGE: [&str; 3] = ["core", "ops", "Range"]; +pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["alloc", "range", "RangeArgument"]; pub const RANGE_FROM: [&str; 3] = ["core", "ops", "RangeFrom"]; pub const RANGE_FROM_STD: [&str; 3] = ["std", "ops", "RangeFrom"]; pub const RANGE_FULL: [&str; 3] = ["core", "ops", "RangeFull"]; diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index e5138c37e..bca48c97e 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -4,6 +4,8 @@ #![warn(needless_pass_by_value)] #![allow(dead_code, single_match, if_let_redundant_pattern_matching, many_single_char_names)] +#![feature(collections_range)] + use std::borrow::Borrow; use std::convert::AsRef; @@ -113,4 +115,9 @@ trait FalsePositive { // shouldn't warn on extern funcs extern "C" fn ext(x: String) -> usize { x.len() } +// whitelist RangeArgument +fn range>(range: T) { + let _ = range.start(); +} + fn main() {} diff --git a/tests/ui/needless_pass_by_value.stderr b/tests/ui/needless_pass_by_value.stderr index 441a9095b..f03fbfee9 100644 --- a/tests/ui/needless_pass_by_value.stderr +++ b/tests/ui/needless_pass_by_value.stderr @@ -1,151 +1,151 @@ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:12:23 + --> $DIR/needless_pass_by_value.rs:14:23 | -12 | fn foo(v: Vec, w: Vec, mut x: Vec, y: Vec) -> Vec { +14 | fn foo(v: Vec, w: Vec, mut x: Vec, y: Vec) -> Vec { | ^^^^^^ help: consider changing the type to: `&[T]` | = note: `-D needless-pass-by-value` implied by `-D warnings` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:26:11 + --> $DIR/needless_pass_by_value.rs:28:11 | -26 | fn bar(x: String, y: Wrapper) { +28 | fn bar(x: String, y: Wrapper) { | ^^^^^^ help: consider changing the type to: `&str` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:26:22 + --> $DIR/needless_pass_by_value.rs:28:22 | -26 | fn bar(x: String, y: Wrapper) { +28 | fn bar(x: String, y: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` | help: consider marking this type as Copy if possible - --> $DIR/needless_pass_by_value.rs:24:1 + --> $DIR/needless_pass_by_value.rs:26:1 | -24 | struct Wrapper(String); +26 | struct Wrapper(String); | ^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:32:71 + --> $DIR/needless_pass_by_value.rs:34:71 | -32 | fn test_borrow_trait, U: AsRef, V>(t: T, u: U, v: V) { +34 | fn test_borrow_trait, U: AsRef, V>(t: T, u: U, v: V) { | ^ help: consider taking a reference instead: `&V` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:44:18 + --> $DIR/needless_pass_by_value.rs:46:18 | -44 | fn test_match(x: Option>, y: Option>) { +46 | fn test_match(x: Option>, y: Option>) { | ^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead | -44 | fn test_match(x: &Option>, y: Option>) { -45 | match *x { +46 | fn test_match(x: &Option>, y: Option>) { +47 | match *x { | error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:57:24 + --> $DIR/needless_pass_by_value.rs:59:24 | -57 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { +59 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` | help: consider marking this type as Copy if possible - --> $DIR/needless_pass_by_value.rs:24:1 + --> $DIR/needless_pass_by_value.rs:26:1 | -24 | struct Wrapper(String); +26 | struct Wrapper(String); | ^^^^^^^^^^^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:57:36 + --> $DIR/needless_pass_by_value.rs:59:36 | -57 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { +59 | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { | ^^^^^^^ | help: consider marking this type as Copy if possible - --> $DIR/needless_pass_by_value.rs:24:1 + --> $DIR/needless_pass_by_value.rs:26:1 | -24 | struct Wrapper(String); +26 | struct Wrapper(String); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead | -57 | fn test_destructure(x: Wrapper, y: &Wrapper, z: Wrapper) { -58 | let Wrapper(s) = z; // moved -59 | let Wrapper(ref t) = *y; // not moved -60 | let Wrapper(_) = *y; // still not moved +59 | fn test_destructure(x: Wrapper, y: &Wrapper, z: Wrapper) { +60 | let Wrapper(s) = z; // moved +61 | let Wrapper(ref t) = *y; // not moved +62 | let Wrapper(_) = *y; // still not moved | error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:73:49 + --> $DIR/needless_pass_by_value.rs:75:49 | -73 | fn test_blanket_ref(_foo: T, _serializable: S) {} +75 | fn test_blanket_ref(_foo: T, _serializable: S) {} | ^ help: consider taking a reference instead: `&T` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:75:18 + --> $DIR/needless_pass_by_value.rs:77:18 | -75 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +77 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^ help: consider taking a reference instead: `&String` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:75:29 + --> $DIR/needless_pass_by_value.rs:77:29 | -75 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +77 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^ help: consider changing the type to | -75 | fn issue_2114(s: String, t: &str, u: Vec, v: Vec) { +77 | fn issue_2114(s: String, t: &str, u: Vec, v: Vec) { | ^^^^ help: change `t.clone()` to | -77 | let _ = t.to_string(); +79 | let _ = t.to_string(); | ^^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:75:40 + --> $DIR/needless_pass_by_value.rs:77:40 | -75 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +77 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^^^ help: consider taking a reference instead: `&Vec` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:75:53 + --> $DIR/needless_pass_by_value.rs:77:53 | -75 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { +77 | fn issue_2114(s: String, t: String, u: Vec, v: Vec) { | ^^^^^^^^ help: consider changing the type to | -75 | fn issue_2114(s: String, t: String, u: Vec, v: &[i32]) { +77 | fn issue_2114(s: String, t: String, u: Vec, v: &[i32]) { | ^^^^^^ help: change `v.clone()` to | -79 | let _ = v.to_owned(); +81 | let _ = v.to_owned(); | ^^^^^^^^^^^^ error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:87:12 + --> $DIR/needless_pass_by_value.rs:89:12 | -87 | s: String, +89 | s: String, | ^^^^^^ help: consider changing the type to: `&str` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:88:12 + --> $DIR/needless_pass_by_value.rs:90:12 | -88 | t: String, +90 | t: String, | ^^^^^^ help: consider taking a reference instead: `&String` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:100:13 + --> $DIR/needless_pass_by_value.rs:102:13 | -100 | _u: U, +102 | _u: U, | ^ help: consider taking a reference instead: `&U` error: this argument is passed by value, but not consumed in the function body - --> $DIR/needless_pass_by_value.rs:101:13 + --> $DIR/needless_pass_by_value.rs:103:13 | -101 | _s: Self, +103 | _s: Self, | ^^^^ help: consider taking a reference instead: `&Self` | help: consider marking this type as Copy if possible - --> $DIR/needless_pass_by_value.rs:82:1 + --> $DIR/needless_pass_by_value.rs:84:1 | -82 | struct S(T, U); +84 | struct S(T, U); | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 16 previous errors