about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--clippy_lints/src/declared_lints.rs1
-rw-r--r--clippy_lints/src/let_with_type_underscore.rs45
-rw-r--r--clippy_lints/src/lib.rs2
-rw-r--r--tests/ui/crashes/ice-6179.rs2
-rw-r--r--tests/ui/default_numeric_fallback_f64.fixed3
-rw-r--r--tests/ui/default_numeric_fallback_f64.rs3
-rw-r--r--tests/ui/default_numeric_fallback_f64.stderr48
-rw-r--r--tests/ui/default_numeric_fallback_i32.fixed3
-rw-r--r--tests/ui/default_numeric_fallback_i32.rs3
-rw-r--r--tests/ui/default_numeric_fallback_i32.stderr52
-rw-r--r--tests/ui/let_with_type_underscore.rs19
-rw-r--r--tests/ui/let_with_type_underscore.stderr39
-rw-r--r--tests/ui/manual_rem_euclid.fixed1
-rw-r--r--tests/ui/manual_rem_euclid.rs1
-rw-r--r--tests/ui/manual_rem_euclid.stderr20
16 files changed, 178 insertions, 65 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d797b30f47b..82911231ec9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4643,6 +4643,7 @@ Released 2018-09-13
 [`let_underscore_must_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_must_use
 [`let_underscore_untyped`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_untyped
 [`let_unit_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value
+[`let_with_type_underscore`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_with_type_underscore
 [`linkedlist`]: https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist
 [`logic_bug`]: https://rust-lang.github.io/rust-clippy/master/index.html#logic_bug
 [`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#lossy_float_literal
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index d3b9cc67579..cc6024b87cd 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -227,6 +227,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::let_underscore::LET_UNDERSCORE_LOCK_INFO,
     crate::let_underscore::LET_UNDERSCORE_MUST_USE_INFO,
     crate::let_underscore::LET_UNDERSCORE_UNTYPED_INFO,
+    crate::let_with_type_underscore::LET_WITH_TYPE_UNDERSCORE_INFO,
     crate::lifetimes::EXTRA_UNUSED_LIFETIMES_INFO,
     crate::lifetimes::NEEDLESS_LIFETIMES_INFO,
     crate::literal_representation::DECIMAL_LITERAL_REPRESENTATION_INFO,
diff --git a/clippy_lints/src/let_with_type_underscore.rs b/clippy_lints/src/let_with_type_underscore.rs
new file mode 100644
index 00000000000..ba51973f2f9
--- /dev/null
+++ b/clippy_lints/src/let_with_type_underscore.rs
@@ -0,0 +1,45 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use rustc_hir::*;
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::lint::in_external_macro;
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Detects when a variable is declared with an explicit type of `_`.
+    /// ### Why is this bad?
+    /// It adds noise, `: _` provides zero clarity or utility.
+    /// ### Example
+    /// ```rust,ignore
+    /// let my_number: _ = 1;
+    /// ```
+    /// Use instead:
+    /// ```rust,ignore
+    /// let my_number = 1;
+    /// ```
+    #[clippy::version = "1.69.0"]
+    pub LET_WITH_TYPE_UNDERSCORE,
+    complexity,
+    "unneeded underscore type (`_`) in a variable declaration"
+}
+declare_lint_pass!(UnderscoreTyped => [LET_WITH_TYPE_UNDERSCORE]);
+
+impl LateLintPass<'_> for UnderscoreTyped {
+    fn check_local<'tcx>(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) {
+        if_chain! {
+            if !in_external_macro(cx.tcx.sess, local.span);
+            if let Some(ty) = local.ty; // Ensure that it has a type defined
+            if let TyKind::Infer = &ty.kind; // that type is '_'
+            if local.span.ctxt() == ty.span.ctxt();
+            then {
+                span_lint_and_help(cx,
+                    LET_WITH_TYPE_UNDERSCORE,
+                    local.span,
+                    "variable declared with type underscore",
+                    Some(ty.span.with_lo(local.pat.span.hi())),
+                    "remove the explicit type `_` declaration"
+                )
+            }
+        };
+    }
+}
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index ea1e0ab506c..ce50c4657d8 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -167,6 +167,7 @@ mod large_stack_arrays;
 mod len_zero;
 mod let_if_seq;
 mod let_underscore;
