Auto merge of #11669 - y21:issue11577, r=Jarcho
new lint: `unnecessary_fallible_conversions` Closes #11577 A new lint that looks for calls such as `i64::try_from(1i32)` and suggests `i64::from(1i32)`. See lint description (and linked issue) for more details for why. There's a tiny bit of overlap with the `useless_conversion` lint, in that the other one warns `T::try_from(T)` (i.e., fallibly converting to the same type), so this lint ignores cases like `i32::try_from(1i32)` to avoid emitting two warnings for the same expression. Also, funnily enough, with this one exception, this lint would warn on exactly every case in the `useless_conversion_try` ui test that `useless_conversion` didn't cover (but never two warnings at the same time), which is neat. I did add an `#![allow]` though since we don't want interleaved warnings from multiple lints in the same uitest. changelog: new lint: `unnecessary_fallible_conversions`
This commit is contained in:
commit
7d34406015
14 changed files with 291 additions and 22 deletions
|
|
@ -1,4 +1,5 @@
|
|||
#![warn(clippy::manual_string_new)]
|
||||
#![allow(clippy::unnecessary_fallible_conversions)]
|
||||
|
||||
macro_rules! create_strings_from_macro {
|
||||
// When inside a macro, nothing should warn to prevent false positives.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#![warn(clippy::manual_string_new)]
|
||||
#![allow(clippy::unnecessary_fallible_conversions)]
|
||||
|
||||
macro_rules! create_strings_from_macro {
|
||||
// When inside a macro, nothing should warn to prevent false positives.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: empty String is being created manually
|
||||
--> $DIR/manual_string_new.rs:13:13
|
||||
--> $DIR/manual_string_new.rs:14:13
|
||||
|
|
||||
LL | let _ = "".to_string();
|
||||
| ^^^^^^^^^^^^^^ help: consider using: `String::new()`
|
||||
|
|
@ -8,49 +8,49 @@ LL | let _ = "".to_string();
|
|||
= help: to override `-D warnings` add `#[allow(clippy::manual_string_new)]`
|
||||
|
||||
error: empty String is being created manually
|
||||
--> $DIR/manual_string_new.rs:16:13
|
||||
--> $DIR/manual_string_new.rs:17:13
|
||||
|
|
||||
LL | let _ = "".to_owned();
|
||||
| ^^^^^^^^^^^^^ help: consider using: `String::new()`
|
||||
|
||||
error: empty String is being created manually
|
||||
--> $DIR/manual_string_new.rs:19:21
|
||||
--> $DIR/manual_string_new.rs:20:21
|
||||
|
|
||||
LL | let _: String = "".into();
|
||||
| ^^^^^^^^^ help: consider using: `String::new()`
|
||||
|
||||
error: empty String is being created manually
|
||||
--> $DIR/manual_string_new.rs:26:13
|
||||
--> $DIR/manual_string_new.rs:27:13
|
||||
|
|
||||
LL | let _ = String::from("");
|
||||
| ^^^^^^^^^^^^^^^^ help: consider using: `String::new()`
|
||||
|
||||
error: empty String is being created manually
|
||||
--> $DIR/manual_string_new.rs:27:13
|
||||
--> $DIR/manual_string_new.rs:28:13
|
||||
|
|
||||
LL | let _ = <String>::from("");
|
||||
| ^^^^^^^^^^^^^^^^^^ help: consider using: `String::new()`
|
||||
|
||||
error: empty String is being created manually
|
||||
--> $DIR/manual_string_new.rs:32:13
|
||||
--> $DIR/manual_string_new.rs:33:13
|
||||
|
|
||||
LL | let _ = String::try_from("").unwrap();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `String::new()`
|
||||
|
||||
error: empty String is being created manually
|
||||
--> $DIR/manual_string_new.rs:38:21
|
||||
--> $DIR/manual_string_new.rs:39:21
|
||||
|
|
||||
LL | let _: String = From::from("");
|
||||
| ^^^^^^^^^^^^^^ help: consider using: `String::new()`
|
||||
|
||||
error: empty String is being created manually
|
||||
--> $DIR/manual_string_new.rs:43:21
|
||||
--> $DIR/manual_string_new.rs:44:21
|
||||
|
|
||||
LL | let _: String = TryFrom::try_from("").unwrap();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `String::new()`
|
||||
|
||||
error: empty String is being created manually
|
||||
--> $DIR/manual_string_new.rs:46:21
|
||||
--> $DIR/manual_string_new.rs:47:21
|
||||
|
|
||||
LL | let _: String = TryFrom::try_from("").expect("this should warn");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `String::new()`
|
||||
|
|
|
|||
6
tests/ui/unnecessary_fallible_conversions.fixed
Normal file
6
tests/ui/unnecessary_fallible_conversions.fixed
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#![warn(clippy::unnecessary_fallible_conversions)]
|
||||
|
||||
fn main() {
|
||||
let _: i64 = 0i32.into();
|
||||
let _: i64 = 0i32.into();
|
||||
}
|
||||
6
tests/ui/unnecessary_fallible_conversions.rs
Normal file
6
tests/ui/unnecessary_fallible_conversions.rs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#![warn(clippy::unnecessary_fallible_conversions)]
|
||||
|
||||
fn main() {
|
||||
let _: i64 = 0i32.try_into().unwrap();
|
||||
let _: i64 = 0i32.try_into().expect("can't happen");
|
||||
}
|
||||
17
tests/ui/unnecessary_fallible_conversions.stderr
Normal file
17
tests/ui/unnecessary_fallible_conversions.stderr
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
error: use of a fallible conversion when an infallible one could be used
|
||||
--> $DIR/unnecessary_fallible_conversions.rs:4:23
|
||||
|
|
||||
LL | let _: i64 = 0i32.try_into().unwrap();
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: use: `into()`
|
||||
|
|
||||
= note: `-D clippy::unnecessary-fallible-conversions` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::unnecessary_fallible_conversions)]`
|
||||
|
||||
error: use of a fallible conversion when an infallible one could be used
|
||||
--> $DIR/unnecessary_fallible_conversions.rs:5:23
|
||||
|
|
||||
LL | let _: i64 = 0i32.try_into().expect("can't happen");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `into()`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
43
tests/ui/unnecessary_fallible_conversions_unfixable.rs
Normal file
43
tests/ui/unnecessary_fallible_conversions_unfixable.rs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
//@aux-build:proc_macros.rs
|
||||
//@no-rustfix
|
||||
#![warn(clippy::unnecessary_fallible_conversions)]
|
||||
|
||||
extern crate proc_macros;
|
||||
|
||||
struct Foo;
|
||||
impl TryFrom<i32> for Foo {
|
||||
type Error = ();
|
||||
fn try_from(_: i32) -> Result<Self, Self::Error> {
|
||||
Ok(Foo)
|
||||
}
|
||||
}
|
||||
impl From<i64> for Foo {
|
||||
fn from(_: i64) -> Self {
|
||||
Foo
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// `Foo` only implements `TryFrom<i32>` and not `From<i32>`, so don't lint
|
||||
let _: Result<Foo, _> = 0i32.try_into();
|
||||
let _: Result<Foo, _> = i32::try_into(0i32);
|
||||
let _: Result<Foo, _> = Foo::try_from(0i32);
|
||||
|
||||
// ... it does impl From<i64> however
|
||||
let _: Result<Foo, _> = 0i64.try_into();
|
||||
//~^ ERROR: use of a fallible conversion when an infallible one could be used
|
||||
let _: Result<Foo, _> = i64::try_into(0i64);
|
||||
//~^ ERROR: use of a fallible conversion when an infallible one could be used
|
||||
let _: Result<Foo, _> = Foo::try_from(0i64);
|
||||
//~^ ERROR: use of a fallible conversion when an infallible one could be used
|
||||
|
||||
let _: Result<i64, _> = 0i32.try_into();
|
||||
//~^ ERROR: use of a fallible conversion when an infallible one could be used
|
||||
let _: Result<i64, _> = i32::try_into(0i32);
|
||||
//~^ ERROR: use of a fallible conversion when an infallible one could be used
|
||||
let _: Result<i64, _> = <_>::try_from(0i32);
|
||||
//~^ ERROR: use of a fallible conversion when an infallible one could be used
|
||||
|
||||
// From a macro
|
||||
let _: Result<i64, _> = proc_macros::external!(0i32).try_into();
|
||||
}
|
||||
41
tests/ui/unnecessary_fallible_conversions_unfixable.stderr
Normal file
41
tests/ui/unnecessary_fallible_conversions_unfixable.stderr
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
error: use of a fallible conversion when an infallible one could be used
|
||||
--> $DIR/unnecessary_fallible_conversions_unfixable.rs:27:34
|
||||
|
|
||||
LL | let _: Result<Foo, _> = 0i64.try_into();
|
||||
| ^^^^^^^^ help: use: `into`
|
||||
|
|
||||
= note: `-D clippy::unnecessary-fallible-conversions` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::unnecessary_fallible_conversions)]`
|
||||
|
||||
error: use of a fallible conversion when an infallible one could be used
|
||||
--> $DIR/unnecessary_fallible_conversions_unfixable.rs:29:29
|
||||
|
|
||||
LL | let _: Result<Foo, _> = i64::try_into(0i64);
|
||||
| ^^^^^^^^^^^^^ help: use: `Into::into`
|
||||
|
||||
error: use of a fallible conversion when an infallible one could be used
|
||||
--> $DIR/unnecessary_fallible_conversions_unfixable.rs:31:29
|
||||
|
|
||||
LL | let _: Result<Foo, _> = Foo::try_from(0i64);
|
||||
| ^^^^^^^^^^^^^ help: use: `From::from`
|
||||
|
||||
error: use of a fallible conversion when an infallible one could be used
|
||||
--> $DIR/unnecessary_fallible_conversions_unfixable.rs:34:34
|
||||
|
|
||||
LL | let _: Result<i64, _> = 0i32.try_into();
|
||||
| ^^^^^^^^ help: use: `into`
|
||||
|
||||
error: use of a fallible conversion when an infallible one could be used
|
||||
--> $DIR/unnecessary_fallible_conversions_unfixable.rs:36:29
|
||||
|
|
||||
LL | let _: Result<i64, _> = i32::try_into(0i32);
|
||||
| ^^^^^^^^^^^^^ help: use: `Into::into`
|
||||
|
||||
error: use of a fallible conversion when an infallible one could be used
|
||||
--> $DIR/unnecessary_fallible_conversions_unfixable.rs:38:29
|
||||
|
|
||||
LL | let _: Result<i64, _> = <_>::try_from(0i32);
|
||||
| ^^^^^^^^^^^^^ help: use: `From::from`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
#![deny(clippy::useless_conversion)]
|
||||
#![allow(clippy::needless_if)]
|
||||
#![allow(clippy::needless_if, clippy::unnecessary_fallible_conversions)]
|
||||
|
||||
fn test_generic<T: Copy>(val: T) -> T {
|
||||
let _ = T::try_from(val).unwrap();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue