about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--clippy_dev/src/new_lint.rs9
-rw-r--r--clippy_dev/src/update_lints.rs6
-rw-r--r--clippy_lints/src/declared_lints.rs1
-rw-r--r--clippy_lints/src/entry.rs8
-rw-r--r--clippy_lints/src/inconsistent_struct_constructor.rs4
-rw-r--r--clippy_lints/src/let_underscore.rs52
-rw-r--r--clippy_lints/src/literal_representation.rs2
-rw-r--r--clippy_lints/src/module_style.rs2
-rw-r--r--clippy_utils/src/numeric_literal.rs2
-rw-r--r--clippy_utils/src/sugg.rs8
-rw-r--r--lintcheck/src/main.rs12
-rw-r--r--tests/ui/let_underscore_untyped.rs54
-rw-r--r--tests/ui/let_underscore_untyped.stderr51
-rw-r--r--tests/ui/map_flatten_fixable.fixed1
-rw-r--r--tests/ui/map_flatten_fixable.rs1
-rw-r--r--tests/ui/map_flatten_fixable.stderr18
-rw-r--r--tests/ui/methods.rs1
-rw-r--r--tests/ui/methods.stderr4
19 files changed, 199 insertions, 38 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d14a6b5d31e..feab94c52a5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4494,6 +4494,7 @@ Released 2018-09-13
 [`let_underscore_future`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_future
 [`let_underscore_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_lock
 [`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
 [`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
diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs
index ec7f1dd0d84..420214d9256 100644
--- a/clippy_dev/src/new_lint.rs
+++ b/clippy_dev/src/new_lint.rs
@@ -1,5 +1,6 @@
 use crate::clippy_project_root;
 use indoc::{formatdoc, writedoc};
+use std::fmt;
 use std::fmt::Write as _;
 use std::fs::{self, OpenOptions};
 use std::io::prelude::*;
@@ -256,7 +257,7 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
         )
     });
 
-    let _ = write!(result, "{}", get_lint_declaration(&name_upper, category));
+    let _: fmt::Result = write!(result, "{}", get_lint_declaration(&name_upper, category));
 
     result.push_str(&if enable_msrv {
         formatdoc!(
@@ -353,7 +354,7 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R
     let mut lint_file_contents = String::new();
 
     if enable_msrv {
-        let _ = writedoc!(
+        let _: fmt::Result = writedoc!(
             lint_file_contents,
             r#"
                 use clippy_utils::msrvs::{{self, Msrv}};
@@ -373,7 +374,7 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R
             name_upper = name_upper,
         );
     } else {
-        let _ = writedoc!(
+        let _: fmt::Result = writedoc!(
             lint_file_contents,
             r#"
                 use rustc_lint::{{{context_import}, LintContext}};
@@ -521,7 +522,7 @@ fn setup_mod_file(path: &Path, lint: &LintData<'_>) -> io::Result<&'static str>
         .chain(std::iter::once(&*lint_name_upper))
         .filter(|s| !s.is_empty())
     {
-        let _ = write!(new_arr_content, "\n    {ident},");
+        let _: fmt::Result = write!(new_arr_content, "\n    {ident},");
     }
     new_arr_content.push('\n');
 
diff --git a/clippy_dev/src/update_lints.rs b/clippy_dev/src/update_lints.rs
index 837618c9294..779e4d0e1e3 100644
--- a/clippy_dev/src/update_lints.rs
+++ b/clippy_dev/src/update_lints.rs
@@ -5,7 +5,7 @@ use itertools::Itertools;
 use rustc_lexer::{tokenize, unescape, LiteralKind, TokenKind};
 use std::collections::{HashMap, HashSet};
 use std::ffi::OsStr;
-use std::fmt::Write;
+use std::fmt::{self, Write};
 use std::fs::{self, OpenOptions};
 use std::io::{self, Read, Seek, SeekFrom, Write as _};
 use std::ops::Range;
@@ -691,7 +691,7 @@ fn gen_deprecated(lints: &[DeprecatedLint]) -> String {
     let mut output = GENERATED_FILE_COMMENT.to_string();
     output.push_str("{\n");
     for lint in lints {
-        let _ = write!(
+        let _: fmt::Result = write!(
             output,
             concat!(
                 "    store.register_removed(\n",
@@ -726,7 +726,7 @@ fn gen_declared_lints<'a>(
         if !is_public {
             output.push_str("    #[cfg(feature = \"internal\")]\n");
         }
-        let _ = writeln!(output, "    crate::{module_name}::{lint_name}_INFO,");
+        let _: fmt::Result = writeln!(output, "    crate::{module_name}::{lint_name}_INFO,");
     }
     output.push_str("];\n");
 
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index f543a2d3a1c..0962c3ce66c 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -224,6 +224,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::let_underscore::LET_UNDERSCORE_FUTURE_INFO,
     crate::let_underscore::LET_UNDERSCORE_LOCK_INFO,
     crate::let_underscore::LET_UNDERSCORE_MUST_USE_INFO,
+    crate::let_underscore::LET_UNDERSCORE_UNTYPED_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/entry.rs b/clippy_lints/src/entry.rs
index ed9d94cdec3..48a54f60253 100644
--- a/clippy_lints/src/entry.rs
+++ b/clippy_lints/src/entry.rs
@@ -6,7 +6,7 @@ use clippy_utils::{
     source::{reindent_multiline, snippet_indent, snippet_with_applicability, snippet_with_context},
     SpanlessEq,
 };
-use core::fmt::Write;
+use core::fmt::{self, Write};
 use rustc_errors::Applicability;
 use rustc_hir::{
     hir_id::HirIdSet,
@@ -536,7 +536,7 @@ impl<'tcx> InsertSearchResults<'tcx> {
             if is_expr_used_or_unified(cx.tcx, insertion.call) {
                 write_wrapped(&mut res, insertion, ctxt, app);
             } else {
-                let _ = write!(
+                let _: fmt::Result = write!(
                     res,
                     "e.insert({})",
                     snippet_with_context(cx, insertion.value.span, ctxt, "..", app).0
@@ -552,7 +552,7 @@ impl<'tcx> InsertSearchResults<'tcx> {
         (
             self.snippet(cx, span, app, |res, insertion, ctxt, app| {
                 // Insertion into a map would return `Some(&mut value)`, but the entry returns `&mut value`
-                let _ = write!(
+                let _: fmt::Result = write!(
                     res,
                     "Some(e.insert({}))",
                     snippet_with_context(cx, insertion.value.span, ctxt, "..", app).0
@@ -566,7 +566,7 @@ impl<'tcx> InsertSearchResults<'tcx> {
         (
             self.snippet(cx, span, app, |res, insertion, ctxt, app| {
                 // Insertion into a map would return `None`, but the entry returns a mutable reference.
-                let _ = if is_expr_final_block_expr(cx.tcx, insertion.call) {
+                let _: fmt::Result = if is_expr_final_block_expr(cx.tcx, insertion.call) {
                     write!(
                         res,
                         "e.insert({});\n{}None",
diff --git a/clippy_lints/src/inconsistent_struct_constructor.rs b/clippy_lints/src/inconsistent_struct_constructor.rs
index e2f2d3d42e6..1ad886f2cf3 100644
--- a/clippy_lints/src/inconsistent_struct_constructor.rs
+++ b/clippy_lints/src/inconsistent_struct_constructor.rs
@@ -7,7 +7,7 @@ use rustc_hir::{self as hir, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::symbol::Symbol;
-use std::fmt::Write as _;
+use std::fmt::{self, Write as _};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -90,7 +90,7 @@ impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor {
                 let mut fields_snippet = String::new();
                 let (last_ident, idents) = ordered_fields.split_last().unwrap();
                 for ident in idents {
-                    let _ = write!(fields_snippet, "{ident}, ");
+                    let _: fmt::Result = write!(fields_snippet, "{ident}, ");
                 }
                 fields_snippet.push_str(&last_ident.to_string());
 
diff --git a/clippy_lints/src/let_underscore.rs b/clippy_lints/src/let_underscore.rs
index f8e35950980..7600777fab9 100644
--- a/clippy_lints/src/let_underscore.rs
+++ b/clippy_lints/src/let_underscore.rs
@@ -90,7 +90,45 @@ declare_clippy_lint! {
     "non-binding `let` on a future"
 }
 
-declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK, LET_UNDERSCORE_FUTURE]);
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for `let _ = <expr>` without a type annotation, and suggests to either provide one,
+    /// or remove the `let` keyword altogether.
+    ///
+    /// ### Why is this bad?
+    /// The `let _ = <expr>` expression ignores the value of `<expr>` but will remain doing so even
+    /// if the type were to change, thus potentially introducing subtle bugs. By supplying a type
+    /// annotation, one will be forced to re-visit the decision to ignore the value in such cases.
+    ///
+    /// ### Known problems
+    /// The `_ = <expr>` is not properly supported by some tools (e.g. IntelliJ) and may seem odd
+    /// to many developers. This lint also partially overlaps with the other `let_underscore_*`
+    /// lints.
+    ///
+    /// ### Example
+    /// ```rust
+    /// fn foo() -> Result<u32, ()> {
+    ///     Ok(123)
+    /// }
+    /// let _ = foo();
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// fn foo() -> Result<u32, ()> {
+    ///     Ok(123)
+    /// }
+    /// // Either provide a type annotation:
+    /// let _: Result<u32, ()> = foo();
+    /// // …or drop the let keyword:
+    /// _ = foo();
+    /// ```
+    #[clippy::version = "1.69.0"]
+    pub LET_UNDERSCORE_UNTYPED,
+    pedantic,
+    "non-binding `let` without a type annotation"
+}
+
+declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK, LET_UNDERSCORE_FUTURE, LET_UNDERSCORE_UNTYPED]);
 
 const SYNC_GUARD_PATHS: [&[&str]; 3] = [
     &paths::PARKING_LOT_MUTEX_GUARD,
@@ -148,6 +186,18 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
                     "consider explicitly using function result",
                 );
             }