+mod let_with_type_underscore;
 mod lifetimes;
 mod literal_representation;
 mod loops;
@@ -930,6 +931,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(collection_is_never_read::CollectionIsNeverRead));
     store.register_late_pass(|_| Box::new(missing_assert_message::MissingAssertMessage));
     store.register_early_pass(|| Box::new(redundant_async_block::RedundantAsyncBlock));
+    store.register_late_pass(|_| Box::new(let_with_type_underscore::UnderscoreTyped));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
 
diff --git a/tests/ui/crashes/ice-6179.rs b/tests/ui/crashes/ice-6179.rs
index 4fe92d356c4..ce1895851e2 100644
--- a/tests/ui/crashes/ice-6179.rs
+++ b/tests/ui/crashes/ice-6179.rs
@@ -2,7 +2,7 @@
 //! The ICE is mainly caused by using `hir_ty_to_ty`. See the discussion in the PR for details.
 
 #![warn(clippy::use_self)]
-#![allow(dead_code)]
+#![allow(dead_code, clippy::let_with_type_underscore)]
 
 struct Foo;
 
diff --git a/tests/ui/default_numeric_fallback_f64.fixed b/tests/ui/default_numeric_fallback_f64.fixed
index a370ccc7696..a9e5fd159af 100644
--- a/tests/ui/default_numeric_fallback_f64.fixed
+++ b/tests/ui/default_numeric_fallback_f64.fixed
@@ -9,7 +9,8 @@
     clippy::unnecessary_operation,
     clippy::branches_sharing_code,
     clippy::match_single_binding,
-    clippy::let_unit_value
+    clippy::let_unit_value,
+    clippy::let_with_type_underscore
 )]
 
 #[macro_use]
diff --git a/tests/ui/default_numeric_fallback_f64.rs b/tests/ui/default_numeric_fallback_f64.rs
index 2476fe95141..085f8f452b2 100644
--- a/tests/ui/default_numeric_fallback_f64.rs
+++ b/tests/ui/default_numeric_fallback_f64.rs
@@ -9,7 +9,8 @@
     clippy::unnecessary_operation,
     clippy::branches_sharing_code,
     clippy::match_single_binding,
-    clippy::let_unit_value
+    clippy::let_unit_value,
+    clippy::let_with_type_underscore
 )]
 
 #[macro_use]
diff --git a/tests/ui/default_numeric_fallback_f64.stderr b/tests/ui/default_numeric_fallback_f64.stderr
index 5df2f642388..44c6f1a9bea 100644
--- a/tests/ui/default_numeric_fallback_f64.stderr
+++ b/tests/ui/default_numeric_fallback_f64.stderr
@@ -1,5 +1,5 @@
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:21:17
+  --> $DIR/default_numeric_fallback_f64.rs:22:17
    |
 LL |         let x = 0.12;
    |                 ^^^^ help: consider adding suffix: `0.12_f64`
@@ -7,139 +7,139 @@ LL |         let x = 0.12;
    = note: `-D clippy::default-numeric-fallback` implied by `-D warnings`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:22:18
+  --> $DIR/default_numeric_fallback_f64.rs:23:18
    |
 LL |         let x = [1., 2., 3.];
    |                  ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:22:22
+  --> $DIR/default_numeric_fallback_f64.rs:23:22
    |
 LL |         let x = [1., 2., 3.];
    |                      ^^ help: consider adding suffix: `2.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:22:26
+  --> $DIR/default_numeric_fallback_f64.rs:23:26
    |
 LL |         let x = [1., 2., 3.];
    |                          ^^ help: consider adding suffix: `3.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:23:28
+  --> $DIR/default_numeric_fallback_f64.rs:24:28
    |
 LL |         let x = if true { (1., 2.) } else { (3., 4.) };
    |                            ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:23:32
