Auto merge of #10570 - AlessioC31:redundant_type_annotations, r=xFrednet
Add redundant type annotations lint
Hello, I'm trying to add the `redundat_type_annotations` lint.
It's still WIP but I'd like to start gathering some feedbacks to be sure that I'm not doing things 100% wrong :)
Right now it still misses lints like:
- [x] `let foo: u32 = 5_u32`,
- [x] `let foo: String = STest2::func()`
- [x] `let foo: String = self.func()` (`MethodCall`)
- [x] refs
- [ ] Generics
I've some problems regarding the second example above, in the `init` part of the `Local` I have:
```rust
init: Some(
Expr {
hir_id: HirId(DefId(0:24 ~ playground[e1bd]::main).58),
kind: Call(
Expr {
hir_id: HirId(DefId(0:24 ~ playground[e1bd]::main).59),
kind: Path(
TypeRelative(
Ty {
hir_id: HirId(DefId(0:24 ~ playground[e1bd]::main).61),
kind: Path(
Resolved(
None,
Path {
span: src/main.rs:77:21: 77:27 (#0),
res: Def(
Struct,
DefId(0:17 ~ playground[e1bd]::STest2),
),
segments: [
PathSegment {
ident: STest2#0,
hir_id: HirId(DefId(0:24 ~ playground[e1bd]::main).60),
res: Def(
Struct,
DefId(0:17 ~ playground[e1bd]::STest2),
),
args: None,
infer_args: true,
},
],
},
),
),
span: src/main.rs:77:21: 77:27 (#0),
},
PathSegment {
ident: get_numb#0,
hir_id: HirId(DefId(0:24 ~ playground[e1bd]::main).62),
res: Err,
args: None,
infer_args: true,
},
),
),
span: src/main.rs:77:21: 77:37 (#0),
},
[],
),
span: src/main.rs:77:21: 77:39 (#0),
},
),
```
And I'm not sure how to get the return type of the function `STest2::func()` since the resolved path `DefId` points to the struct itself and not the function. Do you have any idea on how I could get this information in this case?
Thanks!
changelog: changelog: [`redundant_type_annotations`]: New lint to warn on redundant type annotations
fixes #9155
This commit is contained in:
commit
cc8ead2cce
6 changed files with 496 additions and 0 deletions
176
tests/ui/redundant_type_annotations.rs
Normal file
176
tests/ui/redundant_type_annotations.rs
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
#![allow(unused)]
|
||||
#![warn(clippy::redundant_type_annotations)]
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct Cake<T> {
|
||||
_data: T,
|
||||
}
|
||||
|
||||
fn make_something<T: Default>() -> T {
|
||||
T::default()
|
||||
}
|
||||
|
||||
fn make_cake<T: Default>() -> Cake<T> {
|
||||
Cake::<T>::default()
|
||||
}
|
||||
|
||||
fn plus_one<T: std::ops::Add<u8, Output = T>>(val: T) -> T {
|
||||
val + 1
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct Slice {
|
||||
inner: u32,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct Pie {
|
||||
inner: u32,
|
||||
inner_struct: Slice,
|
||||
}
|
||||
|
||||
enum Pizza {
|
||||
One,
|
||||
Two,
|
||||
}
|
||||
|
||||
fn return_a_string() -> String {
|
||||
String::new()
|
||||
}
|
||||
|
||||
fn return_a_struct() -> Pie {
|
||||
Pie::default()
|
||||
}
|
||||
|
||||
fn return_an_enum() -> Pizza {
|
||||
Pizza::One
|
||||
}
|
||||
|
||||
fn return_an_int() -> u32 {
|
||||
5
|
||||
}
|
||||
|
||||
impl Pie {
|
||||
fn return_an_int(&self) -> u32 {
|
||||
self.inner
|
||||
}
|
||||
|
||||
fn return_a_ref(&self) -> &u32 {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
fn return_a_ref_to_struct(&self) -> &Slice {
|
||||
&self.inner_struct
|
||||
}
|
||||
|
||||
fn associated_return_an_int() -> u32 {
|
||||
5
|
||||
}
|
||||
|
||||
fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
fn associated_return_a_string() -> String {
|
||||
String::from("")
|
||||
}
|
||||
|
||||
fn test_method_call(&self) {
|
||||
// Everything here should be lint
|
||||
|
||||
let v: u32 = self.return_an_int();
|
||||
let v: &u32 = self.return_a_ref();
|
||||
let v: &Slice = self.return_a_ref_to_struct();
|
||||
}
|
||||
}
|
||||
|
||||
fn test_generics() {
|
||||
// The type annotation is needed to determine T
|
||||
let _c: Cake<i32> = make_something();
|
||||
|
||||
// The type annotation is needed to determine the topic
|
||||
let _c: Cake<u8> = make_cake();
|
||||
|
||||
// This could be lint, but currently doesn't
|
||||
let _c: Cake<u8> = make_cake::<u8>();
|
||||
|
||||
// This could be lint, but currently doesn't
|
||||
let _c: u8 = make_something::<u8>();
|
||||
|
||||
// This could be lint, but currently doesn't
|
||||
let _c: u8 = plus_one(5_u8);
|
||||
|
||||
// Annotation needed otherwise T is i32
|
||||
let _c: u8 = plus_one(5);
|
||||
|
||||
// This could be lint, but currently doesn't
|
||||
let _return: String = String::from("test");
|
||||
}
|
||||
|
||||
fn test_non_locals() {
|
||||
// This shouldn't be lint
|
||||
fn _arg(x: u32) -> u32 {
|
||||
x
|
||||
}
|
||||
|
||||
// This could lint, but probably shouldn't
|
||||
let _closure_arg = |x: u32| x;
|
||||
}
|
||||
|
||||
fn test_complex_types() {
|
||||
// Shouldn't be lint, since the literal will be i32 otherwise
|
||||
let _u8: u8 = 128;
|
||||
|
||||
// This could be lint, but currently doesn't
|
||||
let _tuple_i32: (i32, i32) = (12, 13);
|
||||
|
||||
// Shouldn't be lint, since the tuple will be i32 otherwise
|
||||
let _tuple_u32: (u32, u32) = (1, 2);
|
||||
|
||||
// Should be lint, since the type is determined by the init value, but currently doesn't
|
||||
let _tuple_u32: (u32, u32) = (3_u32, 4_u32);
|
||||
|
||||
// This could be lint, but currently doesn't
|
||||
let _array: [i32; 3] = [5, 6, 7];
|
||||
|
||||
// Shouldn't be lint
|
||||
let _array: [u32; 2] = [8, 9];
|
||||
}
|
||||
|
||||
fn test_functions() {
|
||||
// Everything here should be lint
|
||||
|
||||
let _return: String = return_a_string();
|
||||
|
||||
let _return: Pie = return_a_struct();
|
||||
|
||||
let _return: Pizza = return_an_enum();
|
||||
|
||||
let _return: u32 = return_an_int();
|
||||
|
||||
let _return: String = String::new();
|
||||
|
||||
let new_pie: Pie = Pie::new();
|
||||
|
||||
let _return: u32 = new_pie.return_an_int();
|
||||
|
||||
let _return: u32 = Pie::associated_return_an_int();
|
||||
|
||||
let _return: String = Pie::associated_return_a_string();
|
||||
}
|
||||
|
||||
fn test_simple_types() {
|
||||
// Everything here should be lint
|
||||
|
||||
let _var: u32 = u32::MAX;
|
||||
|
||||
let _var: u32 = 5_u32;
|
||||
|
||||
let _var: &str = "test";
|
||||
|
||||
let _var: &[u8] = b"test";
|
||||
|
||||
let _var: bool = false;
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
106
tests/ui/redundant_type_annotations.stderr
Normal file
106
tests/ui/redundant_type_annotations.stderr
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
error: redundant type annotation
|
||||
--> $DIR/redundant_type_annotations.rs:81:9
|
||||
|
|
||||
LL | let v: u32 = self.return_an_int();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::redundant-type-annotations` implied by `-D warnings`
|
||||
|
||||
error: redundant type annotation
|
||||
--> $DIR/redundant_type_annotations.rs:82:9
|
||||
|
|
||||
LL | let v: &u32 = self.return_a_ref();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: redundant type annotation
|
||||
--> $DIR/redundant_type_annotations.rs:83:9
|
||||
|
|
||||
LL | let v: &Slice = self.return_a_ref_to_struct();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: redundant type annotation
|
||||
--> $DIR/redundant_type_annotations.rs:143:5
|
||||
|
|
||||
LL | let _return: String = return_a_string();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: redundant type annotation
|
||||
--> $DIR/redundant_type_annotations.rs:145:5
|
||||
|
|
||||
LL | let _return: Pie = return_a_struct();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: redundant type annotation
|
||||
--> $DIR/redundant_type_annotations.rs:147:5
|
||||
|
|
||||
LL | let _return: Pizza = return_an_enum();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: redundant type annotation
|
||||
--> $DIR/redundant_type_annotations.rs:149:5
|
||||
|
|
||||
LL | let _return: u32 = return_an_int();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: redundant type annotation
|
||||
--> $DIR/redundant_type_annotations.rs:151:5
|
||||
|
|
||||
LL | let _return: String = String::new();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: redundant type annotation
|
||||
--> $DIR/redundant_type_annotations.rs:153:5
|
||||
|
|
||||
LL | let new_pie: Pie = Pie::new();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: redundant type annotation
|
||||
--> $DIR/redundant_type_annotations.rs:155:5
|
||||
|
|
||||
LL | let _return: u32 = new_pie.return_an_int();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: redundant type annotation
|
||||
--> $DIR/redundant_type_annotations.rs:157:5
|
||||
|
|
||||
LL | let _return: u32 = Pie::associated_return_an_int();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: redundant type annotation
|
||||
--> $DIR/redundant_type_annotations.rs:159:5
|
||||
|
|
||||
LL | let _return: String = Pie::associated_return_a_string();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: redundant type annotation
|
||||
--> $DIR/redundant_type_annotations.rs:165:5
|
||||
|
|
||||
LL | let _var: u32 = u32::MAX;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: redundant type annotation
|
||||
--> $DIR/redundant_type_annotations.rs:167:5
|
||||
|
|
||||
LL | let _var: u32 = 5_u32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: redundant type annotation
|
||||
--> $DIR/redundant_type_annotations.rs:169:5
|
||||
|
|
||||
LL | let _var: &str = "test";
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: redundant type annotation
|
||||
--> $DIR/redundant_type_annotations.rs:171:5
|
||||
|
|
||||
LL | let _var: &[u8] = b"test";
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: redundant type annotation
|
||||
--> $DIR/redundant_type_annotations.rs:173:5
|
||||
|
|
||||
LL | let _var: bool = false;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 17 previous errors
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue