about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduardo Broto <ebroto@tutanota.com>2020-10-31 09:33:40 +0100
committerEduardo Broto <ebroto@tutanota.com>2020-10-31 09:33:40 +0100
commit9d73371663ec67558700b43a55d606caa71a7f71 (patch)
treebe08801aa67ac6c18a669003823d285e0933ad83
parent1c8c3d14ef6f9ab297103c526ba4b6023822aa87 (diff)
parent084b203988e04bcf89d3b2d6bbc77b65ecfab553 (diff)
downloadrust-9d73371663ec67558700b43a55d606caa71a7f71.tar.gz
rust-9d73371663ec67558700b43a55d606caa71a7f71.zip
Merge remote-tracking branch 'upstream/master' into rustup
-rw-r--r--.github/driver.sh6
-rw-r--r--CHANGELOG.md2
-rw-r--r--CONTRIBUTING.md7
-rw-r--r--clippy_dev/src/ra_setup.rs11
-rw-r--r--clippy_lints/src/arithmetic.rs25
-rw-r--r--clippy_lints/src/future_not_send.rs9
-rw-r--r--clippy_lints/src/items_after_statements.rs7
-rw-r--r--clippy_lints/src/len_zero.rs77
-rw-r--r--clippy_lints/src/lib.rs6
-rw-r--r--clippy_lints/src/methods/mod.rs147
-rw-r--r--clippy_lints/src/methods/option_map_unwrap_or.rs8
-rw-r--r--clippy_lints/src/misc.rs15
-rw-r--r--clippy_lints/src/types.rs44
-rw-r--r--src/lintlist/mod.rs14
-rw-r--r--tests/ui/auxiliary/macro_rules.rs14
-rw-r--r--tests/ui/borrow_box.rs16
-rw-r--r--tests/ui/borrow_box.stderr50
-rw-r--r--tests/ui/comparison_to_empty.fixed23
-rw-r--r--tests/ui/comparison_to_empty.rs23
-rw-r--r--tests/ui/comparison_to_empty.stderr28
-rw-r--r--tests/ui/crashes/ice-6250.rs16
-rw-r--r--tests/ui/crashes/ice-6250.stderr27
-rw-r--r--tests/ui/crashes/ice-6251.rs6
-rw-r--r--tests/ui/crashes/ice-6251.stderr43
-rw-r--r--tests/ui/crashes/ice-6252.rs15
-rw-r--r--tests/ui/crashes/ice-6252.stderr46
-rw-r--r--tests/ui/crashes/ice-6254.rs15
-rw-r--r--tests/ui/crashes/ice-6254.stderr12
-rw-r--r--tests/ui/crashes/ice-6255.rs15
-rw-r--r--tests/ui/crashes/ice-6255.stderr13
-rw-r--r--tests/ui/crashes/ice-6256.rs13
-rw-r--r--tests/ui/crashes/ice-6256.stderr18
-rw-r--r--tests/ui/filter_map_next.rs3
-rw-r--r--tests/ui/filter_map_next.stderr17
-rw-r--r--tests/ui/filter_map_next_fixable.fixed10
-rw-r--r--tests/ui/filter_map_next_fixable.rs10
-rw-r--r--tests/ui/filter_map_next_fixable.stderr10
-rw-r--r--tests/ui/filter_methods.stderr8
-rw-r--r--tests/ui/find_map.stderr4
-rw-r--r--tests/ui/integer_arithmetic.rs10
-rw-r--r--tests/ui/integer_arithmetic.stderr92
-rw-r--r--tests/ui/item_after_statement.rs5
-rw-r--r--tests/ui/item_after_statement.stderr15
-rw-r--r--tests/ui/iter_skip_next.stderr8
-rw-r--r--tests/ui/map_collect_result_unit.fixed16
-rw-r--r--tests/ui/map_collect_result_unit.rs16
-rw-r--r--tests/ui/map_collect_result_unit.stderr16
-rw-r--r--tests/ui/map_unwrap_or.rs40
-rw-r--r--tests/ui/map_unwrap_or.stderr99
-rw-r--r--tests/ui/map_unwrap_or_fixable.fixed54
-rw-r--r--tests/ui/map_unwrap_or_fixable.rs58
-rw-r--r--tests/ui/map_unwrap_or_fixable.stderr22
-rw-r--r--tests/ui/methods.rs5
-rw-r--r--tests/ui/methods.stderr33
-rw-r--r--tests/ui/methods_fixable.fixed11
-rw-r--r--tests/ui/methods_fixable.rs11
-rw-r--r--tests/ui/methods_fixable.stderr10
-rw-r--r--tests/ui/option_map_or_none.stderr4
-rw-r--r--tests/ui/skip_while_next.stderr8
-rw-r--r--tests/ui/temporary_assignment.rs1
-rw-r--r--tests/ui/temporary_assignment.stderr8
-rw-r--r--tests/ui/toplevel_ref_arg.fixed21
-rw-r--r--tests/ui/toplevel_ref_arg.rs21
-rw-r--r--tests/ui/toplevel_ref_arg.stderr23
-rw-r--r--tests/ui/toplevel_ref_arg_non_rustfix.rs22
-rw-r--r--tests/ui/toplevel_ref_arg_non_rustfix.stderr15
-rwxr-xr-xutil/dev7
67 files changed, 1210 insertions, 274 deletions
diff --git a/.github/driver.sh b/.github/driver.sh
index 321e00df153..6ff189fc859 100644
--- a/.github/driver.sh
+++ b/.github/driver.sh
@@ -24,16 +24,16 @@ unset CARGO_MANIFEST_DIR
 # FIXME: How to match the clippy invocation in compile-test.rs?
 ./target/debug/clippy-driver -Dwarnings -Aunused -Zui-testing --emit metadata --crate-type bin tests/ui/double_neg.rs 2>double_neg.stderr && exit 1
 sed -e "s,tests/ui,\$DIR," -e "/= help/d" double_neg.stderr >normalized.stderr
-diff normalized.stderr tests/ui/double_neg.stderr
+diff -u normalized.stderr tests/ui/double_neg.stderr
 
 # make sure "clippy-driver --rustc --arg" and "rustc --arg" behave the same
 SYSROOT=$(rustc --print sysroot)
-diff <(LD_LIBRARY_PATH=${SYSROOT}/lib ./target/debug/clippy-driver --rustc --version --verbose) <(rustc --version --verbose)
+diff -u <(LD_LIBRARY_PATH=${SYSROOT}/lib ./target/debug/clippy-driver --rustc --version --verbose) <(rustc --version --verbose)
 
 echo "fn main() {}" >target/driver_test.rs
 # we can't run 2 rustcs on the same file at the same time
 CLIPPY=$(LD_LIBRARY_PATH=${SYSROOT}/lib ./target/debug/clippy-driver ./target/driver_test.rs --rustc)
 RUSTC=$(rustc ./target/driver_test.rs)
