diff options
| author | Samuel Tardieu <sam@rfc1149.net> | 2024-11-30 19:22:58 +0100 |
|---|---|---|
| committer | Samuel Tardieu <sam@rfc1149.net> | 2024-12-02 16:26:51 +0100 |
| commit | ab5d55c996af0e52e216ce18bf3c38eb263633f4 (patch) | |
| tree | f7385783e498eecfef96dfc56803eb805cfbc55f | |
| parent | 9a692ec8cd726b6670c353b872a5c2e73e891081 (diff) | |
| download | rust-ab5d55c996af0e52e216ce18bf3c38eb263633f4.tar.gz rust-ab5d55c996af0e52e216ce18bf3c38eb263633f4.zip | |
Add more receivers to `useless_conversion`
- `ControlFlow::map_break()` - `ControlFlow::map_continue()` - `Iterator::map()`
| -rw-r--r-- | clippy_lints/src/methods/mod.rs | 3 | ||||
| -rw-r--r-- | clippy_lints/src/useless_conversion.rs | 22 | ||||
| -rw-r--r-- | tests/ui/useless_conversion.fixed | 17 | ||||
| -rw-r--r-- | tests/ui/useless_conversion.rs | 17 | ||||
| -rw-r--r-- | tests/ui/useless_conversion.stderr | 108 |
5 files changed, 120 insertions, 47 deletions
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 6c10ef6e206..941b086ab2e 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -4984,6 +4984,9 @@ impl Methods { manual_inspect::check(cx, expr, m_arg, name, span, &self.msrv); crate::useless_conversion::check_function_application(cx, expr, recv, m_arg); }, + ("map_break" | "map_continue", [m_arg]) => { + crate::useless_conversion::check_function_application(cx, expr, recv, m_arg); + }, ("map_or", [def, map]) => { option_map_or_none::check(cx, expr, recv, def, map); manual_ok_or::check(cx, expr, recv, def, map); diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs index 315410c768a..ccf04ab50f2 100644 --- a/clippy_lints/src/useless_conversion.rs +++ b/clippy_lints/src/useless_conversion.rs @@ -14,7 +14,7 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, AdtDef, EarlyBinder, GenericArg, GenericArgsRef, Ty, TypeVisitableExt}; use rustc_session::impl_lint_pass; -use rustc_span::{Span, sym}; +use rustc_span::{Span, Symbol, sym}; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; declare_clippy_lint! { @@ -415,9 +415,25 @@ fn has_eligible_receiver(cx: &LateContext<'_>, recv: &Expr<'_>, expr: &Expr<'_>) let recv_ty = cx.typeck_results().expr_ty(recv); if is_inherent_method_call(cx, expr) && let Some(recv_ty_defid) = recv_ty.ty_adt_def().map(AdtDef::did) - && let Some(diag_name) = cx.tcx.get_diagnostic_name(recv_ty_defid) - && matches!(diag_name, sym::Option | sym::Result) { + if let Some(diag_name) = cx.tcx.get_diagnostic_name(recv_ty_defid) + && matches!(diag_name, sym::Option | sym::Result) + { + return true; + } + + // FIXME: Add ControlFlow diagnostic item + let def_path = cx.get_def_path(recv_ty_defid); + if def_path + .iter() + .map(Symbol::as_str) + .zip(["core", "ops", "control_flow", "ControlFlow"]) + .all(|(sym, s)| sym == s) + { + return true; + } + } + if is_trait_method(cx, expr, sym::Iterator) { return true; } false diff --git a/tests/ui/useless_conversion.fixed b/tests/ui/useless_conversion.fixed index 36fc8938e87..2f7edd92bb7 100644 --- a/tests/ui/useless_conversion.fixed +++ b/tests/ui/useless_conversion.fixed @@ -3,6 +3,8 @@ // FIXME(static_mut_refs): Do not allow `static_mut_refs` lint #![allow(static_mut_refs)] +use std::ops::ControlFlow; + fn test_generic<T: Copy>(val: T) -> T { let _ = val; val @@ -308,6 +310,13 @@ fn direct_application() { let _: Result<(), std::io::Error> = test_issue_3913(); //~^ useless_conversion + let c: ControlFlow<()> = ControlFlow::Continue(()); + let _: ControlFlow<()> = c; + //~^ useless_conversion + let c: ControlFlow<()> = ControlFlow::Continue(()); + let _: ControlFlow<()> = c; + //~^ useless_conversion + struct Absorb; impl From<()> for Absorb { fn from(_: ()) -> Self { @@ -319,11 +328,17 @@ fn direct_application() { Self } } + let _: Vec<u32> = [1u32].into_iter().collect(); + //~^ useless_conversion // No lint for those let _: Result<Absorb, std::io::Error> = test_issue_3913().map(Into::into); let _: Result<(), Absorb> = test_issue_3913().map_err(Into::into); let _: Result<Absorb, std::io::Error> = test_issue_3913().map(From::from); let _: Result<(), Absorb> = test_issue_3913().map_err(From::from); - let _: Vec<u32> = [1u32].into_iter().map(Into::into).collect(); +} + +fn gen_identity<T>(x: [T; 3]) -> Vec<T> { + x.into_iter().collect() + //~^ useless_conversion } diff --git a/tests/ui/useless_conversion.rs b/tests/ui/useless_conversion.rs index 7509b70d39c..eacdf77f905 100644 --- a/tests/ui/useless_conversion.rs +++ b/tests/ui/useless_conversion.rs @@ -3,6 +3,8 @@ // FIXME(static_mut_refs): Do not allow `static_mut_refs` lint #![allow(static_mut_refs)] +use std::ops::ControlFlow; + fn test_generic<T: Copy>(val: T) -> T { let _ = T::from(val); val.into() @@ -308,6 +310,13 @@ fn direct_application() { let _: Result<(), std::io::Error> = test_issue_3913().map_err(From::from); //~^ useless_conversion + let c: ControlFlow<()> = ControlFlow::Continue(()); + let _: ControlFlow<()> = c.map_break(Into::into); + //~^ useless_conversion + let c: ControlFlow<()> = ControlFlow::Continue(()); + let _: ControlFlow<()> = c.map_continue(Into::into); + //~^ useless_conversion + struct Absorb; impl From<()> for Absorb { fn from(_: ()) -> Self { @@ -319,11 +328,17 @@ fn direct_application() { Self } } + let _: Vec<u32> = [1u32].into_iter().map(Into::into).collect(); + //~^ useless_conversion // No lint for those let _: Result<Absorb, std::io::Error> = test_issue_3913().map(Into::into); let _: Result<(), Absorb> = test_issue_3913().map_err(Into::into); let _: Result<Absorb, std::io::Error> = test_issue_3913().map(From::from); let _: Result<(), Absorb> = test_issue_3913().map_err(From::from); - let _: Vec<u32> = [1u32].into_iter().map(Into::into).collect(); +} + +fn gen_identity<T>(x: [T; 3]) -> Vec<T> { + x.into_iter().map(Into::into).collect() + //~^ useless_conversion } diff --git a/tests/ui/useless_conversion.stderr b/tests/ui/useless_conversion.stderr index 7ed42dd2080..6aeb382902b 100644 --- a/tests/ui/useless_conversion.stderr +++ b/tests/ui/useless_conversion.stderr @@ -1,5 +1,5 @@ error: useless conversion to the same type: `T` - --> tests/ui/useless_conversion.rs:7:13 + --> tests/ui/useless_conversion.rs:9:13 | LL | let _ = T::from(val); | ^^^^^^^^^^^^ help: consider removing `T::from()`: `val` @@ -11,244 +11,268 @@ LL | #![deny(clippy::useless_conversion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: useless conversion to the same type: `T` - --> tests/ui/useless_conversion.rs:8:5 + --> tests/ui/useless_conversion.rs:10:5 | LL | val.into() | ^^^^^^^^^^ help: consider removing `.into()`: `val` error: useless conversion to the same type: `i32` - --> tests/ui/useless_conversion.rs:20:22 + --> tests/ui/useless_conversion.rs:22:22 | LL | let _: i32 = 0i32.into(); | ^^^^^^^^^^^ help: consider removing `.into()`: `0i32` error: useless conversion to the same type: `std::str::Lines<'_>` - --> tests/ui/useless_conversion.rs:50:22 + --> tests/ui/useless_conversion.rs:52:22 | LL | if Some("ok") == lines.into_iter().next() {} | ^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `lines` error: useless conversion to the same type: `std::str::Lines<'_>` - --> tests/ui/useless_conversion.rs:55:21 + --> tests/ui/useless_conversion.rs:57:21 | LL | let mut lines = text.lines().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `text.lines()` error: useless conversion to the same type: `std::str::Lines<'_>` - --> tests/ui/useless_conversion.rs:61:22 + --> tests/ui/useless_conversion.rs:63:22 | LL | if Some("ok") == text.lines().into_iter().next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `text.lines()` error: useless conversion to the same type: `std::ops::Range<i32>` - --> tests/ui/useless_conversion.rs:67:13 + --> tests/ui/useless_conversion.rs:69:13 | LL | let _ = NUMBERS.into_iter().next(); | ^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `NUMBERS` error: useless conversion to the same type: `std::ops::Range<i32>` - --> tests/ui/useless_conversion.rs:72:17 + --> tests/ui/useless_conversion.rs:74:17 | LL | let mut n = NUMBERS.into_iter(); | ^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `NUMBERS` error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion.rs:134:21 + --> tests/ui/useless_conversion.rs:136:21 | LL | let _: String = "foo".to_string().into(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()` error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion.rs:135:21 + --> tests/ui/useless_conversion.rs:137:21 | LL | let _: String = From::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()` error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion.rs:136:13 + --> tests/ui/useless_conversion.rs:138:13 | LL | let _ = String::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()` error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion.rs:137:13 + --> tests/ui/useless_conversion.rs:139:13 | LL | let _ = String::from(format!("A: {:04}", 123)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)` error: useless conversion to the same type: `std::str::Lines<'_>` - --> tests/ui/useless_conversion.rs:138:13 + --> tests/ui/useless_conversion.rs:140:13 | LL | let _ = "".lines().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()` error: useless conversion to the same type: `std::vec::IntoIter<i32>` - --> tests/ui/useless_conversion.rs:139:13 + --> tests/ui/useless_conversion.rs:141:13 | LL | let _ = vec![1, 2, 3].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()` error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion.rs:140:21 + --> tests/ui/useless_conversion.rs:142:21 | LL | let _: String = format!("Hello {}", "world").into(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `format!("Hello {}", "world")` error: useless conversion to the same type: `i32` - --> tests/ui/useless_conversion.rs:145:13 + --> tests/ui/useless_conversion.rs:147:13 | LL | let _ = i32::from(a + b) * 3; | ^^^^^^^^^^^^^^^^ help: consider removing `i32::from()`: `(a + b)` error: useless conversion to the same type: `Foo<'a'>` - --> tests/ui/useless_conversion.rs:151:23 + --> tests/ui/useless_conversion.rs:153:23 | LL | let _: Foo<'a'> = s2.into(); | ^^^^^^^^^ help: consider removing `.into()`: `s2` error: useless conversion to the same type: `Foo<'a'>` - --> tests/ui/useless_conversion.rs:153:13 + --> tests/ui/useless_conversion.rs:155:13 | LL | let _ = Foo::<'a'>::from(s3); | ^^^^^^^^^^^^^^^^^^^^ help: consider removing `Foo::<'a'>::from()`: `s3` error: useless conversion to the same type: `std::vec::IntoIter<Foo<'a'>>` - --> tests/ui/useless_conversion.rs:155:13 + --> tests/ui/useless_conversion.rs:157:13 | LL | let _ = vec![s4, s4, s4].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![s4, s4, s4].into_iter()` error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:187:7 + --> tests/ui/useless_conversion.rs:189:7 | LL | b(vec![1, 2].into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:177:13 + --> tests/ui/useless_conversion.rs:179:13 | LL | fn b<T: IntoIterator<Item = i32>>(_: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:188:7 + --> tests/ui/useless_conversion.rs:190:7 | LL | c(vec![1, 2].into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:178:18 + --> tests/ui/useless_conversion.rs:180:18 | LL | fn c(_: impl IntoIterator<Item = i32>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:189:7 + --> tests/ui/useless_conversion.rs:191:7 | LL | d(vec![1, 2].into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:181:12 + --> tests/ui/useless_conversion.rs:183:12 | LL | T: IntoIterator<Item = i32>, | ^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:192:7 + --> tests/ui/useless_conversion.rs:194:7 | LL | b(vec![1, 2].into_iter().into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`s: `vec![1, 2]` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:177:13 + --> tests/ui/useless_conversion.rs:179:13 | LL | fn b<T: IntoIterator<Item = i32>>(_: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:193:7 + --> tests/ui/useless_conversion.rs:195:7 | LL | b(vec![1, 2].into_iter().into_iter().into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`s: `vec![1, 2]` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:177:13 + --> tests/ui/useless_conversion.rs:179:13 | LL | fn b<T: IntoIterator<Item = i32>>(_: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:239:24 + --> tests/ui/useless_conversion.rs:241:24 | LL | foo2::<i32, _>([1, 2, 3].into_iter()); | ^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `[1, 2, 3]` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:218:12 + --> tests/ui/useless_conversion.rs:220:12 | LL | I: IntoIterator<Item = i32> + Helper<X>, | ^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:247:14 + --> tests/ui/useless_conversion.rs:249:14 | LL | foo3([1, 2, 3].into_iter()); | ^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `[1, 2, 3]` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:227:12 + --> tests/ui/useless_conversion.rs:229:12 | LL | I: IntoIterator<Item = i32>, | ^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:256:16 + --> tests/ui/useless_conversion.rs:258:16 | LL | S1.foo([1, 2].into_iter()); | ^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `[1, 2]` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:253:27 + --> tests/ui/useless_conversion.rs:255:27 | LL | pub fn foo<I: IntoIterator>(&self, _: I) {} | ^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:275:44 + --> tests/ui/useless_conversion.rs:277:44 | LL | v0.into_iter().interleave_shortest(v1.into_iter()); | ^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `v1` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:262:20 + --> tests/ui/useless_conversion.rs:264:20 | LL | J: IntoIterator, | ^^^^^^^^^^^^ error: useless conversion to the same type: `()` - --> tests/ui/useless_conversion.rs:302:58 + --> tests/ui/useless_conversion.rs:304:58 | LL | let _: Result<(), std::io::Error> = test_issue_3913().map(Into::into); | ^^^^^^^^^^^^^^^^ help: consider removing error: useless conversion to the same type: `std::io::Error` - --> tests/ui/useless_conversion.rs:304:58 + --> tests/ui/useless_conversion.rs:306:58 | LL | let _: Result<(), std::io::Error> = test_issue_3913().map_err(Into::into); | ^^^^^^^^^^^^^^^^^^^^ help: consider removing error: useless conversion to the same type: `()` - --> tests/ui/useless_conversion.rs:306:58 + --> tests/ui/useless_conversion.rs:308:58 | LL | let _: Result<(), std::io::Error> = test_issue_3913().map(From::from); | ^^^^^^^^^^^^^^^^ help: consider removing error: useless conversion to the same type: `std::io::Error` - --> tests/ui/useless_conversion.rs:308:58 + --> tests/ui/useless_conversion.rs:310:58 | LL | let _: Result<(), std::io::Error> = test_issue_3913().map_err(From::from); | ^^^^^^^^^^^^^^^^^^^^ help: consider removing -error: aborting due to 32 previous errors +error: useless conversion to the same type: `()` + --> tests/ui/useless_conversion.rs:314:31 + | +LL | let _: ControlFlow<()> = c.map_break(Into::into); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing + +error: useless conversion to the same type: `()` + --> tests/ui/useless_conversion.rs:317:31 + | +LL | let _: ControlFlow<()> = c.map_continue(Into::into); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing + +error: useless conversion to the same type: `u32` + --> tests/ui/useless_conversion.rs:331:41 + | +LL | let _: Vec<u32> = [1u32].into_iter().map(Into::into).collect(); + | ^^^^^^^^^^^^^^^^ help: consider removing + +error: useless conversion to the same type: `T` + --> tests/ui/useless_conversion.rs:342:18 + | +LL | x.into_iter().map(Into::into).collect() + | ^^^^^^^^^^^^^^^^ help: consider removing + +error: aborting due to 36 previous errors |