+  --> $DIR/default_numeric_fallback_f64.rs:24:32
    |
 LL |         let x = if true { (1., 2.) } else { (3., 4.) };
    |                                ^^ help: consider adding suffix: `2.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:23:46
+  --> $DIR/default_numeric_fallback_f64.rs:24:46
    |
 LL |         let x = if true { (1., 2.) } else { (3., 4.) };
    |                                              ^^ help: consider adding suffix: `3.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:23:50
+  --> $DIR/default_numeric_fallback_f64.rs:24:50
    |
 LL |         let x = if true { (1., 2.) } else { (3., 4.) };
    |                                                  ^^ help: consider adding suffix: `4.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:24:23
+  --> $DIR/default_numeric_fallback_f64.rs:25:23
    |
 LL |         let x = match 1. {
    |                       ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:25:18
+  --> $DIR/default_numeric_fallback_f64.rs:26:18
    |
 LL |             _ => 1.,
    |                  ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:44:21
+  --> $DIR/default_numeric_fallback_f64.rs:45:21
    |
 LL |             let y = 1.;
    |                     ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:52:21
+  --> $DIR/default_numeric_fallback_f64.rs:53:21
    |
 LL |             let y = 1.;
    |                     ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:58:21
+  --> $DIR/default_numeric_fallback_f64.rs:59:21
    |
 LL |             let y = 1.;
    |                     ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:66:21
+  --> $DIR/default_numeric_fallback_f64.rs:67:21
    |
 LL |             let y = 1.;
    |                     ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:78:9
+  --> $DIR/default_numeric_fallback_f64.rs:79:9
    |
 LL |         1.
    |         ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:84:27
+  --> $DIR/default_numeric_fallback_f64.rs:85:27
    |
 LL |         let f = || -> _ { 1. };
    |                           ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:88:29
+  --> $DIR/default_numeric_fallback_f64.rs:89:29
    |
 LL |         let f = || -> f64 { 1. };
    |                             ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:102:21
+  --> $DIR/default_numeric_fallback_f64.rs:103:21
    |
 LL |         generic_arg(1.);
    |                     ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:105:32
+  --> $DIR/default_numeric_fallback_f64.rs:106:32
    |
 LL |         let x: _ = generic_arg(1.);
    |                                ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:123:28
+  --> $DIR/default_numeric_fallback_f64.rs:124:28
    |
 LL |         GenericStruct { x: 1. };
    |                            ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:126:36
+  --> $DIR/default_numeric_fallback_f64.rs:127:36
    |
 LL |         let _ = GenericStruct { x: 1. };
    |                                    ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:144:24
+  --> $DIR/default_numeric_fallback_f64.rs:145:24
    |
 LL |         GenericEnum::X(1.);
    |                        ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:164:23
+  --> $DIR/default_numeric_fallback_f64.rs:165:23
    |
 LL |         s.generic_arg(1.);
    |                       ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:171:21
+  --> $DIR/default_numeric_fallback_f64.rs:172:21
    |
 LL |             let x = 22.;
    |                     ^^^ help: consider adding suffix: `22.0_f64`
diff --git a/tests/ui/default_numeric_fallback_i32.fixed b/tests/ui/default_numeric_fallback_i32.fixed
index 3f4994f0453..63ac4d5aeb6 100644
--- a/tests/ui/default_numeric_fallback_i32.fixed
+++ b/tests/ui/default_numeric_fallback_i32.fixed
@@ -9,7 +9,8 @@
     clippy::no_effect,
     clippy::unnecessary_operation,
     clippy::branches_sharing_code,
-    clippy::let_unit_value
+    clippy::let_unit_value,
+    clippy::let_with_type_underscore
 )]
 
 #[macro_use]
diff --git a/tests/ui/default_numeric_fallback_i32.rs b/tests/ui/default_numeric_fallback_i32.rs
index 2df0e09787f..28e6eceb80e 100644
--- a/tests/ui/default_numeric_fallback_i32.rs
+++ b/tests/ui/default_numeric_fallback_i32.rs
@@ -9,7 +9,8 @@
     clippy::no_effect,
     clippy::unnecessary_operation,
     clippy::branches_sharing_code,
-    clippy::let_unit_value
+    clippy::let_unit_value,
+    clippy::let_with_type_underscore
 )]
 
 #[macro_use]
diff --git a/tests/ui/default_numeric_fallback_i32.stderr b/tests/ui/default_numeric_fallback_i32.stderr
index 6f219c3fc2b..dd91574d5b3 100644
--- a/tests/ui/default_numeric_fallback_i32.stderr
+++ b/tests/ui/default_numeric_fallback_i32.stderr
@@ -1,5 +1,5 @@
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:21:17
+  --> $DIR/default_numeric_fallback_i32.rs:22:17
    |
 LL |         let x = 22;
    |                 ^^ help: consider adding suffix: `22_i32`
@@ -7,151 +7,151 @@ LL |         let x = 22;
    = note: `-D clippy::default-numeric-fallback` implied by `-D warnings`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:22:18
+  --> $DIR/default_numeric_fallback_i32.rs:23:18
    |
 LL |         let x = [1, 2, 3];
    |                  ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:22:21
+  --> $DIR/default_numeric_fallback_i32.rs:23:21
    |
 LL |         let x = [1, 2, 3];
    |                     ^ help: consider adding suffix: `2_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:22:24