-diff <($CLIPPY) <($RUSTC)
+diff -u <($CLIPPY) <($RUSTC)
 
 # TODO: CLIPPY_CONF_DIR / CARGO_MANIFEST_DIR
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 25f3b5da198..6b63dbb7eff 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1665,6 +1665,7 @@ Released 2018-09-13
 [`cognitive_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#cognitive_complexity
 [`collapsible_if`]: https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if
 [`comparison_chain`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_chain
+[`comparison_to_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_to_empty
 [`copy_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#copy_iterator
 [`create_dir`]: https://rust-lang.github.io/rust-clippy/master/index.html#create_dir
 [`crosspointer_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#crosspointer_transmute
@@ -1802,6 +1803,7 @@ Released 2018-09-13
 [`manual_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_unwrap_or
 [`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names
 [`map_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_clone
+[`map_collect_result_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_collect_result_unit
 [`map_entry`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_entry
 [`map_err_ignore`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_err_ignore
 [`map_flatten`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 6494695606c..a8e2123656e 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -63,9 +63,10 @@ To figure out how this syntax structure is encoded in the AST, it is recommended
 Usually the lint will end up to be a nested series of matches and ifs, [like so][deep-nesting].
 But we can make it nest-less by using [if_chain] macro, [like this][nest-less].
 
-[`E-medium`] issues are generally pretty easy too, though it's recommended you work on an E-easy issue first.
-They are mostly classified as [`E-medium`], since they might be somewhat involved code wise,
-but not difficult per-se.
+[`E-medium`] issues are generally pretty easy too, though it's recommended you work on an [`good first issue`]
+first. Sometimes they are only somewhat involved code wise, but not difficult per-se.
+Note that [`E-medium`] issues may require some knowledge of Clippy internals or some 
+debugging to find the actual problem behind the issue. 
 
 [`T-middle`] issues can be more involved and require verifying types. The [`ty`] module contains a
 lot of methods that are useful, though one of the most useful would be `expr_ty` (gives the type of
diff --git a/clippy_dev/src/ra_setup.rs b/clippy_dev/src/ra_setup.rs
index c67efc10f15..9d9e836cc08 100644
--- a/clippy_dev/src/ra_setup.rs
+++ b/clippy_dev/src/ra_setup.rs
@@ -11,7 +11,7 @@ use std::path::PathBuf;
 // code. See https://github.com/rust-analyzer/rust-analyzer/issues/3517 and https://github.com/rust-lang/rust-clippy/issues/5514 for details
 
 pub fn run(rustc_path: Option<&str>) {
-    // we can unwrap here because the arg is required here
+    // we can unwrap here because the arg is required by clap
     let rustc_path = PathBuf::from(rustc_path.unwrap());
     assert!(rustc_path.is_dir(), "path is not a directory");
     let rustc_source_basedir = rustc_path.join("compiler");
@@ -49,6 +49,15 @@ fn inject_deps_into_manifest(
     cargo_toml: &str,
     lib_rs: &str,
 ) -> std::io::Result<()> {
+    // do not inject deps if we have aleady done so
+    if cargo_toml.contains("[target.'cfg(NOT_A_PLATFORM)'.dependencies]") {
+        eprintln!(
+            "cargo dev ra-setup: warning: deps already found inside {}, doing nothing.",
+            manifest_path
+        );
+        return Ok(());
+    }
+
     let extern_crates = lib_rs
         .lines()
         // get the deps
diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs
index e84481f9b53..9861d8cfc4e 100644
--- a/clippy_lints/src/arithmetic.rs
+++ b/clippy_lints/src/arithmetic.rs
@@ -88,9 +88,28 @@ impl<'tcx> LateLintPass<'tcx> for Arithmetic {
 
                 let (l_ty, r_ty) = (cx.typeck_results().expr_ty(l), cx.typeck_results().expr_ty(r));
                 if l_ty.peel_refs().is_integral() && r_ty.peel_refs().is_integral() {
-                    span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
-                    self.expr_span = Some(expr.span);
-                } else if l_ty.peel_refs().is_floating_point() && r_ty.peel_refs().is_floating_point() {
+                    match op.node {
+                        hir::BinOpKind::Div | hir::BinOpKind::Rem => match &r.kind {
+                            hir::ExprKind::Lit(_lit) => (),
+                            hir::ExprKind::Unary(hir::UnOp::UnNeg, expr) => {
+                                if let hir::ExprKind::Lit(lit) = &expr.kind {
+                                    if let rustc_ast::ast::LitKind::Int(1, _) = lit.node {
+                                        span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
+                                        self.expr_span = Some(expr.span);
+                                    }
+                                }
+                            },
+                            _ => {
+                                span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
+                                self.expr_span = Some(expr.span);
+                            },
+                        },
+                        _ => {
+                            span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
+                            self.expr_span = Some(expr.span);
+                        },
+                    }
+                } else if r_ty.peel_refs().is_floating_point() && r_ty.peel_refs().is_floating_point() {
                     span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected");
                     self.expr_span = Some(expr.span);
                 }
diff --git a/clippy_lints/src/future_not_send.rs b/clippy_lints/src/future_not_send.rs
index d2a322e1223..71a30d1c33d 100644
--- a/clippy_lints/src/future_not_send.rs
+++ b/clippy_lints/src/future_not_send.rs
@@ -92,13 +92,8 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
                         |db| {
                             cx.tcx.infer_ctxt().enter(|infcx| {
                                 for FulfillmentError { obligation, .. } in send_errors {
-                                    infcx.maybe_note_obligation_cause_for_async_await(
-                                        db,
-                                        &obligation,
-                                    );
-                                    if let Trait(trait_pred, _) =
-                                        obligation.predicate.skip_binders()
-                                    {
+                                    infcx.maybe_note_obligation_cause_for_async_await(db, &obligation);
+                                    if let Trait(trait_pred, _) = obligation.predicate.skip_binders() {
                                         db.note(&format!(
                                             "`{}` doesn't implement `{}`",
                                             trait_pred.self_ty(),
diff --git a/clippy_lints/src/items_after_statements.rs b/clippy_lints/src/items_after_statements.rs
index c8576bcfcb4..8998fae09de 100644
--- a/clippy_lints/src/items_after_statements.rs
+++ b/clippy_lints/src/items_after_statements.rs
@@ -2,7 +2,8 @@
 
 use crate::utils::span_lint;
 use rustc_ast::ast::{Block, ItemKind, StmtKind};
-use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
 declare_clippy_lint! {
@@ -53,7 +54,7 @@ declare_lint_pass!(ItemsAfterStatements => [ITEMS_AFTER_STATEMENTS]);
 
 impl EarlyLintPass for ItemsAfterStatements {
     fn check_block(&mut self, cx: &EarlyContext<'_>, item: &Block) {
-        if item.span.from_expansion() {
+        if in_external_macro(cx.sess(), item.span) {
             return;
         }
 
@@ -67,7 +68,7 @@ impl EarlyLintPass for ItemsAfterStatements {
         // lint on all further items
         for stmt in stmts {
             if let StmtKind::Item(ref it) = *stmt {
-                if it.span.from_expansion() {
+                if in_external_macro(cx.sess(), it.span) {
                     return;
                 }
                 if let ItemKind::MacroDef(..) = it.kind {
diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs
index c9c4891bb08..8e2f03d6e4e 100644
--- a/clippy_lints/src/len_zero.rs
+++ b/clippy_lints/src/len_zero.rs
@@ -68,7 +68,44 @@ declare_clippy_lint! {
     "traits or impls with a public `len` method but no corresponding `is_empty` method"
 }
 
-declare_lint_pass!(LenZero => [LEN_ZERO, LEN_WITHOUT_IS_EMPTY]);
+declare_clippy_lint! {
+    /// **What it does:** Checks for comparing to an empty slice such as "" or [],`
+    /// and suggests using `.is_empty()` where applicable.
+    ///
+    /// **Why is this bad?** Some structures can answer `.is_empty()` much faster
+    /// than checking for equality. So it is good to get into the habit of using
+    /// `.is_empty()`, and having it is cheap.
+    /// Besides, it makes the intent clearer than a manual comparison in some contexts.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    ///
+    /// ```ignore
+    /// if s == "" {
+    ///     ..
+    /// }
+    ///
+    /// if arr == [] {
+    ///     ..
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```ignore
+    /// if s.is_empty() {
+    ///     ..
+    /// }
+    ///
+    /// if arr.is_empty() {
+    ///     ..
+    /// }
+    /// ```
+    pub COMPARISON_TO_EMPTY,
+    style,
+    "checking `x == \"\"` or `x == []` (or similar) when `.is_empty()` could be used instead"
+}
+
+declare_lint_pass!(LenZero => [LEN_ZERO, LEN_WITHOUT_IS_EMPTY, COMPARISON_TO_EMPTY]);
 
 impl<'tcx> LateLintPass<'tcx> for LenZero {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
@@ -221,6 +258,8 @@ fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>
         }
 
         check_len(cx, span, method_path.ident.name, args, &lit.node, op, compare_to)
+    } else {
+        check_empty_expr(cx, span, method, lit, op)
     }
 }
 
@@ -258,6 +297,42 @@ fn check_len(
     }
 }
 
+fn check_empty_expr(cx: &LateContext<'_>, span: Span, lit1: &Expr<'_>, lit2: &Expr<'_>, op: &str) {
+    if (is_empty_array(lit2) || is_empty_string(lit2)) && has_is_empty(cx, lit1) {
+        let mut applicability = Applicability::MachineApplicable;
+        span_lint_and_sugg(
+            cx,
+            COMPARISON_TO_EMPTY,
+            span,
+            "comparison to empty slice",
+            &format!("using `{}is_empty` is clearer and more explicit", op),
+            format!(
+                "{}{}.is_empty()",
+                op,
+                snippet_with_applicability(cx, lit1.span, "_", &mut applicability)
+            ),
+            applicability,
+        );
+    }
+}
+
+fn is_empty_string(expr: &Expr<'_>) -> bool {
+    if let ExprKind::Lit(ref lit) = expr.kind {
+        if let LitKind::Str(lit, _) = lit.node {
+            let lit = lit.as_str();
+            return lit == "";
+        }
+    }
+    false
+}
+
+fn is_empty_array(expr: &Expr<'_>) -> bool {
+    if let ExprKind::Array(ref arr) = expr.kind {
+        return arr.is_empty();
+    }
+    false
+}
+
 /// Checks if this type has an `is_empty` method.
 fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     /// Gets an `AssocItem` and return true if it matches `is_empty(self)`.
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index e97fa543a09..5c3af014ee1 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -615,6 +615,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         &large_const_arrays::LARGE_CONST_ARRAYS,
         &large_enum_variant::LARGE_ENUM_VARIANT,
         &large_stack_arrays::LARGE_STACK_ARRAYS,
+        &len_zero::COMPARISON_TO_EMPTY,
         &len_zero::LEN_WITHOUT_IS_EMPTY,
         &len_zero::LEN_ZERO,
         &let_if_seq::USELESS_LET_IF_SEQ,
@@ -702,6 +703,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         &methods::ITER_NTH_ZERO,
         &methods::ITER_SKIP_NEXT,
         &methods::MANUAL_SATURATING_ARITHMETIC,
+        &methods::MAP_COLLECT_RESULT_UNIT,
         &methods::MAP_FLATTEN,
         &methods::MAP_UNWRAP_OR,
         &methods::NEW_RET_NO_SELF,
@@ -1366,6 +1368,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&int_plus_one::INT_PLUS_ONE),
         LintId::of(&large_const_arrays::LARGE_CONST_ARRAYS),
         LintId::of(&large_enum_variant::LARGE_ENUM_VARIANT),
+        LintId::of(&len_zero::COMPARISON_TO_EMPTY),
         LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY),
         LintId::of(&len_zero::LEN_ZERO),
         LintId::of(&let_underscore::LET_UNDERSCORE_LOCK),
@@ -1427,6 +1430,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&methods::ITER_NTH_ZERO),
         LintId::of(&methods::ITER_SKIP_NEXT),
         LintId::of(&methods::MANUAL_SATURATING_ARITHMETIC),
+        LintId::of(&methods::MAP_COLLECT_RESULT_UNIT),
         LintId::of(&methods::NEW_RET_NO_SELF),
         LintId::of(&methods::OK_EXPECT),
         LintId::of(&methods::OPTION_AS_REF_DEREF),
@@ -1592,6 +1596,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&functions::RESULT_UNIT_ERR),
         LintId::of(&if_let_some_result::IF_LET_SOME_RESULT),
         LintId::of(&inherent_to_string::INHERENT_TO_STRING),
+        LintId::of(&len_zero::COMPARISON_TO_EMPTY),
         LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY),
         LintId::of(&len_zero::LEN_ZERO),
         LintId::of(&literal_representation::INCONSISTENT_DIGIT_GROUPING),
@@ -1621,6 +1626,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&methods::ITER_NTH_ZERO),
         LintId::of(&methods::ITER_SKIP_NEXT),
         LintId::of(&methods::MANUAL_SATURATING_ARITHMETIC),
+        LintId::of(&methods::MAP_COLLECT_RESULT_UNIT),
         LintId::of(&methods::NEW_RET_NO_SELF),
         LintId::of(&methods::OK_EXPECT),
         LintId::of(&methods::OPTION_MAP_OR_NONE),
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index d250bfd71e9..3c3093e869c 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -32,8 +32,7 @@ use crate::utils::{
     is_copy, is_expn_of, is_type_diagnostic_item, iter_input_pats, last_path_segment, match_def_path, match_qpath,
     match_trait_method, match_type, match_var, method_calls, method_chain_args, paths, remove_blocks, return_ty,
     single_segment_path, snippet, snippet_with_applicability, snippet_with_macro_callsite, span_lint,
-    span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then, sugg, walk_ptrs_ty_depth,
-    SpanlessEq,
+    span_lint_and_help, span_lint_and_sugg, span_lint_and_then, sugg, walk_ptrs_ty_depth, SpanlessEq,
 };
 
 declare_clippy_lint! {
@@ -1349,6 +1348,27 @@ declare_clippy_lint! {
     "using unnecessary lazy evaluation, which can be replaced with simpler eager evaluation"
 }
 
+declare_clippy_lint! {
+    /// **What it does:** Checks for usage of `_.map(_).collect::<Result<(),_>()`.
+    ///
+    /// **Why is this bad?** Using `try_for_each` instead is more readable and idiomatic.
+    ///
+    /// **Known problems:** None
+    ///
+    /// **Example:**
+    ///
+    /// ```rust
+    /// (0..3).map(|t| Err(t)).collect::<Result<(), _>>();
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// (0..3).try_for_each(|t| Err(t));
+    /// ```
+    pub MAP_COLLECT_RESULT_UNIT,
+    style,
+    "using `.map(_).collect::<Result<(),_>()`, which can be replaced with `try_for_each`"
+}
+
 declare_lint_pass!(Methods => [
     UNWRAP_USED,
     EXPECT_USED,
@@ -1398,6 +1418,7 @@ declare_lint_pass!(Methods => [
     FILETYPE_IS_FILE,
     OPTION_AS_REF_DEREF,
     UNNECESSARY_LAZY_EVALUATIONS,
+    MAP_COLLECT_RESULT_UNIT,
 ]);
 
 impl<'tcx> LateLintPass<'tcx> for Methods {
@@ -1479,6 +1500,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
             ["unwrap_or_else", ..] => unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], "unwrap_or"),
             ["get_or_insert_with", ..] => unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], "get_or_insert"),
             ["ok_or_else", ..] => unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], "ok_or"),
+            ["collect", "map"] => lint_map_collect(cx, expr, arg_lists[1], arg_lists[0]),
             _ => {},
         }
 
@@ -1712,7 +1734,7 @@ fn lint_or_fun_call<'tcx>(
                     "try this",
                     format!(
                         "{}.unwrap_or_default()",
-                        snippet_with_applicability(cx, self_expr.span, "_", &mut applicability)
+                        snippet_with_applicability(cx, self_expr.span, "..", &mut applicability)
                     ),
                     applicability,
                 );
@@ -2119,7 +2141,7 @@ fn lint_clone_on_ref_ptr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::
             return;
         };
 
-        let snippet = snippet_with_macro_callsite(cx, arg.span, "_");
+        let snippet = snippet_with_macro_callsite(cx, arg.span, "..");
 
         span_lint_and_sugg(
             cx,
@@ -2155,9 +2177,9 @@ fn lint_string_extend(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::E
             "try this",
             format!(
                 "{}.push_str({}{})",
-                snippet_with_applicability(cx, args[0].span, "_", &mut applicability),
+                snippet_with_applicability(cx, args[0].span, "..", &mut applicability),
                 ref_str,
-                snippet_with_applicability(cx, target.span, "_", &mut applicability)
+                snippet_with_applicability(cx, target.span, "..", &mut applicability)
             ),
             applicability,
         );
@@ -2404,7 +2426,7 @@ fn lint_get_unwrap<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, get_args:
     let mut applicability = Applicability::MachineApplicable;
     let expr_ty = cx.typeck_results().expr_ty(&get_args[0]);
     let get_args_str = if get_args.len() > 1 {
-        snippet_with_applicability(cx, get_args[1].span, "_", &mut applicability)
+        snippet_with_applicability(cx, get_args[1].span, "..", &mut applicability)
     } else {
         return; // not linting on a .get().unwrap() chain or variant
     };
@@ -2464,7 +2486,7 @@ fn lint_get_unwrap<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, get_args:
         format!(
             "{}{}[{}]",
             borrow_str,
-            snippet_with_applicability(cx, get_args[0].span, "_", &mut applicability),
+            snippet_with_applicability(cx, get_args[0].span, "..", &mut applicability),
             get_args_str
         ),
         applicability,
@@ -2480,7 +2502,7 @@ fn lint_iter_skip_next(cx: &LateContext<'_>, expr: &hir::Expr<'_>, skip_args: &[
                 cx,
                 ITER_SKIP_NEXT,
                 expr.span.trim_start(caller.span).unwrap(),
-                "called `skip(x).next()` on an iterator",
+                "called `skip(..).next()` on an iterator",
                 "use `nth` instead",
                 hint,
                 Applicability::MachineApplicable,
@@ -2683,11 +2705,11 @@ fn lint_map_unwrap_or_else<'tcx>(
 
         // lint message
         let msg = if is_option {
-            "called `map(f).unwrap_or_else(g)` on an `Option` value. This can be done more directly by calling \
-            `map_or_else(g, f)` instead"
+            "called `map(<f>).unwrap_or_else(<g>)` on an `Option` value. This can be done more directly by calling \
+            `map_or_else(<g>, <f>)` instead"
         } else {
-            "called `map(f).unwrap_or_else(g)` on a `Result` value. This can be done more directly by calling \
-            `.map_or_else(g, f)` instead"
+            "called `map(<f>).unwrap_or_else(<g>)` on a `Result` value. This can be done more directly by calling \
+            `.map_or_else(<g>, <f>)` instead"
         };
         // get snippets for args to map() and unwrap_or_else()
         let map_snippet = snippet(cx, map_args[1].span, "..");
@@ -2697,16 +2719,15 @@ fn lint_map_unwrap_or_else<'tcx>(
         let multiline = map_snippet.lines().count() > 1 || unwrap_snippet.lines().count() > 1;
         let same_span = map_args[1].span.ctxt() == unwrap_args[1].span.ctxt();
         if same_span && !multiline {
-            span_lint_and_note(
+            let var_snippet = snippet(cx, map_args[0].span, "..");
+            span_lint_and_sugg(
                 cx,
                 MAP_UNWRAP_OR,
                 expr.span,
                 msg,
-                None,
-                &format!(
-                    "replace `map({0}).unwrap_or_else({1})` with `map_or_else({1}, {0})`",
-                    map_snippet, unwrap_snippet,
-                ),
+                "try this",
+                format!("{}.map_or_else({}, {})", var_snippet, unwrap_snippet, map_snippet),
+                Applicability::MachineApplicable,
             );
             return true;
         } else if same_span && multiline {
@@ -2753,8 +2774,8 @@ fn lint_map_or_none<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map
         if is_option {
             let self_snippet = snippet(cx, map_or_args[0].span, "..");
             let func_snippet = snippet(cx, map_or_args[2].span, "..");
-            let msg = "called `map_or(None, f)` on an `Option` value. This can be done more directly by calling \
-                       `and_then(f)` instead";
+            let msg = "called `map_or(None, ..)` on an `Option` value. This can be done more directly by calling \
+                       `and_then(..)` instead";
             (
                 OPTION_MAP_OR_NONE,
                 msg,
@@ -2792,18 +2813,20 @@ fn lint_map_or_none<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map
 fn lint_filter_next<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, filter_args: &'tcx [hir::Expr<'_>]) {
     // lint if caller of `.filter().next()` is an Iterator
     if match_trait_method(cx, expr, &paths::ITERATOR) {
-        let msg = "called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling \
-                   `.find(p)` instead.";
+        let msg = "called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling \
+                   `.find(..)` instead.";
         let filter_snippet = snippet(cx, filter_args[1].span, "..");
         if filter_snippet.lines().count() <= 1 {
+            let iter_snippet = snippet(cx, filter_args[0].span, "..");
             // add note if not multi-line
-            span_lint_and_note(
+            span_lint_and_sugg(
                 cx,
                 FILTER_NEXT,
                 expr.span,
                 msg,
-                None,
-                &format!("replace `filter({0}).next()` with `find({0})`", filter_snippet),
+                "try this",
+                format!("{}.find({})", iter_snippet, filter_snippet),
+                Applicability::MachineApplicable,
             );
         } else {
             span_lint(cx, FILTER_NEXT, expr.span, msg);
@@ -2823,9 +2846,9 @@ fn lint_skip_while_next<'tcx>(
             cx,
             SKIP_WHILE_NEXT,
             expr.span,
-            "called `skip_while(p).next()` on an `Iterator`",
+            "called `skip_while(<p>).next()` on an `Iterator`",
             None,
-            "this is more succinctly expressed by calling `.find(!p)` instead",
+            "this is more succinctly expressed by calling `.find(!<p>)` instead",
         );
     }
 }
@@ -2839,7 +2862,7 @@ fn lint_filter_map<'tcx>(
 ) {
     // lint if caller of `.filter().map()` is an Iterator
     if match_trait_method(cx, expr, &paths::ITERATOR) {
-        let msg = "called `filter(p).map(q)` on an `Iterator`";
+        let msg = "called `filter(..).map(..)` on an `Iterator`";
         let hint = "this is more succinctly expressed by calling `.filter_map(..)` instead";
         span_lint_and_help(cx, FILTER_MAP, expr.span, msg, None, hint);
     }
@@ -2848,17 +2871,19 @@ fn lint_filter_map<'tcx>(
 /// lint use of `filter_map().next()` for `Iterators`
 fn lint_filter_map_next<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, filter_args: &'tcx [hir::Expr<'_>]) {
     if match_trait_method(cx, expr, &paths::ITERATOR) {
-        let msg = "called `filter_map(p).next()` on an `Iterator`. This is more succinctly expressed by calling \
-                   `.find_map(p)` instead.";
+        let msg = "called `filter_map(..).next()` on an `Iterator`. This is more succinctly expressed by calling \
+                   `.find_map(..)` instead.";
         let filter_snippet = snippet(cx, filter_args[1].span, "..");
         if filter_snippet.lines().count() <= 1 {
-            span_lint_and_note(
+            let iter_snippet = snippet(cx, filter_args[0].span, "..");
+            span_lint_and_sugg(
                 cx,
                 FILTER_MAP_NEXT,
                 expr.span,
                 msg,
-                None,
-                &format!("replace `filter_map({0}).next()` with `find_map({0})`", filter_snippet),
+                "try this",
+                format!("{}.find_map({})", iter_snippet, filter_snippet),
+                Applicability::MachineApplicable,
             );
         } else {
             span_lint(cx, FILTER_MAP_NEXT, expr.span, msg);
@@ -2875,7 +2900,7 @@ fn lint_find_map<'tcx>(
 ) {
     // lint if caller of `.filter().map()` is an Iterator
     if match_trait_method(cx, &map_args[0], &paths::ITERATOR) {
-        let msg = "called `find(p).map(q)` on an `Iterator`";
+        let msg = "called `find(..).map(..)` on an `Iterator`";
         let hint = "this is more succinctly expressed by calling `.find_map(..)` instead";
         span_lint_and_help(cx, FIND_MAP, expr.span, msg, None, hint);
     }
@@ -2890,7 +2915,7 @@ fn lint_filter_map_map<'tcx>(
 ) {
     // lint if caller of `.filter().map()` is an Iterator
     if match_trait_method(cx, expr, &paths::ITERATOR) {
-        let msg = "called `filter_map(p).map(q)` on an `Iterator`";
+        let msg = "called `filter_map(..).map(..)` on an `Iterator`";
         let hint = "this is more succinctly expressed by only calling `.filter_map(..)` instead";
         span_lint_and_help(cx, FILTER_MAP, expr.span, msg, None, hint);
     }
@@ -2905,7 +2930,7 @@ fn lint_filter_flat_map<'tcx>(
 ) {
     // lint if caller of `.filter().flat_map()` is an Iterator
     if match_trait_method(cx, expr, &paths::ITERATOR) {
-        let msg = "called `filter(p).flat_map(q)` on an `Iterator`";
+        let msg = "called `filter(..).flat_map(..)` on an `Iterator`";
         let hint = "this is more succinctly expressed by calling `.flat_map(..)` \
                     and filtering by returning `iter::empty()`";
         span_lint_and_help(cx, FILTER_MAP, expr.span, msg, None, hint);
@@ -2921,7 +2946,7 @@ fn lint_filter_map_flat_map<'tcx>(
 ) {
     // lint if caller of `.filter_map().flat_map()` is an Iterator
     if match_trait_method(cx, expr, &paths::ITERATOR) {
-        let msg = "called `filter_map(p).flat_map(q)` on an `Iterator`";
+        let msg = "called `filter_map(..).flat_map(..)` on an `Iterator`";
         let hint = "this is more succinctly expressed by calling `.flat_map(..)` \
                     and filtering by returning `iter::empty()`";
         span_lint_and_help(cx, FILTER_MAP, expr.span, msg, None, hint);
@@ -3092,9 +3117,9 @@ fn lint_chars_cmp(
                 "like this",
                 format!("{}{}.{}({})",
                         if info.eq { "" } else { "!" },
-                        snippet_with_applicability(cx, args[0][0].span, "_", &mut applicability),
+                        snippet_with_applicability(cx, args[0][0].span, "..", &mut applicability),
                         suggest,
-                        snippet_with_applicability(cx, arg_char[0].span, "_", &mut applicability)),
+                        snippet_with_applicability(cx, arg_char[0].span, "..", &mut applicability)),
                 applicability,
             );
 
@@ -3141,7 +3166,7 @@ fn lint_chars_cmp_with_unwrap<'tcx>(
                 "like this",
                 format!("{}{}.{}('{}')",
                         if info.eq { "" } else { "!" },
-                        snippet_with_applicability(cx, args[0][0].span, "_", &mut applicability),
+                        snippet_with_applicability(cx, args[0][0].span, "..", &mut applicability),
                         suggest,
                         c),
                 applicability,
@@ -3216,7 +3241,7 @@ fn lint_single_char_pattern(cx: &LateContext<'_>, _expr: &hir::Expr<'_>, arg: &h
 fn lint_single_char_push_string(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
     let mut applicability = Applicability::MachineApplicable;
     if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[1], &mut applicability) {
-        let base_string_snippet = snippet_with_applicability(cx, args[0].span, "_", &mut applicability);
+        let base_string_snippet = snippet_with_applicability(cx, args[0].span, "..", &mut applicability);
         let sugg = format!("{}.push({})", base_string_snippet, extension_string);
         span_lint_and_sugg(
             cx,
@@ -3259,7 +3284,7 @@ fn lint_asref(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str, as_re
                 expr.span,
                 &format!("this call to `{}` does nothing", call_name),
                 "try this",
-                snippet_with_applicability(cx, recvr.span, "_", &mut applicability).to_string(),
+                snippet_with_applicability(cx, recvr.span, "..", &mut applicability).to_string(),
                 applicability,
             );
         }
@@ -3445,6 +3470,42 @@ fn lint_option_as_ref_deref<'tcx>(
     }
 }
 
+fn lint_map_collect(
+    cx: &LateContext<'_>,
+    expr: &hir::Expr<'_>,
+    map_args: &[hir::Expr<'_>],
+    collect_args: &[hir::Expr<'_>],
+) {
+    if_chain! {
+        // called on Iterator
+        if let [map_expr] = collect_args;
+        if match_trait_method(cx, map_expr, &paths::ITERATOR);
+        // return of collect `Result<(),_>`
+        let collect_ret_ty = cx.typeck_results().expr_ty(expr);
+        if is_type_diagnostic_item(cx, collect_ret_ty, sym!(result_type));
+        if let ty::Adt(_, substs) = collect_ret_ty.kind();
+        if let Some(result_t) = substs.types().next();
+        if result_t.is_unit();
+        // get parts for snippet
+        if let [iter, map_fn] = map_args;
+        then {
+            span_lint_and_sugg(
+                cx,
+                MAP_COLLECT_RESULT_UNIT,
+                expr.span,
+                "`.map().collect()` can be replaced with `.try_for_each()`",
+                "try this",
+                format!(
+                    "{}.try_for_each({})",
+                    snippet(cx, iter.span, ".."),
+                    snippet(cx, map_fn.span, "..")
+                ),
+                Applicability::MachineApplicable,
+            );
+        }
+    }
+}
+
 /// Given a `Result<T, E>` type, return its error type (`E`).
 fn get_error_type<'a>(cx: &LateContext<'_>, ty: Ty<'a>) -> Option<Ty<'a>> {
     match ty.kind() {
diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs
index 95fa28e1c0f..d30b85d6a78 100644
--- a/clippy_lints/src/methods/option_map_unwrap_or.rs
+++ b/clippy_lints/src/methods/option_map_unwrap_or.rs
@@ -53,15 +53,15 @@ pub(super) fn lint<'tcx>(
         // lint message
         // comparing the snippet from source to raw text ("None") below is safe
         // because we already have checked the type.
-        let arg = if unwrap_snippet == "None" { "None" } else { "a" };
+        let arg = if unwrap_snippet == "None" { "None" } else { "<a>" };
         let unwrap_snippet_none = unwrap_snippet == "None";
         let suggest = if unwrap_snippet_none {
-            "and_then(f)"
+            "and_then(<f>)"
         } else {
-            "map_or(a, f)"
+            "map_or(<a>, <f>)"
         };
         let msg = &format!(
-            "called `map(f).unwrap_or({})` on an `Option` value. \
+            "called `map(<f>).unwrap_or({})` on an `Option` value. \
             This can be done more directly by calling `{}` instead",
             arg, suggest
         );
diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs
index 909e79f661a..308e92057b7 100644
--- a/clippy_lints/src/misc.rs
+++ b/clippy_lints/src/misc.rs
@@ -7,6 +7,7 @@ use rustc_hir::{
     StmtKind, TyKind, UnOp,
 };
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, Ty};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::hygiene::DesugaringKind;
@@ -271,13 +272,16 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
         k: FnKind<'tcx>,
         decl: &'tcx FnDecl<'_>,
         body: &'tcx Body<'_>,
-        _: Span,
+        span: Span,
         _: HirId,
     ) {
         if let FnKind::Closure(_) = k {
             // Does not apply to closures
             return;
         }
+        if in_external_macro(cx.tcx.sess, span) {
+            return;
+        }
         for arg in iter_input_pats(decl, body) {
             if let PatKind::Binding(BindingAnnotation::Ref | BindingAnnotation::RefMut, ..) = arg.pat.kind {
                 span_lint(
@@ -293,13 +297,16 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
 
     fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
         if_chain! {
+            if !in_external_macro(cx.tcx.sess, stmt.span);
             if let StmtKind::Local(ref local) = stmt.kind;
             if let PatKind::Binding(an, .., name, None) = local.pat.kind;
             if let Some(ref init) = local.init;
             if !higher::is_from_for_desugar(local);
             then {
                 if an == BindingAnnotation::Ref || an == BindingAnnotation::RefMut {
-                    let sugg_init = if init.span.from_expansion() {
+                    // use the macro callsite when the init span (but not the whole local span)
+                    // comes from an expansion like `vec![1, 2, 3]` in `let ref _ = vec![1, 2, 3];`
+                    let sugg_init = if init.span.from_expansion() && !local.span.from_expansion() {
                         Sugg::hir_with_macro_callsite(cx, init, "..")
                     } else {
                         Sugg::hir(cx, init, "..")
@@ -310,7 +317,7 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
                         ("", sugg_init.addr())
                     };
                     let tyopt = if let Some(ref ty) = local.ty {
-                        format!(": &{mutopt}{ty}", mutopt=mutopt, ty=snippet(cx, ty.span, "_"))
+                        format!(": &{mutopt}{ty}", mutopt=mutopt, ty=snippet(cx, ty.span, ".."))
                     } else {
                         String::new()
                     };
@@ -326,7 +333,7 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
                                 "try",
                                 format!(
                                     "let {name}{tyopt} = {initref};",
-                                    name=snippet(cx, name.span, "_"),
+                                    name=snippet(cx, name.span, ".."),
                                     tyopt=tyopt,
                                     initref=initref,
                                 ),
diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs
index 6a33aaaaab2..45f3bc3ea85 100644
--- a/clippy_lints/src/types.rs
+++ b/clippy_lints/src/types.rs
@@ -10,9 +10,9 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor};
 use rustc_hir::{
-    BinOpKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, FnSig, GenericArg, GenericParamKind, HirId, ImplItem,
-    ImplItemKind, Item, ItemKind, Lifetime, Lit, Local, MatchSource, MutTy, Mutability, Node, QPath, Stmt, StmtKind,
-    TraitFn, TraitItem, TraitItemKind, TyKind, UnOp,
+    BinOpKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, FnSig, GenericArg, GenericBounds, GenericParamKind, HirId,
+    ImplItem, ImplItemKind, Item, ItemKind, Lifetime, Lit, Local, MatchSource, MutTy, Mutability, Node, QPath, Stmt,
+    StmtKind, SyntheticTyParamKind, TraitFn, TraitItem, TraitItemKind, TyKind, UnOp,
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::hir::map::Map;
@@ -678,17 +678,30 @@ impl Types {
                             // details.
                             return;
                         }
+
+                        // When trait objects or opaque types have lifetime or auto-trait bounds,
+                        // we need to add parentheses to avoid a syntax error due to its ambiguity.
+                        // Originally reported as the issue #3128.
+                        let inner_snippet = snippet(cx, inner.span, "..");
+                        let suggestion = match &inner.kind {
+                            TyKind::TraitObject(bounds, lt_bound) if bounds.len() > 1 || !lt_bound.is_elided() => {
+                                format!("&{}({})", ltopt, &inner_snippet)
+                            },
+                            TyKind::Path(qpath)
+                                if get_bounds_if_impl_trait(cx, qpath, inner.hir_id)
+                                    .map_or(false, |bounds| bounds.len() > 1) =>
+                            {
+                                format!("&{}({})", ltopt, &inner_snippet)
+                            },
+                            _ => format!("&{}{}", ltopt, &inner_snippet),
+                        };
                         span_lint_and_sugg(
                             cx,
                             BORROWED_BOX,
                             hir_ty.span,
                             "you seem to be trying to use `&Box<T>`. Consider using just `&T`",
                             "try",
-                            format!(
-                                "&{}{}",
-                                ltopt,
-                                &snippet(cx, inner.span, "..")
-                            ),
+                            suggestion,
                             // To make this `MachineApplicable`, at least one needs to check if it isn't a trait item
                             // because the trait impls of it will break otherwise;
                             // and there may be other cases that result in invalid code.
@@ -721,6 +734,21 @@ fn is_any_trait(t: &hir::Ty<'_>) -> bool {
     false
 }
 
+fn get_bounds_if_impl_trait<'tcx>(cx: &LateContext<'tcx>, qpath: &QPath<'_>, id: HirId) -> Option<GenericBounds<'tcx>> {
+    if_chain! {
+        if let Some(did) = qpath_res(cx, qpath, id).opt_def_id();
+        if let Some(node) = cx.tcx.hir().get_if_local(did);
+        if let Node::GenericParam(generic_param) = node;
+        if let GenericParamKind::Type { synthetic, .. } = generic_param.kind;
+        if synthetic == Some(SyntheticTyParamKind::ImplTrait);
+        then {
+            Some(generic_param.bounds)
+        } else {
+            None
+        }
+    }
+}
+
 declare_clippy_lint! {
     /// **What it does:** Checks for binding a unit value.
     ///
diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs
index c2e63ecb581..016bda77ef5 100644
--- a/src/lintlist/mod.rs
+++ b/src/lintlist/mod.rs
@@ -299,6 +299,13 @@ vec![
         module: "comparison_chain",
     },
     Lint {
+        name: "comparison_to_empty",
+        group: "style",
+        desc: "checking `x == \"\"` or `x == []` (or similar) when `.is_empty()` could be used instead",
+        deprecation: None,
+        module: "len_zero",
+    },
+    Lint {
         name: "copy_iterator",
         group: "pedantic",
         desc: "implementing `Iterator` on a `Copy` type",
@@ -1223,6 +1230,13 @@ vec![
         module: "map_clone",
     },
     Lint {
+        name: "map_collect_result_unit",
+        group: "style",
+        desc: "using `.map(_).collect::<Result<(),_>()`, which can be replaced with `try_for_each`",
+        deprecation: None,
+        module: "methods",
+    },
+    Lint {
         name: "map_entry",
         group: "perf",
         desc: "use of `contains_key` followed by `insert` on a `HashMap` or `BTreeMap`",
diff --git a/tests/ui/auxiliary/macro_rules.rs b/tests/ui/auxiliary/macro_rules.rs
index 0bbb9534928..93303865e17 100644
--- a/tests/ui/auxiliary/macro_rules.rs
+++ b/tests/ui/auxiliary/macro_rules.rs
@@ -56,3 +56,17 @@ macro_rules! option_env_unwrap_external {
         option_env!($env).expect($message)
     };
 }
+
+#[macro_export]
+macro_rules! ref_arg_binding {
+    () => {
+        let ref _y = 42;
+    };
+}
+
+#[macro_export]
+macro_rules! ref_arg_function {
+    () => {
+        fn fun_example(ref _x: usize) {}
+    };
+}
diff --git a/tests/ui/borrow_box.rs b/tests/ui/borrow_box.rs
index 1901de46ca8..b606f773cfb 100644
--- a/tests/ui/borrow_box.rs
+++ b/tests/ui/borrow_box.rs
@@ -3,6 +3,8 @@
 #![allow(unused_variables)]
 #![allow(dead_code)]
 
+use std::fmt::Display;
+
 pub fn test1(foo: &mut Box<bool>) {
     // Although this function could be changed to "&mut bool",
     // avoiding the Box, mutable references to boxes are not
@@ -89,6 +91,20 @@ pub fn test13(boxed_slice: &mut Box<[i32]>) {
     *boxed_slice = data.into_boxed_slice();
 }
 
+// The suggestion should include proper parentheses to avoid a syntax error.
+pub fn test14(_display: &Box<dyn Display>) {}
+pub fn test15(_display: &Box<dyn Display + Send>) {}
+pub fn test16<'a>(_display: &'a Box<dyn Display + 'a>) {}
+
+pub fn test17(_display: &Box<impl Display>) {}
+pub fn test18(_display: &Box<impl Display + Send>) {}
+pub fn test19<'a>(_display: &'a Box<impl Display + 'a>) {}
+
+// This exists only to check what happens when parentheses are already present.
+// Even though the current implementation doesn't put extra parentheses,
+// it's fine that unnecessary parentheses appear in the future for some reason.
+pub fn test20(_display: &Box<(dyn Display + Send)>) {}
+
 fn main() {
     test1(&mut Box::new(false));
     test2();
diff --git a/tests/ui/borrow_box.stderr b/tests/ui/borrow_box.stderr
index b5db691f89f..3eac32815be 100644
--- a/tests/ui/borrow_box.stderr
+++ b/tests/ui/borrow_box.stderr
@@ -1,5 +1,5 @@
 error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
-  --> $DIR/borrow_box.rs:19:14
+  --> $DIR/borrow_box.rs:21:14
    |
 LL |     let foo: &Box<bool>;
    |              ^^^^^^^^^^ help: try: `&bool`
@@ -11,16 +11,58 @@ LL | #![deny(clippy::borrowed_box)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
-  --> $DIR/borrow_box.rs:23:10
+  --> $DIR/borrow_box.rs:25:10
    |
 LL |     foo: &'a Box<bool>,
    |          ^^^^^^^^^^^^^ help: try: `&'a bool`
 
 error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
-  --> $DIR/borrow_box.rs:27:17
+  --> $DIR/borrow_box.rs:29:17
    |
 LL |     fn test4(a: &Box<bool>);
    |                 ^^^^^^^^^^ help: try: `&bool`
 
-error: aborting due to 3 previous errors
+error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
+  --> $DIR/borrow_box.rs:95:25
+   |
+LL | pub fn test14(_display: &Box<dyn Display>) {}
+   |                         ^^^^^^^^^^^^^^^^^ help: try: `&dyn Display`
+
+error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
+  --> $DIR/borrow_box.rs:96:25
+   |
+LL | pub fn test15(_display: &Box<dyn Display + Send>) {}
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&(dyn Display + Send)`
+
+error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
+  --> $DIR/borrow_box.rs:97:29
+   |
+LL | pub fn test16<'a>(_display: &'a Box<dyn Display + 'a>) {}
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&'a (dyn Display + 'a)`
+
+error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
+  --> $DIR/borrow_box.rs:99:25
+   |
+LL | pub fn test17(_display: &Box<impl Display>) {}
+   |                         ^^^^^^^^^^^^^^^^^^ help: try: `&impl Display`
+
+error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
+  --> $DIR/borrow_box.rs:100:25
+   |
+LL | pub fn test18(_display: &Box<impl Display + Send>) {}
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&(impl Display + Send)`
+
+error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
+  --> $DIR/borrow_box.rs:101:29
+   |
+LL | pub fn test19<'a>(_display: &'a Box<impl Display + 'a>) {}
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&'a (impl Display + 'a)`
+
+error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
+  --> $DIR/borrow_box.rs:106:25
+   |
+LL | pub fn test20(_display: &Box<(dyn Display + Send)>) {}
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&(dyn Display + Send)`
+
+error: aborting due to 10 previous errors
 
diff --git a/tests/ui/comparison_to_empty.fixed b/tests/ui/comparison_to_empty.fixed
new file mode 100644
index 00000000000..261024caca7
--- /dev/null
+++ b/tests/ui/comparison_to_empty.fixed
@@ -0,0 +1,23 @@
+// run-rustfix
+
+#![warn(clippy::comparison_to_empty)]
+
+fn main() {
+    // Disallow comparisons to empty
+    let s = String::new();
+    let _ = s.is_empty();
+    let _ = !s.is_empty();
+
+    let v = vec![0];
+    let _ = v.is_empty();
+    let _ = !v.is_empty();
+
+    // Allow comparisons to non-empty
+    let s = String::new();
+    let _ = s == " ";
+    let _ = s != " ";
+
+    let v = vec![0];
+    let _ = v == [0];
+    let _ = v != [0];
+}
diff --git a/tests/ui/comparison_to_empty.rs b/tests/ui/comparison_to_empty.rs
new file mode 100644
index 00000000000..98ddd974951
--- /dev/null
+++ b/tests/ui/comparison_to_empty.rs
@@ -0,0 +1,23 @@
+// run-rustfix
+
+#![warn(clippy::comparison_to_empty)]
+
+fn main() {
+    // Disallow comparisons to empty
+    let s = String::new();
+    let _ = s == "";
+    let _ = s != "";
+
+    let v = vec![0];
+    let _ = v == [];
+    let _ = v != [];
+
+    // Allow comparisons to non-empty
+    let s = String::new();
+    let _ = s == " ";
+    let _ = s != " ";
+
+    let v = vec![0];
+    let _ = v == [0];
+    let _ = v != [0];
+}
diff --git a/tests/ui/comparison_to_empty.stderr b/tests/ui/comparison_to_empty.stderr
new file mode 100644
index 00000000000..f69d6bd5255
--- /dev/null
+++ b/tests/ui/comparison_to_empty.stderr
@@ -0,0 +1,28 @@
+error: comparison to empty slice
+  --> $DIR/comparison_to_empty.rs:8:13
+   |
+LL |     let _ = s == "";
+   |             ^^^^^^^ help: using `is_empty` is clearer and more explicit: `s.is_empty()`
+   |
+   = note: `-D clippy::comparison-to-empty` implied by `-D warnings`
+
+error: comparison to empty slice
+  --> $DIR/comparison_to_empty.rs:9:13
+   |
+LL |     let _ = s != "";
+   |             ^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!s.is_empty()`
+
+error: comparison to empty slice
+  --> $DIR/comparison_to_empty.rs:12:13
+   |
+LL |     let _ = v == [];
+   |             ^^^^^^^ help: using `is_empty` is clearer and more explicit: `v.is_empty()`
+
+error: comparison to empty slice
+  --> $DIR/comparison_to_empty.rs:13:13
+   |
+LL |     let _ = v != [];
+   |             ^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!v.is_empty()`
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/crashes/ice-6250.rs b/tests/ui/crashes/ice-6250.rs
new file mode 100644
index 00000000000..c33580ff6ab
--- /dev/null
+++ b/tests/ui/crashes/ice-6250.rs
@@ -0,0 +1,16 @@
+// originally from glacier/fixed/77218.rs
+// ice while adjusting...
+
+pub struct Cache {
+    data: Vec<i32>,
+}
+
+pub fn list_data(cache: &Cache, key: usize) {
+    for reference in vec![1, 2, 3] {
+        if
+        /* let */
+        Some(reference) = cache.data.get(key) {
+            unimplemented!()
+        }
+    }
+}
diff --git a/tests/ui/crashes/ice-6250.stderr b/tests/ui/crashes/ice-6250.stderr
new file mode 100644
index 00000000000..8241dcd8feb
--- /dev/null
+++ b/tests/ui/crashes/ice-6250.stderr
@@ -0,0 +1,27 @@
+error[E0601]: `main` function not found in crate `ice_6250`
+  --> $DIR/ice-6250.rs:4:1
+   |
+LL | / pub struct Cache {
+LL | |     data: Vec<i32>,
+LL | | }
+LL | |
+...  |
+LL | |     }
+LL | | }
+   | |_^ consider adding a `main` function to `$DIR/ice-6250.rs`
+
+error[E0308]: mismatched types
+  --> $DIR/ice-6250.rs:12:9
+   |
+LL |         Some(reference) = cache.data.get(key) {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()`
+   |
+help: you might have meant to use pattern matching
+   |
+LL |         let Some(reference) = cache.data.get(key) {
+   |         ^^^
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0308, E0601.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/crashes/ice-6251.rs b/tests/ui/crashes/ice-6251.rs
new file mode 100644
index 00000000000..6aa779aaeb3
--- /dev/null
+++ b/tests/ui/crashes/ice-6251.rs
@@ -0,0 +1,6 @@
+// originally from glacier/fixed/77329.rs
+// assertion failed: `(left == right) ; different DefIds
+
+fn bug<T>() -> impl Iterator<Item = [(); { |x: [u8]| x }]> {
+    std::iter::empty()
+}
diff --git a/tests/ui/crashes/ice-6251.stderr b/tests/ui/crashes/ice-6251.stderr
new file mode 100644
index 00000000000..9a7cf4b0919
--- /dev/null
+++ b/tests/ui/crashes/ice-6251.stderr
@@ -0,0 +1,43 @@
+error[E0601]: `main` function not found in crate `ice_6251`
+  --> $DIR/ice-6251.rs:4:1
+   |
+LL | / fn bug<T>() -> impl Iterator<Item = [(); { |x: [u8]| x }]> {
+LL | |     std::iter::empty()
+LL | | }
+   | |_^ consider adding a `main` function to `$DIR/ice-6251.rs`
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/ice-6251.rs:4:45
+   |
+LL | fn bug<T>() -> impl Iterator<Item = [(); { |x: [u8]| x }]> {
+   |                                             ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[u8]`
+   = help: unsized fn params are gated as an unstable feature
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL | fn bug<T>() -> impl Iterator<Item = [(); { |&x: [u8]| x }]> {
+   |                                             ^
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/ice-6251.rs:4:54
+   |
+LL | fn bug<T>() -> impl Iterator<Item = [(); { |x: [u8]| x }]> {
+   |                                                      ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[u8]`
+   = note: the return type of a function must have a statically known size
+
+error[E0308]: mismatched types
+  --> $DIR/ice-6251.rs:4:44
+   |
+LL | fn bug<T>() -> impl Iterator<Item = [(); { |x: [u8]| x }]> {
+   |                                            ^^^^^^^^^^^ expected `usize`, found closure
+   |
+   = note: expected type `usize`
+           found closure `[closure@$DIR/ice-6251.rs:4:44: 4:55]`
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0277, E0308, E0601.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/crashes/ice-6252.rs b/tests/ui/crashes/ice-6252.rs
new file mode 100644
index 00000000000..2e3d9fd1e92
--- /dev/null
+++ b/tests/ui/crashes/ice-6252.rs
@@ -0,0 +1,15 @@
+// originally from glacier fixed/77919.rs
+// encountered errors resolving bounds after type-checking
+
+trait TypeVal<T> {
+    const VAL: T;
+}
+struct Five;
+struct Multiply<N, M> {
+    _n: PhantomData,
+}
+impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
+
+fn main() {
+    [1; <Multiply<Five, Five>>::VAL];
+}
diff --git a/tests/ui/crashes/ice-6252.stderr b/tests/ui/crashes/ice-6252.stderr
new file mode 100644
index 00000000000..440973e2439
--- /dev/null
+++ b/tests/ui/crashes/ice-6252.stderr
@@ -0,0 +1,46 @@
+error[E0412]: cannot find type `PhantomData` in this scope
+  --> $DIR/ice-6252.rs:9:9
+   |
+LL |     _n: PhantomData,
+   |         ^^^^^^^^^^^ not found in this scope
+   |
+help: consider importing this struct
+   |
+LL | use std::marker::PhantomData;
+   |
+
+error[E0412]: cannot find type `VAL` in this scope
+  --> $DIR/ice-6252.rs:11:63
+   |
+LL | impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
+   |          -                                                    ^^^ not found in this scope
+   |          |
+   |          help: you might be missing a type parameter: `, VAL`
+
+error[E0046]: not all trait items implemented, missing: `VAL`
+  --> $DIR/ice-6252.rs:11:1
+   |
+LL |     const VAL: T;
+   |     ------------- `VAL` from trait
+...
+LL | impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `VAL` in implementation
+
+error: any use of this value will cause an error
+  --> $DIR/ice-6252.rs:5:5
+   |
+LL |     const VAL: T;
+   |     ^^^^^^^^^^^^^ no MIR body is available for DefId(0:5 ~ ice_6252[317d]::TypeVal::VAL)
+   |
+   = note: `#[deny(const_err)]` on by default
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/ice-6252.rs:14:9
+   |
+LL |     [1; <Multiply<Five, Five>>::VAL];
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0046, E0080, E0412.
+For more information about an error, try `rustc --explain E0046`.
diff --git a/tests/ui/crashes/ice-6254.rs b/tests/ui/crashes/ice-6254.rs
new file mode 100644
index 00000000000..c19eca43884
--- /dev/null
+++ b/tests/ui/crashes/ice-6254.rs
@@ -0,0 +1,15 @@
+// originally from ./src/test/ui/pattern/usefulness/consts-opaque.rs
+// panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())',
+// compiler/rustc_mir_build/src/thir/pattern/_match.rs:2030:5
+
+#[derive(PartialEq)]
+struct Foo(i32);
+const FOO_REF_REF: &&Foo = &&Foo(42);
+
+fn main() {
+    // This used to cause an ICE (https://github.com/rust-lang/rust/issues/78071)
+    match FOO_REF_REF {
+        FOO_REF_REF => {},
+        Foo(_) => {},
+    }
+}
diff --git a/tests/ui/crashes/ice-6254.stderr b/tests/ui/crashes/ice-6254.stderr
new file mode 100644
index 00000000000..95ebf23d818
--- /dev/null
+++ b/tests/ui/crashes/ice-6254.stderr
@@ -0,0 +1,12 @@
+error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/ice-6254.rs:12:9
+   |
+LL |         FOO_REF_REF => {},
+   |         ^^^^^^^^^^^
+   |
+   = note: `-D indirect-structural-match` implied by `-D warnings`
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
+
+error: aborting due to previous error
+
diff --git a/tests/ui/crashes/ice-6255.rs b/tests/ui/crashes/ice-6255.rs
new file mode 100644
index 00000000000..bd4a81d98e2
--- /dev/null
+++ b/tests/ui/crashes/ice-6255.rs
@@ -0,0 +1,15 @@
+// originally from rustc ./src/test/ui/macros/issue-78325-inconsistent-resolution.rs
+// inconsistent resolution for a macro
+
+macro_rules! define_other_core {
+    ( ) => {
+        extern crate std as core;
+        //~^ ERROR macro-expanded `extern crate` items cannot shadow names passed with `--extern`
+    };
+}
+
+fn main() {
+    core::panic!();
+}
+
+define_other_core!();
diff --git a/tests/ui/crashes/ice-6255.stderr b/tests/ui/crashes/ice-6255.stderr
new file mode 100644
index 00000000000..d973ea1e23a
--- /dev/null
+++ b/tests/ui/crashes/ice-6255.stderr
@@ -0,0 +1,13 @@
+error: macro-expanded `extern crate` items cannot shadow names passed with `--extern`
+  --> $DIR/ice-6255.rs:6:9
+   |
+LL |         extern crate std as core;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | define_other_core!();
+   | --------------------- in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/tests/ui/crashes/ice-6256.rs b/tests/ui/crashes/ice-6256.rs
new file mode 100644
index 00000000000..6f60d45d68a
--- /dev/null
+++ b/tests/ui/crashes/ice-6256.rs
@@ -0,0 +1,13 @@
+// originally from rustc ./src/test/ui/regions/issue-78262.rs
+// ICE: to get the signature of a closure, use substs.as_closure().sig() not fn_sig()
+
+trait TT {}
+
+impl dyn TT {
+    fn func(&self) {}
+}
+
+fn main() {
+    let f = |x: &dyn TT| x.func(); //[default]~ ERROR: mismatched types
+                                   //[nll]~^ ERROR: borrowed data escapes outside of closure
+}
diff --git a/tests/ui/crashes/ice-6256.stderr b/tests/ui/crashes/ice-6256.stderr
new file mode 100644
index 00000000000..0e8353a418a
--- /dev/null
+++ b/tests/ui/crashes/ice-6256.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+  --> $DIR/ice-6256.rs:11:28
+   |
+LL |     let f = |x: &dyn TT| x.func(); //[default]~ ERROR: mismatched types
+   |                            ^^^^ lifetime mismatch
+   |
+   = note: expected reference `&(dyn TT + 'static)`
+              found reference `&dyn TT`
+note: the anonymous lifetime #1 defined on the body at 11:13...
+  --> $DIR/ice-6256.rs:11:13
+   |
+LL |     let f = |x: &dyn TT| x.func(); //[default]~ ERROR: mismatched types
+   |             ^^^^^^^^^^^^^^^^^^^^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/filter_map_next.rs b/tests/ui/filter_map_next.rs
index f5d051be198..dbeb2354309 100644
--- a/tests/ui/filter_map_next.rs
+++ b/tests/ui/filter_map_next.rs
@@ -3,9 +3,6 @@
 fn main() {
     let a = ["1", "lol", "3", "NaN", "5"];
 
-    let element: Option<i32> = a.iter().filter_map(|s| s.parse().ok()).next();
-    assert_eq!(element, Some(1));
-
     #[rustfmt::skip]
     let _: Option<u32> = vec![1, 2, 3, 4, 5, 6]
         .into_iter()
diff --git a/tests/ui/filter_map_next.stderr b/tests/ui/filter_map_next.stderr
index d69ae212414..45427684d96 100644
--- a/tests/ui/filter_map_next.stderr
+++ b/tests/ui/filter_map_next.stderr
@@ -1,14 +1,5 @@
-error: called `filter_map(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find_map(p)` instead.
-  --> $DIR/filter_map_next.rs:6:32
-   |
-LL |     let element: Option<i32> = a.iter().filter_map(|s| s.parse().ok()).next();
-   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `-D clippy::filter-map-next` implied by `-D warnings`
-   = note: replace `filter_map(|s| s.parse().ok()).next()` with `find_map(|s| s.parse().ok())`
-
-error: called `filter_map(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find_map(p)` instead.
-  --> $DIR/filter_map_next.rs:10:26
+error: called `filter_map(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find_map(..)` instead.
+  --> $DIR/filter_map_next.rs:7:26
    |
 LL |       let _: Option<u32> = vec![1, 2, 3, 4, 5, 6]
    |  __________________________^
@@ -19,6 +10,8 @@ LL | |             if x == 2 {
 LL | |         })
 LL | |         .next();
    | |_______________^
+   |
+   = note: `-D clippy::filter-map-next` implied by `-D warnings`
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/tests/ui/filter_map_next_fixable.fixed b/tests/ui/filter_map_next_fixable.fixed
new file mode 100644
index 00000000000..c3992d7e92c
--- /dev/null
+++ b/tests/ui/filter_map_next_fixable.fixed
@@ -0,0 +1,10 @@
+// run-rustfix
+
+#![warn(clippy::all, clippy::pedantic)]
+
+fn main() {
+    let a = ["1", "lol", "3", "NaN", "5"];
+
+    let element: Option<i32> = a.iter().find_map(|s| s.parse().ok());
+    assert_eq!(element, Some(1));
+}
diff --git a/tests/ui/filter_map_next_fixable.rs b/tests/ui/filter_map_next_fixable.rs
new file mode 100644
index 00000000000..447219a9683
--- /dev/null
+++ b/tests/ui/filter_map_next_fixable.rs
@@ -0,0 +1,10 @@
+// run-rustfix
+
+#![warn(clippy::all, clippy::pedantic)]
+
+fn main() {
+    let a = ["1", "lol", "3", "NaN", "5"];
+
+    let element: Option<i32> = a.iter().filter_map(|s| s.parse().ok()).next();
+    assert_eq!(element, Some(1));
+}
diff --git a/tests/ui/filter_map_next_fixable.stderr b/tests/ui/filter_map_next_fixable.stderr
new file mode 100644
index 00000000000..6c2530e0379
--- /dev/null
+++ b/tests/ui/filter_map_next_fixable.stderr
@@ -0,0 +1,10 @@
+error: called `filter_map(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find_map(..)` instead.
+  --> $DIR/filter_map_next_fixable.rs:8:32
+   |
+LL |     let element: Option<i32> = a.iter().filter_map(|s| s.parse().ok()).next();
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `a.iter().find_map(|s| s.parse().ok())`
+   |
+   = note: `-D clippy::filter-map-next` implied by `-D warnings`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/filter_methods.stderr b/tests/ui/filter_methods.stderr
index 84a957a374c..91718dd1175 100644
--- a/tests/ui/filter_methods.stderr
+++ b/tests/ui/filter_methods.stderr
@@ -1,4 +1,4 @@
-error: called `filter(p).map(q)` on an `Iterator`
+error: called `filter(..).map(..)` on an `Iterator`
   --> $DIR/filter_methods.rs:5:21
    |
 LL |     let _: Vec<_> = vec![5; 6].into_iter().filter(|&x| x == 0).map(|x| x * 2).collect();
@@ -7,7 +7,7 @@ LL |     let _: Vec<_> = vec![5; 6].into_iter().filter(|&x| x == 0).map(|x| x *
    = note: `-D clippy::filter-map` implied by `-D warnings`
    = help: this is more succinctly expressed by calling `.filter_map(..)` instead
 
-error: called `filter(p).flat_map(q)` on an `Iterator`
+error: called `filter(..).flat_map(..)` on an `Iterator`
   --> $DIR/filter_methods.rs:7:21
    |
 LL |       let _: Vec<_> = vec![5_i8; 6]
@@ -19,7 +19,7 @@ LL | |         .flat_map(|x| x.checked_mul(2))
    |
    = help: this is more succinctly expressed by calling `.flat_map(..)` and filtering by returning `iter::empty()`
 
-error: called `filter_map(p).flat_map(q)` on an `Iterator`
+error: called `filter_map(..).flat_map(..)` on an `Iterator`
   --> $DIR/filter_methods.rs:13:21
    |
 LL |       let _: Vec<_> = vec![5_i8; 6]
@@ -31,7 +31,7 @@ LL | |         .flat_map(|x| x.checked_mul(2))
    |
    = help: this is more succinctly expressed by calling `.flat_map(..)` and filtering by returning `iter::empty()`
 
-error: called `filter_map(p).map(q)` on an `Iterator`
+error: called `filter_map(..).map(..)` on an `Iterator`
   --> $DIR/filter_methods.rs:19:21
    |
 LL |       let _: Vec<_> = vec![5_i8; 6]
diff --git a/tests/ui/find_map.stderr b/tests/ui/find_map.stderr
index f279850fef8..aea3cc62afc 100644
--- a/tests/ui/find_map.stderr
+++ b/tests/ui/find_map.stderr
@@ -1,4 +1,4 @@
-error: called `find(p).map(q)` on an `Iterator`
+error: called `find(..).map(..)` on an `Iterator`
   --> $DIR/find_map.rs:20:26
    |
 LL |     let _: Option<i32> = a.iter().find(|s| s.parse::<i32>().is_ok()).map(|s| s.parse().unwrap());
@@ -7,7 +7,7 @@ LL |     let _: Option<i32> = a.iter().find(|s| s.parse::<i32>().is_ok()).map(|s
    = note: `-D clippy::find-map` implied by `-D warnings`
    = help: this is more succinctly expressed by calling `.find_map(..)` instead
 
-error: called `find(p).map(q)` on an `Iterator`
+error: called `find(..).map(..)` on an `Iterator`
   --> $DIR/find_map.rs:23:29
    |
 LL |       let _: Option<Flavor> = desserts_of_the_week
diff --git a/tests/ui/integer_arithmetic.rs b/tests/ui/integer_arithmetic.rs
index 7b1b64f390a..b74c93dc4a6 100644
--- a/tests/ui/integer_arithmetic.rs
+++ b/tests/ui/integer_arithmetic.rs
@@ -11,6 +11,8 @@
 #[rustfmt::skip]
 fn main() {
     let mut i = 1i32;
+    let mut var1 = 0i32;
+    let mut var2 = -1i32;
     1 + i;
     i * 2;
     1 %
@@ -32,7 +34,15 @@ fn main() {
     i -= 1;
     i *= 2;
     i /= 2;
+    i /= 0;
+    i /= -1;
+    i /= var1;
+    i /= var2;
     i %= 2;
+    i %= 0;
+    i %= -1;
+    i %= var1;
+    i %= var2;
     i <<= 3;
     i >>= 2;
 
diff --git a/tests/ui/integer_arithmetic.stderr b/tests/ui/integer_arithmetic.stderr
index 83e8a9cde3f..add3b6b90fa 100644
--- a/tests/ui/integer_arithmetic.stderr
+++ b/tests/ui/integer_arithmetic.stderr
@@ -1,5 +1,19 @@
+error: this operation will panic at runtime
+  --> $DIR/integer_arithmetic.rs:37:5
+   |
+LL |     i /= 0;
+   |     ^^^^^^ attempt to divide `_` by zero
+   |
+   = note: `#[deny(unconditional_panic)]` on by default
+
+error: this operation will panic at runtime
+  --> $DIR/integer_arithmetic.rs:42:5
+   |
+LL |     i %= 0;
+   |     ^^^^^^ attempt to calculate the remainder of `_` with a divisor of zero
+
 error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:14:5
+  --> $DIR/integer_arithmetic.rs:16:5
    |
 LL |     1 + i;
    |     ^^^^^
@@ -7,125 +21,149 @@ LL |     1 + i;
    = note: `-D clippy::integer-arithmetic` implied by `-D warnings`
 
 error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:15:5
+  --> $DIR/integer_arithmetic.rs:17:5
    |
 LL |     i * 2;
    |     ^^^^^
 
 error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:16:5
+  --> $DIR/integer_arithmetic.rs:18:5
    |
 LL | /     1 %
 LL | |     i / 2; // no error, this is part of the expression in the preceding line
-   | |_________^
+   | |_____^
 
 error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:18:5
+  --> $DIR/integer_arithmetic.rs:20:5
    |
 LL |     i - 2 + 2 - i;
    |     ^^^^^^^^^^^^^
 
 error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:19:5
+  --> $DIR/integer_arithmetic.rs:21:5
    |
 LL |     -i;
    |     ^^
 
 error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:20:5
+  --> $DIR/integer_arithmetic.rs:22:5
    |
 LL |     i >> 1;
    |     ^^^^^^
 
 error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:21:5
+  --> $DIR/integer_arithmetic.rs:23:5
    |
 LL |     i << 1;
    |     ^^^^^^
 
 error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:31:5
+  --> $DIR/integer_arithmetic.rs:33:5
    |
 LL |     i += 1;
    |     ^^^^^^
 
 error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:32:5
+  --> $DIR/integer_arithmetic.rs:34:5
    |
 LL |     i -= 1;
    |     ^^^^^^
 
 error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:33:5
+  --> $DIR/integer_arithmetic.rs:35:5
    |
 LL |     i *= 2;
    |     ^^^^^^
 
 error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:34:5
+  --> $DIR/integer_arithmetic.rs:38:11
    |
-LL |     i /= 2;
-   |     ^^^^^^
+LL |     i /= -1;
+   |           ^
 
 error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:35:5
+  --> $DIR/integer_arithmetic.rs:39:5
    |
-LL |     i %= 2;
-   |     ^^^^^^
+LL |     i /= var1;
+   |     ^^^^^^^^^
+
+error: integer arithmetic detected
+  --> $DIR/integer_arithmetic.rs:40:5
+   |
+LL |     i /= var2;
+   |     ^^^^^^^^^
+
+error: integer arithmetic detected
+  --> $DIR/integer_arithmetic.rs:43:11
+   |
+LL |     i %= -1;
+   |           ^
+
+error: integer arithmetic detected
+  --> $DIR/integer_arithmetic.rs:44:5
+   |
+LL |     i %= var1;
+   |     ^^^^^^^^^
+
+error: integer arithmetic detected
+  --> $DIR/integer_arithmetic.rs:45:5
+   |
+LL |     i %= var2;
+   |     ^^^^^^^^^
 
 error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:36:5
+  --> $DIR/integer_arithmetic.rs:46:5
    |
 LL |     i <<= 3;
    |     ^^^^^^^
 
 error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:37:5
+  --> $DIR/integer_arithmetic.rs:47:5
    |
 LL |     i >>= 2;
    |     ^^^^^^^
 
 error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:79:5
+  --> $DIR/integer_arithmetic.rs:89:5
    |
 LL |     3 + &1;
    |     ^^^^^^
 
 error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:80:5
+  --> $DIR/integer_arithmetic.rs:90:5
    |
 LL |     &3 + 1;
    |     ^^^^^^
 
 error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:81:5
+  --> $DIR/integer_arithmetic.rs:91:5
    |
 LL |     &3 + &1;
    |     ^^^^^^^
 
 error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:86:5
+  --> $DIR/integer_arithmetic.rs:96:5
    |
 LL |     a + x
    |     ^^^^^
 
 error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:90:5
+  --> $DIR/integer_arithmetic.rs:100:5
    |
 LL |     x + y
    |     ^^^^^
 
 error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:94:5
+  --> $DIR/integer_arithmetic.rs:104:5
    |
 LL |     x + y
    |     ^^^^^
 
 error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:98:5
+  --> $DIR/integer_arithmetic.rs:108:5
    |
 LL |     (&x + &y)
    |     ^^^^^^^^^
 
-error: aborting due to 21 previous errors
+error: aborting due to 27 previous errors
 
diff --git a/tests/ui/item_after_statement.rs b/tests/ui/item_after_statement.rs
index c17a7cbc8d9..377e58e4417 100644
--- a/tests/ui/item_after_statement.rs
+++ b/tests/ui/item_after_statement.rs
@@ -28,7 +28,10 @@ fn mac() {
     // do not lint this, because it needs to be after `a`
     macro_rules! b {
         () => {{
-            a = 6
+            a = 6;
+            fn say_something() {
+                println!("something");
+            }
         }};
     }
     b!();
diff --git a/tests/ui/item_after_statement.stderr b/tests/ui/item_after_statement.stderr
index f8f010b5e5c..68a3c81b6a8 100644
--- a/tests/ui/item_after_statement.stderr
+++ b/tests/ui/item_after_statement.stderr
@@ -16,5 +16,18 @@ LL | |         println!("foo");
 LL | |     }
    | |_____^
 
-error: aborting due to 2 previous errors
+error: adding items after statements is confusing, since items exist from the start of the scope
+  --> $DIR/item_after_statement.rs:32:13
+   |
+LL | /             fn say_something() {
+LL | |                 println!("something");
+LL | |             }
+   | |_____________^
+...
+LL |       b!();
+   |       ----- in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/iter_skip_next.stderr b/tests/ui/iter_skip_next.stderr
index feedc2f288a..486de718bb5 100644
--- a/tests/ui/iter_skip_next.stderr
+++ b/tests/ui/iter_skip_next.stderr
@@ -1,4 +1,4 @@
-error: called `skip(x).next()` on an iterator
+error: called `skip(..).next()` on an iterator
   --> $DIR/iter_skip_next.rs:15:28
    |
 LL |     let _ = some_vec.iter().skip(42).next();
@@ -6,19 +6,19 @@ LL |     let _ = some_vec.iter().skip(42).next();
    |
    = note: `-D clippy::iter-skip-next` implied by `-D warnings`
 
-error: called `skip(x).next()` on an iterator
+error: called `skip(..).next()` on an iterator
   --> $DIR/iter_skip_next.rs:16:36
    |
 LL |     let _ = some_vec.iter().cycle().skip(42).next();
    |                                    ^^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(42)`
 
-error: called `skip(x).next()` on an iterator
+error: called `skip(..).next()` on an iterator
   --> $DIR/iter_skip_next.rs:17:20
    |
 LL |     let _ = (1..10).skip(10).next();
    |                    ^^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(10)`
 
-error: called `skip(x).next()` on an iterator
+error: called `skip(..).next()` on an iterator
   --> $DIR/iter_skip_next.rs:18:33
    |
 LL |     let _ = &some_vec[..].iter().skip(3).next();
diff --git a/tests/ui/map_collect_result_unit.fixed b/tests/ui/map_collect_result_unit.fixed
new file mode 100644
index 00000000000..e66c9cc2420
--- /dev/null
+++ b/tests/ui/map_collect_result_unit.fixed
@@ -0,0 +1,16 @@
+// run-rustfix
+#![warn(clippy::map_collect_result_unit)]
+
+fn main() {
+    {
+        let _ = (0..3).try_for_each(|t| Err(t + 1));
+        let _: Result<(), _> = (0..3).try_for_each(|t| Err(t + 1));
+
+        let _ = (0..3).try_for_each(|t| Err(t + 1));
+    }
+}
+
+fn _ignore() {
+    let _ = (0..3).map(|t| Err(t + 1)).collect::<Result<Vec<i32>, _>>();
+    let _ = (0..3).map(|t| Err(t + 1)).collect::<Vec<Result<(), _>>>();
+}
diff --git a/tests/ui/map_collect_result_unit.rs b/tests/ui/map_collect_result_unit.rs
new file mode 100644
index 00000000000..6f08f4c3c53
--- /dev/null
+++ b/tests/ui/map_collect_result_unit.rs
@@ -0,0 +1,16 @@
+// run-rustfix
+#![warn(clippy::map_collect_result_unit)]
+
+fn main() {
+    {
+        let _ = (0..3).map(|t| Err(t + 1)).collect::<Result<(), _>>();
+        let _: Result<(), _> = (0..3).map(|t| Err(t + 1)).collect();
+
+        let _ = (0..3).try_for_each(|t| Err(t + 1));
+    }
+}
+
+fn _ignore() {
+    let _ = (0..3).map(|t| Err(t + 1)).collect::<Result<Vec<i32>, _>>();
+    let _ = (0..3).map(|t| Err(t + 1)).collect::<Vec<Result<(), _>>>();
+}
diff --git a/tests/ui/map_collect_result_unit.stderr b/tests/ui/map_collect_result_unit.stderr
new file mode 100644
index 00000000000..8b06e13baa6
--- /dev/null
+++ b/tests/ui/map_collect_result_unit.stderr
@@ -0,0 +1,16 @@
+error: `.map().collect()` can be replaced with `.try_for_each()`
+  --> $DIR/map_collect_result_unit.rs:6:17
+   |
+LL |         let _ = (0..3).map(|t| Err(t + 1)).collect::<Result<(), _>>();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(0..3).try_for_each(|t| Err(t + 1))`
+   |
+   = note: `-D clippy::map-collect-result-unit` implied by `-D warnings`
+
+error: `.map().collect()` can be replaced with `.try_for_each()`
+  --> $DIR/map_collect_result_unit.rs:7:32
+   |
+LL |         let _: Result<(), _> = (0..3).map(|t| Err(t + 1)).collect();
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(0..3).try_for_each(|t| Err(t + 1))`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/map_unwrap_or.rs b/tests/ui/map_unwrap_or.rs
index 585944032e7..87e16f5d09b 100644
--- a/tests/ui/map_unwrap_or.rs
+++ b/tests/ui/map_unwrap_or.rs
@@ -1,4 +1,3 @@
-// FIXME: Add "run-rustfix" once it's supported for multipart suggestions
 // aux-build:option_helpers.rs
 
 #![warn(clippy::map_unwrap_or)]
@@ -47,10 +46,6 @@ fn option_methods() {
     let _ = Some("prefix").map(|p| format!("{}.", p)).unwrap_or(id);
 
     // Check for `option.map(_).unwrap_or_else(_)` use.
-    // single line case
-    let _ = opt.map(|x| x + 1)
-        // Should lint even though this call is on a separate line.
-        .unwrap_or_else(|| 0);
     // Multi-line cases.
     let _ = opt.map(|x| {
         x + 1
@@ -60,37 +55,24 @@ fn option_methods() {
         .unwrap_or_else(||
             0
         );
-    // Macro case.
-    // Should not lint.
-    let _ = opt_map!(opt, |x| x + 1).unwrap_or_else(|| 0);
-
-    // Issue #4144
-    {
-        let mut frequencies = HashMap::new();
-        let word = "foo";
-
-        frequencies
-            .get_mut(word)
-            .map(|count| {
-                *count += 1;
-            })
-            .unwrap_or_else(|| {
-                frequencies.insert(word.to_owned(), 1);
-            });
-    }
 }
 
+#[rustfmt::skip]
 fn result_methods() {
     let res: Result<i32, ()> = Ok(1);
 
     // Check for `result.map(_).unwrap_or_else(_)` use.
-    // single line case
-    let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); // should lint even though this call is on a separate line
-                                                      // multi line cases
-    let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0);
-    let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0);
+    // multi line cases
+    let _ = res.map(|x| {
+        x + 1
+    }
+    ).unwrap_or_else(|_e| 0);
+    let _ = res.map(|x| x + 1)
+        .unwrap_or_else(|_e| {
+            0
+        });
     // macro case
-    let _ = opt_map!(res, |x| x + 1).unwrap_or_else(|e| 0); // should not lint
+    let _ = opt_map!(res, |x| x + 1).unwrap_or_else(|_e| 0); // should not lint
 }
 
 fn main() {
diff --git a/tests/ui/map_unwrap_or.stderr b/tests/ui/map_unwrap_or.stderr
index b62080a073f..96b9d6cc3c1 100644
--- a/tests/ui/map_unwrap_or.stderr
+++ b/tests/ui/map_unwrap_or.stderr
@@ -1,5 +1,5 @@
-error: called `map(f).unwrap_or(a)` on an `Option` value. This can be done more directly by calling `map_or(a, f)` instead
-  --> $DIR/map_unwrap_or.rs:17:13
+error: called `map(<f>).unwrap_or(<a>)` on an `Option` value. This can be done more directly by calling `map_or(<a>, <f>)` instead
+  --> $DIR/map_unwrap_or.rs:16:13
    |
 LL |       let _ = opt.map(|x| x + 1)
    |  _____________^
@@ -8,13 +8,13 @@ LL | |         .unwrap_or(0);
    | |_____________________^
    |
    = note: `-D clippy::map-unwrap-or` implied by `-D warnings`
-help: use `map_or(a, f)` instead
+help: use `map_or(<a>, <f>)` instead
    |
 LL |     let _ = opt.map_or(0, |x| x + 1);
    |                 ^^^^^^ ^^          --
 
-error: called `map(f).unwrap_or(a)` on an `Option` value. This can be done more directly by calling `map_or(a, f)` instead
-  --> $DIR/map_unwrap_or.rs:21:13
+error: called `map(<f>).unwrap_or(<a>)` on an `Option` value. This can be done more directly by calling `map_or(<a>, <f>)` instead
+  --> $DIR/map_unwrap_or.rs:20:13
    |
 LL |       let _ = opt.map(|x| {
    |  _____________^
@@ -23,7 +23,7 @@ LL | |     }
 LL | |     ).unwrap_or(0);
    | |__________________^
    |
-help: use `map_or(a, f)` instead
+help: use `map_or(<a>, <f>)` instead
    |
 LL |     let _ = opt.map_or(0, |x| {
 LL |         x + 1
@@ -31,8 +31,8 @@ LL |     }
 LL |     );
    |
 
-error: called `map(f).unwrap_or(a)` on an `Option` value. This can be done more directly by calling `map_or(a, f)` instead
-  --> $DIR/map_unwrap_or.rs:25:13
+error: called `map(<f>).unwrap_or(<a>)` on an `Option` value. This can be done more directly by calling `map_or(<a>, <f>)` instead
+  --> $DIR/map_unwrap_or.rs:24:13
    |
 LL |       let _ = opt.map(|x| x + 1)
    |  _____________^
@@ -41,26 +41,26 @@ LL | |             0
 LL | |         });
    | |__________^
    |
-help: use `map_or(a, f)` instead
+help: use `map_or(<a>, <f>)` instead
    |
 LL |     let _ = opt.map_or({
 LL |             0
 LL |         }, |x| x + 1);
    |
 
-error: called `map(f).unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then(f)` instead
-  --> $DIR/map_unwrap_or.rs:30:13
+error: called `map(<f>).unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then(<f>)` instead
+  --> $DIR/map_unwrap_or.rs:29:13
    |
 LL |     let _ = opt.map(|x| Some(x + 1)).unwrap_or(None);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: use `and_then(f)` instead
+help: use `and_then(<f>)` instead
    |
 LL |     let _ = opt.and_then(|x| Some(x + 1));
    |                 ^^^^^^^^                --
 
-error: called `map(f).unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then(f)` instead
-  --> $DIR/map_unwrap_or.rs:32:13
+error: called `map(<f>).unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then(<f>)` instead
+  --> $DIR/map_unwrap_or.rs:31:13
    |
 LL |       let _ = opt.map(|x| {
    |  _____________^
@@ -69,7 +69,7 @@ LL | |     }
 LL | |     ).unwrap_or(None);
    | |_____________________^
    |
-help: use `and_then(f)` instead
+help: use `and_then(<f>)` instead
    |
 LL |     let _ = opt.and_then(|x| {
 LL |         Some(x + 1)
@@ -77,8 +77,8 @@ LL |     }
 LL |     );
    |
 
-error: called `map(f).unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then(f)` instead
-  --> $DIR/map_unwrap_or.rs:36:13
+error: called `map(<f>).unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then(<f>)` instead
+  --> $DIR/map_unwrap_or.rs:35:13
    |
 LL |       let _ = opt
    |  _____________^
@@ -86,35 +86,24 @@ LL | |         .map(|x| Some(x + 1))
 LL | |         .unwrap_or(None);
    | |________________________^
    |
-help: use `and_then(f)` instead
+help: use `and_then(<f>)` instead
    |
 LL |         .and_then(|x| Some(x + 1));
    |          ^^^^^^^^                --
 
-error: called `map(f).unwrap_or(a)` on an `Option` value. This can be done more directly by calling `map_or(a, f)` instead
-  --> $DIR/map_unwrap_or.rs:47:13
+error: called `map(<f>).unwrap_or(<a>)` on an `Option` value. This can be done more directly by calling `map_or(<a>, <f>)` instead
+  --> $DIR/map_unwrap_or.rs:46:13
    |
 LL |     let _ = Some("prefix").map(|p| format!("{}.", p)).unwrap_or(id);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: use `map_or(a, f)` instead
+help: use `map_or(<a>, <f>)` instead
    |
 LL |     let _ = Some("prefix").map_or(id, |p| format!("{}.", p));
    |                            ^^^^^^ ^^^                      --
 
-error: called `map(f).unwrap_or_else(g)` on an `Option` value. This can be done more directly by calling `map_or_else(g, f)` instead
-  --> $DIR/map_unwrap_or.rs:51:13
-   |
-LL |       let _ = opt.map(|x| x + 1)
-   |  _____________^
-LL | |         // Should lint even though this call is on a separate line.
-LL | |         .unwrap_or_else(|| 0);
-   | |_____________________________^
-   |
-   = note: replace `map(|x| x + 1).unwrap_or_else(|| 0)` with `map_or_else(|| 0, |x| x + 1)`
-
-error: called `map(f).unwrap_or_else(g)` on an `Option` value. This can be done more directly by calling `map_or_else(g, f)` instead
-  --> $DIR/map_unwrap_or.rs:55:13
+error: called `map(<f>).unwrap_or_else(<g>)` on an `Option` value. This can be done more directly by calling `map_or_else(<g>, <f>)` instead
+  --> $DIR/map_unwrap_or.rs:50:13
    |
 LL |       let _ = opt.map(|x| {
    |  _____________^
@@ -123,8 +112,8 @@ LL | |     }
 LL | |     ).unwrap_or_else(|| 0);
    | |__________________________^
 
-error: called `map(f).unwrap_or_else(g)` on an `Option` value. This can be done more directly by calling `map_or_else(g, f)` instead
-  --> $DIR/map_unwrap_or.rs:59:13
+error: called `map(<f>).unwrap_or_else(<g>)` on an `Option` value. This can be done more directly by calling `map_or_else(<g>, <f>)` instead
+  --> $DIR/map_unwrap_or.rs:54:13
    |
 LL |       let _ = opt.map(|x| x + 1)
    |  _____________^
@@ -133,29 +122,25 @@ LL | |             0
 LL | |         );
    | |_________^
 
-error: called `map(f).unwrap_or_else(g)` on a `Result` value. This can be done more directly by calling `.map_or_else(g, f)` instead
-  --> $DIR/map_unwrap_or.rs:88:13
+error: called `map(<f>).unwrap_or_else(<g>)` on a `Result` value. This can be done more directly by calling `.map_or_else(<g>, <f>)` instead
+  --> $DIR/map_unwrap_or.rs:66:13
    |
-LL |     let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); // should lint even though this call is on a separate line
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `map_or_else(|e| 0, |x| x + 1)`
-
-error: called `map(f).unwrap_or_else(g)` on a `Result` value. This can be done more directly by calling `.map_or_else(g, f)` instead
-  --> $DIR/map_unwrap_or.rs:90:13
-   |
-LL |     let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `map_or_else(|e| 0, |x| x + 1)`
+LL |       let _ = res.map(|x| {
+   |  _____________^
+LL | |         x + 1
+LL | |     }
+LL | |     ).unwrap_or_else(|_e| 0);
+   | |____________________________^
 
-error: called `map(f).unwrap_or_else(g)` on a `Result` value. This can be done more directly by calling `.map_or_else(g, f)` instead
-  --> $DIR/map_unwrap_or.rs:91:13
-   |
-LL |     let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+error: called `map(<f>).unwrap_or_else(<g>)` on a `Result` value. This can be done more directly by calling `.map_or_else(<g>, <f>)` instead
+  --> $DIR/map_unwrap_or.rs:70:13
    |
-   = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `map_or_else(|e| 0, |x| x + 1)`
+LL |       let _ = res.map(|x| x + 1)
+   |  _____________^
+LL | |         .unwrap_or_else(|_e| {
+LL | |             0
+LL | |         });
+   | |__________^
 
-error: aborting due to 13 previous errors
+error: aborting due to 11 previous errors
 
diff --git a/tests/ui/map_unwrap_or_fixable.fixed b/tests/ui/map_unwrap_or_fixable.fixed
new file mode 100644
index 00000000000..bd5b4f7165a
--- /dev/null
+++ b/tests/ui/map_unwrap_or_fixable.fixed
@@ -0,0 +1,54 @@
+// run-rustfix
+// aux-build:option_helpers.rs
+
+#![warn(clippy::map_unwrap_or)]
+
+#[macro_use]
+extern crate option_helpers;
+
+use std::collections::HashMap;
+
+#[rustfmt::skip]
+fn option_methods() {
+    let opt = Some(1);
+
+    // Check for `option.map(_).unwrap_or_else(_)` use.
+    // single line case
+    let _ = opt.map_or_else(|| 0, |x| x + 1);
+
+    // Macro case.
+    // Should not lint.
+    let _ = opt_map!(opt, |x| x + 1).unwrap_or_else(|| 0);
+
+    // Issue #4144
+    {
+        let mut frequencies = HashMap::new();
+        let word = "foo";
+
+        frequencies
+            .get_mut(word)
+            .map(|count| {
+                *count += 1;
+            })
+            .unwrap_or_else(|| {
+                frequencies.insert(word.to_owned(), 1);
+            });
+    }
+}
+
+#[rustfmt::skip]
+fn result_methods() {
+    let res: Result<i32, ()> = Ok(1);
+
+    // Check for `result.map(_).unwrap_or_else(_)` use.
+    // single line case
+    let _ = res.map_or_else(|_e| 0, |x| x + 1);
+
+    // macro case
+    let _ = opt_map!(res, |x| x + 1).unwrap_or_else(|_e| 0); // should not lint
+}
+
+fn main() {
+    option_methods();
+    result_methods();
+}
diff --git a/tests/ui/map_unwrap_or_fixable.rs b/tests/ui/map_unwrap_or_fixable.rs
new file mode 100644
index 00000000000..0b892caf20e
--- /dev/null
+++ b/tests/ui/map_unwrap_or_fixable.rs
@@ -0,0 +1,58 @@
+// run-rustfix
+// aux-build:option_helpers.rs
+
+#![warn(clippy::map_unwrap_or)]
+
+#[macro_use]
+extern crate option_helpers;
+
+use std::collections::HashMap;
+
+#[rustfmt::skip]
+fn option_methods() {
+    let opt = Some(1);
+
+    // Check for `option.map(_).unwrap_or_else(_)` use.
+    // single line case
+    let _ = opt.map(|x| x + 1)
+        // Should lint even though this call is on a separate line.
+        .unwrap_or_else(|| 0);
+
+    // Macro case.
+    // Should not lint.
+    let _ = opt_map!(opt, |x| x + 1).unwrap_or_else(|| 0);
+
+    // Issue #4144
+    {
+        let mut frequencies = HashMap::new();
+        let word = "foo";
+
+        frequencies
+            .get_mut(word)
+            .map(|count| {
+                *count += 1;
+            })
+            .unwrap_or_else(|| {
+                frequencies.insert(word.to_owned(), 1);
+            });
+    }
+}
+
+#[rustfmt::skip]
+fn result_methods() {
+    let res: Result<i32, ()> = Ok(1);
+
+    // Check for `result.map(_).unwrap_or_else(_)` use.
+    // single line case
+    let _ = res.map(|x| x + 1)
+        // should lint even though this call is on a separate line
+        .unwrap_or_else(|_e| 0);
+
+    // macro case
+    let _ = opt_map!(res, |x| x + 1).unwrap_or_else(|_e| 0); // should not lint
+}
+
+fn main() {
+    option_methods();
+    result_methods();
+}
diff --git a/tests/ui/map_unwrap_or_fixable.stderr b/tests/ui/map_unwrap_or_fixable.stderr
new file mode 100644
index 00000000000..1837bc2ca3b
--- /dev/null
+++ b/tests/ui/map_unwrap_or_fixable.stderr
@@ -0,0 +1,22 @@
+error: called `map(<f>).unwrap_or_else(<g>)` on an `Option` value. This can be done more directly by calling `map_or_else(<g>, <f>)` instead
+  --> $DIR/map_unwrap_or_fixable.rs:17:13
+   |
+LL |       let _ = opt.map(|x| x + 1)
+   |  _____________^
+LL | |         // Should lint even though this call is on a separate line.
+LL | |         .unwrap_or_else(|| 0);
+   | |_____________________________^ help: try this: `opt.map_or_else(|| 0, |x| x + 1)`
+   |
+   = note: `-D clippy::map-unwrap-or` implied by `-D warnings`
+
+error: called `map(<f>).unwrap_or_else(<g>)` on a `Result` value. This can be done more directly by calling `.map_or_else(<g>, <f>)` instead
+  --> $DIR/map_unwrap_or_fixable.rs:47:13
+   |
+LL |       let _ = res.map(|x| x + 1)
+   |  _____________^
+LL | |         // should lint even though this call is on a separate line
+LL | |         .unwrap_or_else(|_e| 0);
+   | |_______________________________^ help: try this: `res.map_or_else(|_e| 0, |x| x + 1)`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs
index 80dd2f744b3..d93e5b114ec 100644
--- a/tests/ui/methods.rs
+++ b/tests/ui/methods.rs
@@ -122,16 +122,13 @@ impl Mul<T> for T {
 fn filter_next() {
     let v = vec![3, 2, 1, 0, -1, -2, -3];
 
-    // Single-line case.
-    let _ = v.iter().filter(|&x| *x < 0).next();
-
     // Multi-line case.
     let _ = v.iter().filter(|&x| {
                                 *x < 0
                             }
                    ).next();
 
-    // Check that hat we don't lint if the caller is not an `Iterator`.
+    // Check that we don't lint if the caller is not an `Iterator`.
     let foo = IteratorFalsePositives { foo: 0 };
     let _ = foo.filter().next();
 }
diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr
index 2a0a43e83a6..8a281c2dbd2 100644
--- a/tests/ui/methods.stderr
+++ b/tests/ui/methods.stderr
@@ -8,27 +8,20 @@ LL | |     }
    |
    = note: `-D clippy::new-ret-no-self` implied by `-D warnings`
 
-error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead.
+error: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead.
   --> $DIR/methods.rs:126:13
    |
-LL |     let _ = v.iter().filter(|&x| *x < 0).next();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `-D clippy::filter-next` implied by `-D warnings`
-   = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)`
-
-error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead.
-  --> $DIR/methods.rs:129:13
-   |
 LL |       let _ = v.iter().filter(|&x| {
    |  _____________^
 LL | |                                 *x < 0
 LL | |                             }
 LL | |                    ).next();
    | |___________________________^
+   |
+   = note: `-D clippy::filter-next` implied by `-D warnings`
 
 error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:146:22
+  --> $DIR/methods.rs:143:22
    |
 LL |     let _ = v.iter().find(|&x| *x < 0).is_some();
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| *x < 0)`
@@ -36,25 +29,25 @@ LL |     let _ = v.iter().find(|&x| *x < 0).is_some();
    = note: `-D clippy::search-is-some` implied by `-D warnings`
 
 error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:147:20
+  --> $DIR/methods.rs:144:20
    |
 LL |     let _ = (0..1).find(|x| **y == *x).is_some(); // one dereference less
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| **y == x)`
 
 error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:148:20
+  --> $DIR/methods.rs:145:20
    |
 LL |     let _ = (0..1).find(|x| *x == 0).is_some();
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| x == 0)`
 
 error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:149:22
+  --> $DIR/methods.rs:146:22
    |
 LL |     let _ = v.iter().find(|x| **x == 0).is_some();
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| *x == 0)`
 
 error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:152:13
+  --> $DIR/methods.rs:149:13
    |
 LL |       let _ = v.iter().find(|&x| {
    |  _____________^
@@ -64,13 +57,13 @@ LL | |                    ).is_some();
    | |______________________________^
 
 error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:158:22
+  --> $DIR/methods.rs:155:22
    |
 LL |     let _ = v.iter().position(|&x| x < 0).is_some();
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|&x| x < 0)`
 
 error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:161:13
+  --> $DIR/methods.rs:158:13
    |
 LL |       let _ = v.iter().position(|&x| {
    |  _____________^
@@ -80,13 +73,13 @@ LL | |                    ).is_some();
    | |______________________________^
 
 error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:167:22
+  --> $DIR/methods.rs:164:22
    |
 LL |     let _ = v.iter().rposition(|&x| x < 0).is_some();
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|&x| x < 0)`
 
 error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`.
-  --> $DIR/methods.rs:170:13
+  --> $DIR/methods.rs:167:13
    |
 LL |       let _ = v.iter().rposition(|&x| {
    |  _____________^
@@ -95,5 +88,5 @@ LL | |                                }
 LL | |                    ).is_some();
    | |______________________________^
 
-error: aborting due to 12 previous errors
+error: aborting due to 11 previous errors
 
diff --git a/tests/ui/methods_fixable.fixed b/tests/ui/methods_fixable.fixed
new file mode 100644
index 00000000000..ee7c1b0da6d
--- /dev/null
+++ b/tests/ui/methods_fixable.fixed
@@ -0,0 +1,11 @@
+// run-rustfix
+
+#![warn(clippy::filter_next)]
+
+/// Checks implementation of `FILTER_NEXT` lint.
+fn main() {
+    let v = vec![3, 2, 1, 0, -1, -2, -3];
+
+    // Single-line case.
+    let _ = v.iter().find(|&x| *x < 0);
+}
diff --git a/tests/ui/methods_fixable.rs b/tests/ui/methods_fixable.rs
new file mode 100644
index 00000000000..6d0f1b7bd51
--- /dev/null
+++ b/tests/ui/methods_fixable.rs
@@ -0,0 +1,11 @@
+// run-rustfix
+
+#![warn(clippy::filter_next)]
+
+/// Checks implementation of `FILTER_NEXT` lint.
+fn main() {
+    let v = vec![3, 2, 1, 0, -1, -2, -3];
+
+    // Single-line case.
+    let _ = v.iter().filter(|&x| *x < 0).next();
+}
diff --git a/tests/ui/methods_fixable.stderr b/tests/ui/methods_fixable.stderr
new file mode 100644
index 00000000000..70e7c3dea54
--- /dev/null
+++ b/tests/ui/methods_fixable.stderr
@@ -0,0 +1,10 @@
+error: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead.
+  --> $DIR/methods_fixable.rs:10:13
+   |
+LL |     let _ = v.iter().filter(|&x| *x < 0).next();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `v.iter().find(|&x| *x < 0)`
+   |
+   = note: `-D clippy::filter-next` implied by `-D warnings`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/option_map_or_none.stderr b/tests/ui/option_map_or_none.stderr
index 6f707987dbc..1cba29412b8 100644
--- a/tests/ui/option_map_or_none.stderr
+++ b/tests/ui/option_map_or_none.stderr
@@ -1,4 +1,4 @@
-error: called `map_or(None, f)` on an `Option` value. This can be done more directly by calling `and_then(f)` instead
+error: called `map_or(None, ..)` on an `Option` value. This can be done more directly by calling `and_then(..)` instead
   --> $DIR/option_map_or_none.rs:10:13
    |
 LL |     let _ = opt.map_or(None, |x| Some(x + 1));
@@ -6,7 +6,7 @@ LL |     let _ = opt.map_or(None, |x| Some(x + 1));
    |
    = note: `-D clippy::option-map-or-none` implied by `-D warnings`
 
-error: called `map_or(None, f)` on an `Option` value. This can be done more directly by calling `and_then(f)` instead
+error: called `map_or(None, ..)` on an `Option` value. This can be done more directly by calling `and_then(..)` instead
   --> $DIR/option_map_or_none.rs:13:13
    |
 LL |       let _ = opt.map_or(None, |x| {
diff --git a/tests/ui/skip_while_next.stderr b/tests/ui/skip_while_next.stderr
index a6b7bcd63ff..269cc13468b 100644
--- a/tests/ui/skip_while_next.stderr
+++ b/tests/ui/skip_while_next.stderr
@@ -1,13 +1,13 @@
-error: called `skip_while(p).next()` on an `Iterator`
+error: called `skip_while(<p>).next()` on an `Iterator`
   --> $DIR/skip_while_next.rs:14:13
    |
 LL |     let _ = v.iter().skip_while(|&x| *x < 0).next();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::skip-while-next` implied by `-D warnings`
-   = help: this is more succinctly expressed by calling `.find(!p)` instead
+   = help: this is more succinctly expressed by calling `.find(!<p>)` instead
 
-error: called `skip_while(p).next()` on an `Iterator`
+error: called `skip_while(<p>).next()` on an `Iterator`
   --> $DIR/skip_while_next.rs:17:13
    |
 LL |       let _ = v.iter().skip_while(|&x| {
@@ -17,7 +17,7 @@ LL | |                             }
 LL | |                    ).next();
    | |___________________________^
    |
-   = help: this is more succinctly expressed by calling `.find(!p)` instead
+   = help: this is more succinctly expressed by calling `.find(!<p>)` instead
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/temporary_assignment.rs b/tests/ui/temporary_assignment.rs
index b4a931043b0..ac4c1bc6597 100644
--- a/tests/ui/temporary_assignment.rs
+++ b/tests/ui/temporary_assignment.rs
@@ -1,5 +1,4 @@
 #![warn(clippy::temporary_assignment)]
-#![allow(const_item_mutation)]
 
 use std::ops::{Deref, DerefMut};
 
diff --git a/tests/ui/temporary_assignment.stderr b/tests/ui/temporary_assignment.stderr
index 4cc32c79f05..7d79901a28d 100644
--- a/tests/ui/temporary_assignment.stderr
+++ b/tests/ui/temporary_assignment.stderr
@@ -1,5 +1,5 @@
 error: assignment to temporary
-  --> $DIR/temporary_assignment.rs:48:5
+  --> $DIR/temporary_assignment.rs:47:5
    |
 LL |     Struct { field: 0 }.field = 1;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL |     Struct { field: 0 }.field = 1;
    = note: `-D clippy::temporary-assignment` implied by `-D warnings`
 
 error: assignment to temporary
-  --> $DIR/temporary_assignment.rs:49:5
+  --> $DIR/temporary_assignment.rs:48:5
    |
 LL | /     MultiStruct {
 LL | |         structure: Struct { field: 0 },
@@ -17,13 +17,13 @@ LL | |     .field = 1;
    | |______________^
 
 error: assignment to temporary
-  --> $DIR/temporary_assignment.rs:54:5
+  --> $DIR/temporary_assignment.rs:53:5
    |
 LL |     ArrayStruct { array: [0] }.array[0] = 1;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: assignment to temporary
-  --> $DIR/temporary_assignment.rs:55:5
+  --> $DIR/temporary_assignment.rs:54:5
    |
 LL |     (0, 0).0 = 1;
    |     ^^^^^^^^^^^^
diff --git a/tests/ui/toplevel_ref_arg.fixed b/tests/ui/toplevel_ref_arg.fixed
index 33605aca019..b129d95c560 100644
--- a/tests/ui/toplevel_ref_arg.fixed
+++ b/tests/ui/toplevel_ref_arg.fixed
@@ -1,7 +1,17 @@
 // run-rustfix
+// aux-build:macro_rules.rs
 
 #![warn(clippy::toplevel_ref_arg)]
 
+#[macro_use]
+extern crate macro_rules;
+
+macro_rules! gen_binding {
+    () => {
+        let _y = &42;
+    };
+}
+
 fn main() {
     // Closures should not warn
     let y = |ref x| println!("{:?}", x);
@@ -26,4 +36,15 @@ fn main() {
 
     // ok
     for ref _x in 0..10 {}
+
+    // lint in macro
+    #[allow(unused)]
+    {
+        gen_binding!();
+    }
+
+    // do not lint in external macro
+    {
+        ref_arg_binding!();
+    }
 }
diff --git a/tests/ui/toplevel_ref_arg.rs b/tests/ui/toplevel_ref_arg.rs
index 59759f11893..73eb4ff7306 100644
--- a/tests/ui/toplevel_ref_arg.rs
+++ b/tests/ui/toplevel_ref_arg.rs
@@ -1,7 +1,17 @@
 // run-rustfix
+// aux-build:macro_rules.rs
 
 #![warn(clippy::toplevel_ref_arg)]
 
+#[macro_use]
+extern crate macro_rules;
+
+macro_rules! gen_binding {
+    () => {
+        let ref _y = 42;
+    };
+}
+
 fn main() {
     // Closures should not warn
     let y = |ref x| println!("{:?}", x);
@@ -26,4 +36,15 @@ fn main() {
 
     // ok
     for ref _x in 0..10 {}
+
+    // lint in macro
+    #[allow(unused)]
+    {
+        gen_binding!();
+    }
+
+    // do not lint in external macro
+    {
+        ref_arg_binding!();
+    }
 }
diff --git a/tests/ui/toplevel_ref_arg.stderr b/tests/ui/toplevel_ref_arg.stderr
index 19d69496709..15cb933fedc 100644
--- a/tests/ui/toplevel_ref_arg.stderr
+++ b/tests/ui/toplevel_ref_arg.stderr
@@ -1,5 +1,5 @@
 error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead
-  --> $DIR/toplevel_ref_arg.rs:10:9
+  --> $DIR/toplevel_ref_arg.rs:20:9
    |
 LL |     let ref _x = 1;
    |     ----^^^^^^----- help: try: `let _x = &1;`
@@ -7,28 +7,39 @@ LL |     let ref _x = 1;
    = note: `-D clippy::toplevel-ref-arg` implied by `-D warnings`
 
 error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead
-  --> $DIR/toplevel_ref_arg.rs:12:9
+  --> $DIR/toplevel_ref_arg.rs:22:9
    |
 LL |     let ref _y: (&_, u8) = (&1, 2);
    |     ----^^^^^^--------------------- help: try: `let _y: &(&_, u8) = &(&1, 2);`
 
 error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead
-  --> $DIR/toplevel_ref_arg.rs:14:9
+  --> $DIR/toplevel_ref_arg.rs:24:9
    |
 LL |     let ref _z = 1 + 2;
    |     ----^^^^^^--------- help: try: `let _z = &(1 + 2);`
 
 error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead
-  --> $DIR/toplevel_ref_arg.rs:16:9
+  --> $DIR/toplevel_ref_arg.rs:26:9
    |
 LL |     let ref mut _z = 1 + 2;
    |     ----^^^^^^^^^^--------- help: try: `let _z = &mut (1 + 2);`
 
 error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead
-  --> $DIR/toplevel_ref_arg.rs:21:9
+  --> $DIR/toplevel_ref_arg.rs:31:9
    |
 LL |     let ref _x = vec![1, 2, 3];
    |     ----^^^^^^----------------- help: try: `let _x = &vec![1, 2, 3];`
 
-error: aborting due to 5 previous errors
+error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead
+  --> $DIR/toplevel_ref_arg.rs:11:13
+   |
+LL |         let ref _y = 42;
+   |         ----^^^^^^------ help: try: `let _y = &42;`
+...
+LL |         gen_binding!();
+   |         --------------- in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 6 previous errors
 
diff --git a/tests/ui/toplevel_ref_arg_non_rustfix.rs b/tests/ui/toplevel_ref_arg_non_rustfix.rs
index 42cac2ba4de..1a493fbce0e 100644
--- a/tests/ui/toplevel_ref_arg_non_rustfix.rs
+++ b/tests/ui/toplevel_ref_arg_non_rustfix.rs
@@ -1,11 +1,33 @@
+// aux-build:macro_rules.rs
+
 #![warn(clippy::toplevel_ref_arg)]
 #![allow(unused)]
 
+#[macro_use]
+extern crate macro_rules;
+
 fn the_answer(ref mut x: u8) {
     *x = 42;
 }
 
+macro_rules! gen_function {
+    () => {
+        fn fun_example(ref _x: usize) {}
+    };
+}
+
 fn main() {
     let mut x = 0;
     the_answer(x);
+
+    // lint in macro
+    #[allow(unused)]
+    {
+        gen_function!();
+    }
+
+    // do not lint in external macro
+    {
+        ref_arg_function!();
+    }
 }
diff --git a/tests/ui/toplevel_ref_arg_non_rustfix.stderr b/tests/ui/toplevel_ref_arg_non_rustfix.stderr
index 295e2f35608..6c36141a58c 100644
--- a/tests/ui/toplevel_ref_arg_non_rustfix.stderr
+++ b/tests/ui/toplevel_ref_arg_non_rustfix.stderr
@@ -1,10 +1,21 @@
 error: `ref` directly on a function argument is ignored. Consider using a reference type instead.
-  --> $DIR/toplevel_ref_arg_non_rustfix.rs:4:15
+  --> $DIR/toplevel_ref_arg_non_rustfix.rs:9:15
    |
 LL | fn the_answer(ref mut x: u8) {
    |               ^^^^^^^^^
    |
    = note: `-D clippy::toplevel-ref-arg` implied by `-D warnings`
 
-error: aborting due to previous error
+error: `ref` directly on a function argument is ignored. Consider using a reference type instead.
+  --> $DIR/toplevel_ref_arg_non_rustfix.rs:15:24
+   |
+LL |         fn fun_example(ref _x: usize) {}
+   |                        ^^^^^^
+...
+LL |         gen_function!();
+   |         ---------------- in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
 
diff --git a/util/dev b/util/dev
deleted file mode 100755
index 319de217e0d..00000000000
--- a/util/dev
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/sh
-CARGO_TARGET_DIR=$(pwd)/target/
-export CARGO_TARGET_DIR
-
-echo 'Deprecated! `util/dev` usage is deprecated, please use `cargo dev` instead.'
-
-cd clippy_dev && cargo run -- "$@"