+
+            if local.pat.default_binding_modes && local.ty.is_none() {
+                // When `default_binding_modes` is true, the `let` keyword is present.
+                span_lint_and_help(
+                    cx,
+                    LET_UNDERSCORE_UNTYPED,
+                    local.span,
+                    "non-binding `let` without a type annotation",
+                    None,
+                    "consider adding a type annotation or removing the `let` keyword",
+                );
+            }
         }
     }
 }
diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs
index 879bcca33a8..dadcd9c5135 100644
--- a/clippy_lints/src/literal_representation.rs
+++ b/clippy_lints/src/literal_representation.rs
@@ -488,7 +488,7 @@ impl DecimalLiteralRepresentation {
             then {
                 let hex = format!("{val:#X}");
                 let num_lit = NumericLiteral::new(&hex, num_lit.suffix, false);
-                let _ = Self::do_lint(num_lit.integer).map_err(|warning_type| {
+                let _: Result<(), ()> = Self::do_lint(num_lit.integer).map_err(|warning_type| {
                     warning_type.display(num_lit.format(), cx, span);
                 });
             }
diff --git a/clippy_lints/src/module_style.rs b/clippy_lints/src/module_style.rs
index 0742943dff2..349fcd2274d 100644
--- a/clippy_lints/src/module_style.rs
+++ b/clippy_lints/src/module_style.rs
@@ -134,7 +134,7 @@ fn process_paths_for_mod_files<'a>(
     mod_folders: &mut FxHashSet<&'a OsStr>,
 ) {
     let mut comp = path.components().rev().peekable();
-    let _ = comp.next();
+    let _: Option<_> = comp.next();
     if path.ends_with("mod.rs") {
         mod_folders.insert(comp.peek().map(|c| c.as_os_str()).unwrap_or_default());
     }
diff --git a/clippy_utils/src/numeric_literal.rs b/clippy_utils/src/numeric_literal.rs
index 42bdfd4827f..c225398ad2a 100644
--- a/clippy_utils/src/numeric_literal.rs
+++ b/clippy_utils/src/numeric_literal.rs
@@ -186,7 +186,7 @@ impl<'a> NumericLiteral<'a> {
         // The exponent may have a sign, output it early, otherwise it will be
         // treated as a digit
         if digits.clone().next() == Some('-') {
-            let _ = digits.next();
+            let _: Option<char> = digits.next();
             output.push('-');
         }
 
diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs
index 78fb2e0eb7e..51e270d330c 100644
--- a/clippy_utils/src/sugg.rs
+++ b/clippy_utils/src/sugg.rs
@@ -20,7 +20,7 @@ use rustc_middle::mir::{FakeReadCause, Mutability};
 use rustc_middle::ty;
 use rustc_span::source_map::{BytePos, CharPos, Pos, Span, SyntaxContext};
 use std::borrow::Cow;
-use std::fmt::{Display, Write as _};
+use std::fmt::{self, Display, Write as _};
 use std::ops::{Add, Neg, Not, Sub};
 
 /// A helper type to build suggestion correctly handling parentheses.
@@ -932,7 +932,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
             if cmt.place.projections.is_empty() {
                 // handle item without any projection, that needs an explicit borrowing
                 // i.e.: suggest `&x` instead of `x`
-                let _ = write!(self.suggestion_start, "{start_snip}&{ident_str}");
+                let _: fmt::Result = write!(self.suggestion_start, "{start_snip}&{ident_str}");
             } else {
                 // cases where a parent `Call` or `MethodCall` is using the item
                 // i.e.: suggest `.contains(&x)` for `.find(|x| [1, 2, 3].contains(x)).is_none()`
@@ -947,7 +947,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
                         // given expression is the self argument and will be handled completely by the compiler
                         // i.e.: `|x| x.is_something()`
                         ExprKind::MethodCall(_, self_expr, ..) if self_expr.hir_id == cmt.hir_id => {
-                            let _ = write!(self.suggestion_start, "{start_snip}{ident_str_with_proj}");
+                            let _: fmt::Result = write!(self.suggestion_start, "{start_snip}{ident_str_with_proj}");
                             self.next_pos = span.hi();
                             return;
                         },
@@ -1055,7 +1055,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
                     }
                 }
 
-                let _ = write!(self.suggestion_start, "{start_snip}{replacement_str}");
+                let _: fmt::Result = write!(self.suggestion_start, "{start_snip}{replacement_str}");
             }
             self.next_pos = span.hi();
         }
diff --git a/lintcheck/src/main.rs b/lintcheck/src/main.rs
index bd49f096072..23c85298027 100644
--- a/lintcheck/src/main.rs
+++ b/lintcheck/src/main.rs
@@ -17,9 +17,9 @@ use crate::recursive::LintcheckServer;
 use std::collections::{HashMap, HashSet};
 use std::env;
 use std::env::consts::EXE_SUFFIX;
-use std::fmt::Write as _;
+use std::fmt::{self, Write as _};
 use std::fs;
-use std::io::ErrorKind;
+use std::io::{self, ErrorKind};
 use std::path::{Path, PathBuf};
 use std::process::Command;
 use std::sync::atomic::{AtomicUsize, Ordering};
@@ -145,8 +145,8 @@ impl ClippyWarning {
             }
 
             let mut output = String::from("| ");
-            let _ = write!(output, "[`{file_with_pos}`]({file}#L{})", self.line);
-            let _ = write!(output, r#" | `{:<50}` | "{}" |"#, self.lint_type, self.message);
+            let _: fmt::Result = write!(output, "[`{file_with_pos}`]({file}#L{})", self.line);
+            let _: fmt::Result = write!(output, r#" | `{:<50}` | "{}" |"#, self.lint_type, self.message);
             output.push('\n');
             output
         } else {
@@ -632,7 +632,7 @@ fn main() {
         .unwrap();
 
     let server = config.recursive.then(|| {
-        let _ = fs::remove_dir_all("target/lintcheck/shared_target_dir/recursive");
+        let _: io::Result<()> = fs::remove_dir_all("target/lintcheck/shared_target_dir/recursive");
 
         LintcheckServer::spawn(recursive_options)
     });
@@ -689,7 +689,7 @@ fn main() {
     write!(text, "{}", all_msgs.join("")).unwrap();
     text.push_str("\n\n### ICEs:\n");
     for (cratename, msg) in &ices {
-        let _ = write!(text, "{cratename}: '{msg}'");
+        let _: fmt::Result = write!(text, "{cratename}: '{msg}'");
     }
 
     println!("Writing logs to {}", config.lintcheck_results_path.display());
diff --git a/tests/ui/let_underscore_untyped.rs b/tests/ui/let_underscore_untyped.rs
new file mode 100644
index 00000000000..bcb33c5c7e3
--- /dev/null
+++ b/tests/ui/let_underscore_untyped.rs
@@ -0,0 +1,54 @@
+#![allow(unused)]
+#![warn(clippy::let_underscore_untyped)]
+
+use std::future::Future;
+use std::{boxed::Box, fmt::Display};
+
+fn a() -> u32 {
+    1
+}
+
+fn b<T>(x: T) -> T {
+    x
+}
+
+fn c() -> impl Display {
+    1
+}
+
+fn d(x: &u32) -> &u32 {
+    x
+}
+
+fn e() -> Result<u32, ()> {
+    Ok(1)
+}
+
+fn f() -> Box<dyn Display> {
+    Box::new(1)
+}
+
+fn main() {
+    let _ = a();
+    let _ = b(1);
+    let _ = c();
+    let _ = d(&1);
+    let _ = e();
+    let _ = f();
+
+    _ = a();
+    _ = b(1);
+    _ = c();
+    _ = d(&1);
+    _ = e();
+    _ = f();
+
+    let _: u32 = a();
+    let _: u32 = b(1);
+    let _: &u32 = d(&1);
+    let _: Result<_, _> = e();
+    let _: Box<_> = f();
+
+    #[allow(clippy::let_underscore_untyped)]
+    let _ = a();
+}
diff --git a/tests/ui/let_underscore_untyped.stderr b/tests/ui/let_underscore_untyped.stderr
new file mode 100644
index 00000000000..36c3d1214d6
--- /dev/null
+++ b/tests/ui/let_underscore_untyped.stderr
@@ -0,0 +1,51 @@
+error: non-binding `let` without a type annotation
+  --> $DIR/let_underscore_untyped.rs:32:5
+   |
+LL |     let _ = a();
+   |     ^^^^^^^^^^^^
+   |
+   = help: consider adding a type annotation or removing the `let` keyword
+   = note: `-D clippy::let-underscore-untyped` implied by `-D warnings`
+
+error: non-binding `let` without a type annotation
+  --> $DIR/let_underscore_untyped.rs:33:5
+   |
+LL |     let _ = b(1);
+   |     ^^^^^^^^^^^^^
+   |
+   = help: consider adding a type annotation or removing the `let` keyword
+
+error: non-binding `let` without a type annotation
+  --> $DIR/let_underscore_untyped.rs:34:5
+   |
+LL |     let _ = c();
+   |     ^^^^^^^^^^^^
+   |
+   = help: consider adding a type annotation or removing the `let` keyword
+
+error: non-binding `let` without a type annotation
+  --> $DIR/let_underscore_untyped.rs:35:5
+   |
+LL |     let _ = d(&1);
+   |     ^^^^^^^^^^^^^^
+   |
+   = help: consider adding a type annotation or removing the `let` keyword
+
+error: non-binding `let` without a type annotation
+  --> $DIR/let_underscore_untyped.rs:36:5
+   |
+LL |     let _ = e();
+   |     ^^^^^^^^^^^^
+   |
+   = help: consider adding a type annotation or removing the `let` keyword
+
+error: non-binding `let` without a type annotation
+  --> $DIR/let_underscore_untyped.rs:37:5
+   |
+LL |     let _ = f();
+   |     ^^^^^^^^^^^^
+   |
+   = help: consider adding a type annotation or removing the `let` keyword
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/map_flatten_fixable.fixed b/tests/ui/map_flatten_fixable.fixed
index 53628ef6531..8e2f11389f8 100644
--- a/tests/ui/map_flatten_fixable.fixed
+++ b/tests/ui/map_flatten_fixable.fixed
@@ -1,6 +1,7 @@
 // run-rustfix
 
 #![warn(clippy::all, clippy::pedantic)]
+#![allow(clippy::let_underscore_untyped)]
 #![allow(clippy::missing_docs_in_private_items)]
 #![allow(clippy::map_identity)]
 #![allow(clippy::redundant_closure)]
diff --git a/tests/ui/map_flatten_fixable.rs b/tests/ui/map_flatten_fixable.rs
index 76016c8ed3c..a783a99c4ff 100644
--- a/tests/ui/map_flatten_fixable.rs
+++ b/tests/ui/map_flatten_fixable.rs
@@ -1,6 +1,7 @@
 // run-rustfix
 
 #![warn(clippy::all, clippy::pedantic)]
+#![allow(clippy::let_underscore_untyped)]
 #![allow(clippy::missing_docs_in_private_items)]
 #![allow(clippy::map_identity)]
 #![allow(clippy::redundant_closure)]
diff --git a/tests/ui/map_flatten_fixable.stderr b/tests/ui/map_flatten_fixable.stderr
index b6b0c4d09c3..c91f0b9ae94 100644
--- a/tests/ui/map_flatten_fixable.stderr
+++ b/tests/ui/map_flatten_fixable.stderr
@@ -1,5 +1,5 @@
 error: called `map(..).flatten()` on `Iterator`
-  --> $DIR/map_flatten_fixable.rs:17:47
+  --> $DIR/map_flatten_fixable.rs:18:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id)`
@@ -7,43 +7,43 @@ LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().coll
    = note: `-D clippy::map-flatten` implied by `-D warnings`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> $DIR/map_flatten_fixable.rs:18:47
+  --> $DIR/map_flatten_fixable.rs:19:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_ref).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id_ref)`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> $DIR/map_flatten_fixable.rs:19:47
+  --> $DIR/map_flatten_fixable.rs:20:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_closure).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id_closure)`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> $DIR/map_flatten_fixable.rs:20:47
+  --> $DIR/map_flatten_fixable.rs:21:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| x.checked_add(1)).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(|x| x.checked_add(1))`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> $DIR/map_flatten_fixable.rs:23:47
+  --> $DIR/map_flatten_fixable.rs:24:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `flat_map` and remove the `.flatten()`: `flat_map(|x| 0..x)`
 
 error: called `map(..).flatten()` on `Option`
-  --> $DIR/map_flatten_fixable.rs:26:40
+  --> $DIR/map_flatten_fixable.rs:27:40
    |
 LL |     let _: Option<_> = (Some(Some(1))).map(|x| x).flatten();
    |                                        ^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `and_then` and remove the `.flatten()`: `and_then(|x| x)`
 
 error: called `map(..).flatten()` on `Result`
-  --> $DIR/map_flatten_fixable.rs:29:42
+  --> $DIR/map_flatten_fixable.rs:30:42
    |
 LL |     let _: Result<_, &str> = (Ok(Ok(1))).map(|x| x).flatten();
    |                                          ^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `and_then` and remove the `.flatten()`: `and_then(|x| x)`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> $DIR/map_flatten_fixable.rs:38:10
+  --> $DIR/map_flatten_fixable.rs:39:10
    |
 LL |           .map(|n| match n {
    |  __________^
@@ -72,7 +72,7 @@ LL ~         });
    |
 
 error: called `map(..).flatten()` on `Option`
-  --> $DIR/map_flatten_fixable.rs:58:10
+  --> $DIR/map_flatten_fixable.rs:59:10
    |
 LL |           .map(|_| {
    |  __________^
diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs
index 6f22366eab2..1519e4da934 100644
--- a/tests/ui/methods.rs
+++ b/tests/ui/methods.rs
@@ -4,6 +4,7 @@
 #![allow(
     clippy::disallowed_names,
     clippy::default_trait_access,
+    clippy::let_underscore_untyped,
     clippy::missing_docs_in_private_items,
     clippy::missing_safety_doc,
     clippy::non_ascii_literal,
diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr
index b63672dd6fd..4643e09e270 100644
--- a/tests/ui/methods.stderr
+++ b/tests/ui/methods.stderr
@@ -1,5 +1,5 @@
 error: methods called `new` usually return `Self`
-  --> $DIR/methods.rs:104:5
+  --> $DIR/methods.rs:105:5
    |
 LL | /     fn new() -> i32 {
 LL | |         0
@@ -9,7 +9,7 @@ LL | |     }
    = note: `-D clippy::new-ret-no-self` implied by `-D warnings`
 
 error: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead
-  --> $DIR/methods.rs:125:13
+  --> $DIR/methods.rs:126:13
    |
 LL |       let _ = v.iter().filter(|&x| {
    |  _____________^