+  --> $DIR/default_numeric_fallback_i32.rs:23:24
    |
 LL |         let x = [1, 2, 3];
    |                        ^ help: consider adding suffix: `3_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:23:28
+  --> $DIR/default_numeric_fallback_i32.rs:24:28
    |
 LL |         let x = if true { (1, 2) } else { (3, 4) };
    |                            ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:23:31
+  --> $DIR/default_numeric_fallback_i32.rs:24:31
    |
 LL |         let x = if true { (1, 2) } else { (3, 4) };
    |                               ^ help: consider adding suffix: `2_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:23:44
+  --> $DIR/default_numeric_fallback_i32.rs:24:44
    |
 LL |         let x = if true { (1, 2) } else { (3, 4) };
    |                                            ^ help: consider adding suffix: `3_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:23:47
+  --> $DIR/default_numeric_fallback_i32.rs:24:47
    |
 LL |         let x = if true { (1, 2) } else { (3, 4) };
    |                                               ^ help: consider adding suffix: `4_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:24:23
+  --> $DIR/default_numeric_fallback_i32.rs:25:23
    |
 LL |         let x = match 1 {
    |                       ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:25:13
+  --> $DIR/default_numeric_fallback_i32.rs:26:13
    |
 LL |             1 => 1,
    |             ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:25:18
+  --> $DIR/default_numeric_fallback_i32.rs:26:18
    |
 LL |             1 => 1,
    |                  ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:26:18
+  --> $DIR/default_numeric_fallback_i32.rs:27:18
    |
 LL |             _ => 2,
    |                  ^ help: consider adding suffix: `2_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:45:21
+  --> $DIR/default_numeric_fallback_i32.rs:46:21
    |
 LL |             let y = 1;
    |                     ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:53:21
+  --> $DIR/default_numeric_fallback_i32.rs:54:21
    |
 LL |             let y = 1;
    |                     ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:59:21
+  --> $DIR/default_numeric_fallback_i32.rs:60:21
    |
 LL |             let y = 1;
    |                     ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:67:21
+  --> $DIR/default_numeric_fallback_i32.rs:68:21
    |
 LL |             let y = 1;
    |                     ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:79:9
+  --> $DIR/default_numeric_fallback_i32.rs:80:9
    |
 LL |         1
    |         ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:85:27
+  --> $DIR/default_numeric_fallback_i32.rs:86:27
    |
 LL |         let f = || -> _ { 1 };
    |                           ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:89:29
+  --> $DIR/default_numeric_fallback_i32.rs:90:29
    |
 LL |         let f = || -> i32 { 1 };
    |                             ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:103:21
+  --> $DIR/default_numeric_fallback_i32.rs:104:21
    |
 LL |         generic_arg(1);
    |                     ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:106:32
+  --> $DIR/default_numeric_fallback_i32.rs:107:32
    |
 LL |         let x: _ = generic_arg(1);
    |                                ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:124:28
+  --> $DIR/default_numeric_fallback_i32.rs:125:28
    |
 LL |         GenericStruct { x: 1 };
    |                            ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:127:36
+  --> $DIR/default_numeric_fallback_i32.rs:128:36
    |
 LL |         let _ = GenericStruct { x: 1 };
    |                                    ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:145:24
+  --> $DIR/default_numeric_fallback_i32.rs:146:24
    |
 LL |         GenericEnum::X(1);
    |                        ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:165:23
+  --> $DIR/default_numeric_fallback_i32.rs:166:23
    |
 LL |         s.generic_arg(1);
    |                       ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:172:21
+  --> $DIR/default_numeric_fallback_i32.rs:173:21
    |
 LL |             let x = 22;
    |                     ^^ help: consider adding suffix: `22_i32`
diff --git a/tests/ui/let_with_type_underscore.rs b/tests/ui/let_with_type_underscore.rs
new file mode 100644
index 00000000000..175718b94c8
--- /dev/null
+++ b/tests/ui/let_with_type_underscore.rs
@@ -0,0 +1,19 @@
+#![allow(unused)]
+#![warn(clippy::let_with_type_underscore)]
+#![allow(clippy::let_unit_value)]
+
+fn func() -> &'static str {
+    ""
+}
+
+fn main() {
+    // Will lint
+    let x: _ = 1;
+    let _: _ = 2;
+    let x: _ = func();
+
+    let x = 1; // Will not lint, Rust inferres this to an integer before Clippy
+    let x = func();
+    let x: Vec<_> = Vec::<u32>::new();
+    let x: [_; 1] = [1];
+}
diff --git a/tests/ui/let_with_type_underscore.stderr b/tests/ui/let_with_type_underscore.stderr
new file mode 100644
index 00000000000..16bf83c708f
--- /dev/null
+++ b/tests/ui/let_with_type_underscore.stderr
@@ -0,0 +1,39 @@
+error: variable declared with type underscore
+  --> $DIR/let_with_type_underscore.rs:11:5
+   |
+LL |     let x: _ = 1;
+   |     ^^^^^^^^^^^^^
+   |
+help: remove the explicit type `_` declaration
+  --> $DIR/let_with_type_underscore.rs:11:10
+   |
+LL |     let x: _ = 1;
+   |          ^^^
+   = note: `-D clippy::let-with-type-underscore` implied by `-D warnings`
+
+error: variable declared with type underscore
+  --> $DIR/let_with_type_underscore.rs:12:5
+   |
+LL |     let _: _ = 2;
+   |     ^^^^^^^^^^^^^
+   |
+help: remove the explicit type `_` declaration
+  --> $DIR/let_with_type_underscore.rs:12:10
+   |
+LL |     let _: _ = 2;
+   |          ^^^
+
+error: variable declared with type underscore
+  --> $DIR/let_with_type_underscore.rs:13:5
+   |
+LL |     let x: _ = func();
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+help: remove the explicit type `_` declaration
+  --> $DIR/let_with_type_underscore.rs:13:10
+   |
+LL |     let x: _ = func();
+   |          ^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/manual_rem_euclid.fixed b/tests/ui/manual_rem_euclid.fixed
index 4cdc0546a74..6916a284a20 100644
--- a/tests/ui/manual_rem_euclid.fixed
+++ b/tests/ui/manual_rem_euclid.fixed
@@ -2,6 +2,7 @@
 // aux-build:macro_rules.rs
 
 #![warn(clippy::manual_rem_euclid)]
+#![allow(clippy::let_with_type_underscore)]
 
 #[macro_use]
 extern crate macro_rules;
diff --git a/tests/ui/manual_rem_euclid.rs b/tests/ui/manual_rem_euclid.rs
index 58a9e20f38b..412dbddb426 100644
--- a/tests/ui/manual_rem_euclid.rs
+++ b/tests/ui/manual_rem_euclid.rs
@@ -2,6 +2,7 @@
 // aux-build:macro_rules.rs
 
 #![warn(clippy::manual_rem_euclid)]
+#![allow(clippy::let_with_type_underscore)]
 
 #[macro_use]
 extern crate macro_rules;
diff --git a/tests/ui/manual_rem_euclid.stderr b/tests/ui/manual_rem_euclid.stderr
index e3122a588b6..6d06654638b 100644
--- a/tests/ui/manual_rem_euclid.stderr
+++ b/tests/ui/manual_rem_euclid.stderr
@@ -1,5 +1,5 @@
 error: manual `rem_euclid` implementation
-  --> $DIR/manual_rem_euclid.rs:19:18
+  --> $DIR/manual_rem_euclid.rs:20:18
    |
 LL |     let _: i32 = ((value % 4) + 4) % 4;
    |                  ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
@@ -7,31 +7,31 @@ LL |     let _: i32 = ((value % 4) + 4) % 4;
    = note: `-D clippy::manual-rem-euclid` implied by `-D warnings`
 
 error: manual `rem_euclid` implementation
-  --> $DIR/manual_rem_euclid.rs:20:18
+  --> $DIR/manual_rem_euclid.rs:21:18
    |
 LL |     let _: i32 = (4 + (value % 4)) % 4;
    |                  ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
 
 error: manual `rem_euclid` implementation
-  --> $DIR/manual_rem_euclid.rs:21:18
+  --> $DIR/manual_rem_euclid.rs:22:18
    |
 LL |     let _: i32 = (value % 4 + 4) % 4;
    |                  ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
 
 error: manual `rem_euclid` implementation
-  --> $DIR/manual_rem_euclid.rs:22:18
+  --> $DIR/manual_rem_euclid.rs:23:18
    |
 LL |     let _: i32 = (4 + value % 4) % 4;
    |                  ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
 
 error: manual `rem_euclid` implementation
-  --> $DIR/manual_rem_euclid.rs:23:22
+  --> $DIR/manual_rem_euclid.rs:24:22
    |
 LL |     let _: i32 = 1 + (4 + value % 4) % 4;
    |                      ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
 
 error: manual `rem_euclid` implementation
-  --> $DIR/manual_rem_euclid.rs:12:22
+  --> $DIR/manual_rem_euclid.rs:13:22
    |
 LL |         let _: i32 = ((value % 4) + 4) % 4;
    |                      ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
@@ -42,25 +42,25 @@ LL |     internal_rem_euclid!();
    = note: this error originates in the macro `internal_rem_euclid` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: manual `rem_euclid` implementation
-  --> $DIR/manual_rem_euclid.rs:49:5
+  --> $DIR/manual_rem_euclid.rs:50:5
    |
 LL |     ((num % 4) + 4) % 4
    |     ^^^^^^^^^^^^^^^^^^^ help: consider using: `num.rem_euclid(4)`
 
 error: manual `rem_euclid` implementation
-  --> $DIR/manual_rem_euclid.rs:54:5
+  --> $DIR/manual_rem_euclid.rs:55:5
    |
 LL |     ((num % 4) + 4) % 4
    |     ^^^^^^^^^^^^^^^^^^^ help: consider using: `num.rem_euclid(4)`
 
 error: manual `rem_euclid` implementation
-  --> $DIR/manual_rem_euclid.rs:66:18
+  --> $DIR/manual_rem_euclid.rs:67:18
    |
 LL |     let _: i32 = ((x % 4) + 4) % 4;
    |                  ^^^^^^^^^^^^^^^^^ help: consider using: `x.rem_euclid(4)`
 
 error: manual `rem_euclid` implementation
-  --> $DIR/manual_rem_euclid.rs:79:18
+  --> $DIR/manual_rem_euclid.rs:80:18
    |
 LL |     let _: i32 = ((x % 4) + 4) % 4;
    |                  ^^^^^^^^^^^^^^^^^ help: consider using: `x.rem_euclid(4)`