about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--book/README.md2
-rw-r--r--book/src/development/infrastructure/changelog_update.md3
-rw-r--r--clippy_dev/src/update_lints.rs2
-rw-r--r--clippy_lints/src/await_holding_invalid.rs2
-rw-r--r--clippy_lints/src/casts/mod.rs2
-rw-r--r--clippy_lints/src/crate_in_macro_def.rs2
-rw-r--r--clippy_lints/src/dereference.rs44
-rw-r--r--clippy_lints/src/drop_forget_ref.rs4
-rw-r--r--clippy_lints/src/empty_drop.rs2
-rw-r--r--clippy_lints/src/entry.rs2
-rw-r--r--clippy_lints/src/inherent_impl.rs2
-rw-r--r--clippy_lints/src/invalid_utf8_in_unchecked.rs74
-rw-r--r--clippy_lints/src/lib.register_all.rs1
-rw-r--r--clippy_lints/src/lib.register_correctness.rs1
-rw-r--r--clippy_lints/src/lib.register_lints.rs1
-rw-r--r--clippy_lints/src/lib.rs2
-rw-r--r--clippy_lints/src/manual_non_exhaustive.rs2
-rw-r--r--clippy_lints/src/matches/manual_map.rs2
-rw-r--r--clippy_lints/src/matches/match_same_arms.rs4
-rw-r--r--clippy_lints/src/matches/mod.rs4
-rw-r--r--clippy_lints/src/methods/manual_str_repeat.rs2
-rw-r--r--clippy_lints/src/methods/mod.rs12
-rw-r--r--clippy_lints/src/methods/unnecessary_lazy_eval.rs7
-rw-r--r--clippy_lints/src/new_without_default.rs12
-rw-r--r--clippy_lints/src/option_if_let_else.rs2
-rw-r--r--clippy_lints/src/ptr.rs2
-rw-r--r--clippy_lints/src/shadow.rs14
-rw-r--r--clippy_lints/src/swap_ptr_to_ref.rs2
-rw-r--r--clippy_lints/src/undocumented_unsafe_blocks.rs18
-rw-r--r--clippy_lints/src/utils/internal_lints/metadata_collector.rs2
-rw-r--r--clippy_lints/src/write.rs2
-rw-r--r--clippy_utils/src/lib.rs2
-rw-r--r--clippy_utils/src/msrvs.rs1
-rw-r--r--clippy_utils/src/paths.rs1
-rw-r--r--clippy_utils/src/source.rs2
-rw-r--r--tests/ui/cast_size_32bit.stderr2
-rw-r--r--tests/ui/explicit_auto_deref.fixed4
-rw-r--r--tests/ui/explicit_auto_deref.rs4
-rw-r--r--tests/ui/explicit_auto_deref.stderr8
-rw-r--r--tests/ui/invalid_utf8_in_unchecked.rs20
-rw-r--r--tests/ui/invalid_utf8_in_unchecked.stderr22
-rw-r--r--tests/ui/new_without_default.rs14
-rw-r--r--tests/ui/shadow.stderr14
-rw-r--r--tests/ui/undocumented_unsafe_blocks.rs9
-rw-r--r--tests/ui/undocumented_unsafe_blocks.stderr62
-rw-r--r--tests/ui/unnecessary_lazy_eval.fixed2
-rw-r--r--tests/ui/unnecessary_lazy_eval.rs2
-rw-r--r--tests/ui/unnecessary_lazy_eval.stderr76
-rw-r--r--util/etc/vscode-tasks.json20
50 files changed, 357 insertions, 142 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 71e498c301b..1b792736a6a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3641,6 +3641,7 @@ Released 2018-09-13
 [`invalid_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_ref
 [`invalid_regex`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_regex
 [`invalid_upcast_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_upcast_comparisons
+[`invalid_utf8_in_unchecked`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_utf8_in_unchecked
 [`invisible_characters`]: https://rust-lang.github.io/rust-clippy/master/index.html#invisible_characters
 [`is_digit_ascii_radix`]: https://rust-lang.github.io/rust-clippy/master/index.html#is_digit_ascii_radix
 [`items_after_statements`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements
diff --git a/book/README.md b/book/README.md
index b652194d0d1..6d67f80ff25 100644
--- a/book/README.md
+++ b/book/README.md
@@ -1,4 +1,4 @@
 # Clippy Book
 
 This is the source for the Clippy Book. See the
-[book](src/infrastructure/book.md) for more information.
+[book](src/development/infrastructure/book.md) for more information.
diff --git a/book/src/development/infrastructure/changelog_update.md b/book/src/development/infrastructure/changelog_update.md
index e560f4c6a3e..80a47affe30 100644
--- a/book/src/development/infrastructure/changelog_update.md
+++ b/book/src/development/infrastructure/changelog_update.md
@@ -95,6 +95,9 @@ As section headers, we use:
 Please also be sure to update the Beta/Unreleased sections at the top with the
 relevant commit ranges.
 
+If you have the time, it would be appreciated if you double-check, that the
+`#[clippy::version]` attributes for the added lints contains the correct version.
+
 [changelog]: https://github.com/rust-lang/rust-clippy/blob/master/CHANGELOG.md
 [forge]: https://forge.rust-lang.org/
 [rust_master_tools]: https://github.com/rust-lang/rust/tree/master/src/tools/clippy
diff --git a/clippy_dev/src/update_lints.rs b/clippy_dev/src/update_lints.rs
index 2e0659f42d7..c089f4d8ce4 100644
--- a/clippy_dev/src/update_lints.rs
+++ b/clippy_dev/src/update_lints.rs
@@ -553,7 +553,7 @@ fn replace_ident_like(contents: &str, replacements: &[(&str, &str)]) -> Option<S
         pos = m.end();
     }
     result.push_str(&contents[pos..]);
-    edited.then(|| result)
+    edited.then_some(result)
 }
 
 fn round_to_fifty(count: usize) -> usize {
diff --git a/clippy_lints/src/await_holding_invalid.rs b/clippy_lints/src/await_holding_invalid.rs
index eee5f90d178..1761360fb28 100644
--- a/clippy_lints/src/await_holding_invalid.rs
+++ b/clippy_lints/src/await_holding_invalid.rs
@@ -161,7 +161,7 @@ declare_clippy_lint! {
     ///   baz().await; // Lint violation
     /// }
     /// ```
-    #[clippy::version = "1.49.0"]
+    #[clippy::version = "1.62.0"]
     pub AWAIT_HOLDING_INVALID_TYPE,
     suspicious,
     "holding a type across an await point which is not allowed to be held as per the configuration"
diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs
index 02c2f30a4dd..af3798a0cc8 100644
--- a/clippy_lints/src/casts/mod.rs
+++ b/clippy_lints/src/casts/mod.rs
@@ -500,7 +500,7 @@ declare_clippy_lint! {
     /// let x: i32 = -42;
     /// let y: u32 = x.unsigned_abs();
     /// ```
-    #[clippy::version = "1.61.0"]
+    #[clippy::version = "1.62.0"]
     pub CAST_ABS_TO_UNSIGNED,
     suspicious,
     "casting the result of `abs()` to an unsigned integer can panic"
diff --git a/clippy_lints/src/crate_in_macro_def.rs b/clippy_lints/src/crate_in_macro_def.rs
index 9b8a481b6ea..f6ec8fe7edc 100644
--- a/clippy_lints/src/crate_in_macro_def.rs
+++ b/clippy_lints/src/crate_in_macro_def.rs
@@ -43,7 +43,7 @@ declare_clippy_lint! {
     /// #[allow(clippy::crate_in_macro_def)]
     /// macro_rules! ok { ... crate::foo ... }
     /// ```
-    #[clippy::version = "1.61.0"]
+    #[clippy::version = "1.62.0"]
     pub CRATE_IN_MACRO_DEF,
     suspicious,
     "using `crate` in a macro definition"
diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs
index d6bd43a7494..6dddb969f33 100644
--- a/clippy_lints/src/dereference.rs
+++ b/clippy_lints/src/dereference.rs
@@ -8,7 +8,7 @@ use rustc_data_structures::fx::FxIndexMap;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_ty, Visitor};
 use rustc_hir::{
-    self as hir, BindingAnnotation, Body, BodyId, BorrowKind, Expr, ExprKind, GenericArg, HirId, ImplItem,
+    self as hir, BindingAnnotation, Body, BodyId, BorrowKind, Expr, ExprKind, FnRetTy, GenericArg, HirId, ImplItem,
     ImplItemKind, Item, ItemKind, Local, MatchSource, Mutability, Node, Pat, PatKind, Path, QPath, TraitItem,
     TraitItemKind, TyKind, UnOp,
 };
@@ -717,20 +717,36 @@ fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (Position, &
 
             Node::Expr(parent) if parent.span.ctxt() == ctxt => match parent.kind {
                 ExprKind::Ret(_) => {
-                    let output = cx
-                        .tcx
-                        .fn_sig(cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap()))
-                        .skip_binder()
-                        .output();
-                    Some(if !output.is_ref() {
-                        Position::Other(precedence)
-                    } else if output.has_placeholders() || output.has_opaque_types() {
-                        Position::ReborrowStable(precedence)
-                    } else {
-                        Position::DerefStable(precedence)
-                    })
+                    let owner_id = cx.tcx.hir().body_owner(cx.enclosing_body.unwrap());
+                    Some(
+                        if let Node::Expr(Expr {
+                            kind: ExprKind::Closure { fn_decl, .. },
+                            ..
+                        }) = cx.tcx.hir().get(owner_id)
+                        {
+                            match fn_decl.output {
+                                FnRetTy::Return(ty) => binding_ty_auto_deref_stability(ty, precedence),
+                                FnRetTy::DefaultReturn(_) => Position::Other(precedence),
+                            }
+                        } else {
+                            let output = cx
+                                .tcx
+                                .fn_sig(cx.tcx.hir().local_def_id(owner_id))
+                                .skip_binder()
+                                .output();
+                            if !output.is_ref() {
+                                Position::Other(precedence)
+                            } else if output.has_placeholders() || output.has_opaque_types() {
+                                Position::ReborrowStable(precedence)
+                            } else {
+                                Position::DerefStable(precedence)
+                            }
+                        },
+                    )
+                },
+                ExprKind::Call(func, _) if func.hir_id == child_id => {
+                    (child_id == e.hir_id).then_some(Position::Callee)
                 },
-                ExprKind::Call(func, _) if func.hir_id == child_id => (child_id == e.hir_id).then(|| Position::Callee),
                 ExprKind::Call(func, args) => args
                     .iter()
                     .position(|arg| arg.hir_id == child_id)
diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs
index 25014bfa1a5..b35f0b8ca52 100644
--- a/clippy_lints/src/drop_forget_ref.rs
+++ b/clippy_lints/src/drop_forget_ref.rs
@@ -116,7 +116,7 @@ declare_clippy_lint! {
     /// let x = Foo;
     /// std::mem::drop(x);
     /// ```
-    #[clippy::version = "1.61.0"]
+    #[clippy::version = "1.62.0"]
     pub DROP_NON_DROP,
     suspicious,
     "call to `std::mem::drop` with a value which does not implement `Drop`"
@@ -136,7 +136,7 @@ declare_clippy_lint! {
     /// let x = Foo;
     /// std::mem::forget(x);
     /// ```
-    #[clippy::version = "1.61.0"]
+    #[clippy::version = "1.62.0"]
     pub FORGET_NON_DROP,
     suspicious,
     "call to `std::mem::forget` with a value which does not implement `Drop`"
diff --git a/clippy_lints/src/empty_drop.rs b/clippy_lints/src/empty_drop.rs
index 325ae2356c1..ec063c0f777 100644
--- a/clippy_lints/src/empty_drop.rs
+++ b/clippy_lints/src/empty_drop.rs
@@ -26,7 +26,7 @@ declare_clippy_lint! {
     /// ```rust
     /// struct S;
     /// ```
-    #[clippy::version = "1.61.0"]
+    #[clippy::version = "1.62.0"]
     pub EMPTY_DROP,
     restriction,
     "empty `Drop` implementations"
diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs
index 27743a0ebec..4e3ae4c9614 100644
--- a/clippy_lints/src/entry.rs
+++ b/clippy_lints/src/entry.rs
@@ -650,7 +650,7 @@ fn find_insert_calls<'tcx>(
     let allow_insert_closure = s.allow_insert_closure;
     let is_single_insert = s.is_single_insert;
     let edits = s.edits;
-    s.can_use_entry.then(|| InsertSearchResults {
+    s.can_use_entry.then_some(InsertSearchResults {
         edits,
         allow_insert_closure,
         is_single_insert,
diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs
index 6a031a627df..c5abcc46254 100644
--- a/clippy_lints/src/inherent_impl.rs
+++ b/clippy_lints/src/inherent_impl.rs
@@ -127,7 +127,7 @@ fn get_impl_span(cx: &LateContext<'_>, id: LocalDefId) -> Option<Span> {
         (!span.from_expansion()
             && impl_item.generics.params.is_empty()
             && !is_lint_allowed(cx, MULTIPLE_INHERENT_IMPL, id))
-        .then(|| span)
+        .then_some(span)
     } else {
         None
     }
diff --git a/clippy_lints/src/invalid_utf8_in_unchecked.rs b/clippy_lints/src/invalid_utf8_in_unchecked.rs
new file mode 100644
index 00000000000..e0a607f9a95
--- /dev/null
+++ b/clippy_lints/src/invalid_utf8_in_unchecked.rs
@@ -0,0 +1,74 @@
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::{match_function_call, paths};
+use rustc_ast::{BorrowKind, LitKind};
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::source_map::Spanned;
+use rustc_span::Span;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for `std::str::from_utf8_unchecked` with an invalid UTF-8 literal
+    ///
+    /// ### Why is this bad?
+    /// Creating such a `str` would result in undefined behavior
+    ///
+    /// ### Example
+    /// ```rust
+    /// # #[allow(unused)]
+    /// unsafe {
+    ///     std::str::from_utf8_unchecked(b"cl\x82ippy");
+    /// }
+    /// ```
+    #[clippy::version = "1.64.0"]
+    pub INVALID_UTF8_IN_UNCHECKED,
+    correctness,
+    "using a non UTF-8 literal in `std::std::from_utf8_unchecked`"
+}
+declare_lint_pass!(InvalidUtf8InUnchecked => [INVALID_UTF8_IN_UNCHECKED]);
+
+impl<'tcx> LateLintPass<'tcx> for InvalidUtf8InUnchecked {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+        if let Some([arg]) = match_function_call(cx, expr, &paths::STR_FROM_UTF8_UNCHECKED) {
+            match &arg.kind {
+                ExprKind::Lit(Spanned { node: lit, .. }) => {
+                    if let LitKind::ByteStr(bytes) = &lit
+                        && std::str::from_utf8(bytes).is_err()
+                    {
+                        lint(cx, expr.span);
+                    }
+                },
+                ExprKind::AddrOf(BorrowKind::Ref, _, Expr { kind: ExprKind::Array(args), .. }) => {
+                    let elements = args.iter().map(|e|{
+                        match &e.kind {
+                            ExprKind::Lit(Spanned { node: lit, .. }) => match lit {
+                                LitKind::Byte(b) => Some(*b),
+                                #[allow(clippy::cast_possible_truncation)]
+                                LitKind::Int(b, _) => Some(*b as u8),
+                                _ => None
+                            }
+                            _ => None
+                        }
+                    }).collect::<Option<Vec<_>>>();
+
+                    if let Some(elements) = elements
+                        && std::str::from_utf8(&elements).is_err()
+                    {
+                        lint(cx, expr.span);
+                    }
+                }
+                _ => {}
+            }
+        }
+    }
+}
+
+fn lint(cx: &LateContext<'_>, span: Span) {
+    span_lint(
+        cx,
+        INVALID_UTF8_IN_UNCHECKED,
+        span,
+        "non UTF-8 literal in `std::str::from_utf8_unchecked`",
+    );
+}
diff --git a/clippy_lints/src/lib.register_all.rs b/clippy_lints/src/lib.register_all.rs
index 563ad891603..da26a3f0130 100644
--- a/clippy_lints/src/lib.register_all.rs
+++ b/clippy_lints/src/lib.register_all.rs
@@ -92,6 +92,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
     LintId::of(init_numbered_fields::INIT_NUMBERED_FIELDS),
     LintId::of(inline_fn_without_body::INLINE_FN_WITHOUT_BODY),
     LintId::of(int_plus_one::INT_PLUS_ONE),
+    LintId::of(invalid_utf8_in_unchecked::INVALID_UTF8_IN_UNCHECKED),
     LintId::of(large_const_arrays::LARGE_CONST_ARRAYS),
     LintId::of(large_enum_variant::LARGE_ENUM_VARIANT),
     LintId::of(len_zero::COMPARISON_TO_EMPTY),
diff --git a/clippy_lints/src/lib.register_correctness.rs b/clippy_lints/src/lib.register_correctness.rs
index 7d5e65cb27a..9975859c54f 100644
--- a/clippy_lints/src/lib.register_correctness.rs
+++ b/clippy_lints/src/lib.register_correctness.rs
@@ -29,6 +29,7 @@ store.register_group(true, "clippy::correctness", Some("clippy_correctness"), ve
     LintId::of(infinite_iter::INFINITE_ITER),
     LintId::of(inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY),
     LintId::of(inline_fn_without_body::INLINE_FN_WITHOUT_BODY),
+    LintId::of(invalid_utf8_in_unchecked::INVALID_UTF8_IN_UNCHECKED),
     LintId::of(let_underscore::LET_UNDERSCORE_LOCK),
     LintId::of(literal_representation::MISTYPED_LITERAL_SUFFIXES),
     LintId::of(loops::ITER_NEXT_LOOP),
diff --git a/clippy_lints/src/lib.register_lints.rs b/clippy_lints/src/lib.register_lints.rs
index d3c75f8b519..ceb8470657f 100644
--- a/clippy_lints/src/lib.register_lints.rs
+++ b/clippy_lints/src/lib.register_lints.rs
@@ -196,6 +196,7 @@ store.register_lints(&[
     inline_fn_without_body::INLINE_FN_WITHOUT_BODY,
     int_plus_one::INT_PLUS_ONE,
     invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS,
+    invalid_utf8_in_unchecked::INVALID_UTF8_IN_UNCHECKED,
     items_after_statements::ITEMS_AFTER_STATEMENTS,
     iter_not_returning_iterator::ITER_NOT_RETURNING_ITERATOR,
     large_const_arrays::LARGE_CONST_ARRAYS,
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 172fdf8c852..1604d1078ee 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -255,6 +255,7 @@ mod init_numbered_fields;
 mod inline_fn_without_body;
 mod int_plus_one;
 mod invalid_upcast_comparisons;
+mod invalid_utf8_in_unchecked;
 mod items_after_statements;
 mod iter_not_returning_iterator;
 mod large_const_arrays;
@@ -913,6 +914,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(move || Box::new(manual_retain::ManualRetain::new(msrv)));
     let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold;
     store.register_late_pass(move || Box::new(operators::Operators::new(verbose_bit_mask_threshold)));
+    store.register_late_pass(|| Box::new(invalid_utf8_in_unchecked::InvalidUtf8InUnchecked));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
 
diff --git a/clippy_lints/src/manual_non_exhaustive.rs b/clippy_lints/src/manual_non_exhaustive.rs
index 4278e98dc91..2b04475c7a9 100644
--- a/clippy_lints/src/manual_non_exhaustive.rs
+++ b/clippy_lints/src/manual_non_exhaustive.rs
@@ -161,7 +161,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum {
                 (matches!(v.data, hir::VariantData::Unit(_))
                     && v.ident.as_str().starts_with('_')
                     && is_doc_hidden(cx.tcx.hir().attrs(v.id)))
-                .then(|| (id, v.span))
+                .then_some((id, v.span))
             });
             if let Some((id, span)) = iter.next()
                 && iter.next().is_none()
diff --git a/clippy_lints/src/matches/manual_map.rs b/clippy_lints/src/matches/manual_map.rs
index 542905a2d76..8f98b43b9e5 100644
--- a/clippy_lints/src/matches/manual_map.rs
+++ b/clippy_lints/src/matches/manual_map.rs
@@ -105,7 +105,7 @@ fn check<'tcx>(
 
     // Determine which binding mode to use.
     let explicit_ref = some_pat.contains_explicit_ref_binding();
-    let binding_ref = explicit_ref.or_else(|| (ty_ref_count != pat_ref_count).then(|| ty_mutability));
+    let binding_ref = explicit_ref.or_else(|| (ty_ref_count != pat_ref_count).then_some(ty_mutability));
 
     let as_ref_str = match binding_ref {
         Some(Mutability::Mut) => ".as_mut()",
diff --git a/clippy_lints/src/matches/match_same_arms.rs b/clippy_lints/src/matches/match_same_arms.rs
index 15513de7d86..61d28b15066 100644
--- a/clippy_lints/src/matches/match_same_arms.rs
+++ b/clippy_lints/src/matches/match_same_arms.rs
@@ -38,7 +38,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
             normalized_pats[i + 1..]
                 .iter()
                 .enumerate()
-                .find_map(|(j, other)| pat.has_overlapping_values(other).then(|| i + 1 + j))
+                .find_map(|(j, other)| pat.has_overlapping_values(other).then_some(i + 1 + j))
                 .unwrap_or(normalized_pats.len())
         })
         .collect();
@@ -55,7 +55,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
                 .zip(forwards_blocking_idxs[..i].iter().copied().rev())
                 .skip_while(|&(_, forward_block)| forward_block > i)
                 .find_map(|((j, other), forward_block)| {
-                    (forward_block == i || pat.has_overlapping_values(other)).then(|| j)
+                    (forward_block == i || pat.has_overlapping_values(other)).then_some(j)
                 })
                 .unwrap_or(0)
         })
diff --git a/clippy_lints/src/matches/mod.rs b/clippy_lints/src/matches/mod.rs
index b2a873ef582..5c996bc33f3 100644
--- a/clippy_lints/src/matches/mod.rs
+++ b/clippy_lints/src/matches/mod.rs
@@ -1061,7 +1061,7 @@ fn contains_cfg_arm(cx: &LateContext<'_>, e: &Expr<'_>, scrutinee: &Expr<'_>, ar
     let start = scrutinee_span.hi();
     let mut arm_spans = arms.iter().map(|arm| {
         let data = arm.span.data();
-        (data.ctxt == SyntaxContext::root()).then(|| (data.lo, data.hi))
+        (data.ctxt == SyntaxContext::root()).then_some((data.lo, data.hi))
     });
     let end = e.span.hi();
 
@@ -1095,7 +1095,7 @@ fn contains_cfg_arm(cx: &LateContext<'_>, e: &Expr<'_>, scrutinee: &Expr<'_>, ar
             parent: None,
         }
         .span();
-        (!span_contains_cfg(cx, span)).then(|| next_start).ok_or(())
+        (!span_contains_cfg(cx, span)).then_some(next_start).ok_or(())
     });
     match found {
         Ok(start) => {
diff --git a/clippy_lints/src/methods/manual_str_repeat.rs b/clippy_lints/src/methods/manual_str_repeat.rs
index 68a75667914..46d2fc493f8 100644
--- a/clippy_lints/src/methods/manual_str_repeat.rs
+++ b/clippy_lints/src/methods/manual_str_repeat.rs
@@ -43,7 +43,7 @@ fn parse_repeat_arg(cx: &LateContext<'_>, e: &Expr<'_>) -> Option<RepeatKind> {
             Some(RepeatKind::String)
         } else {
             let ty = ty.peel_refs();
-            (ty.is_str() || is_type_diagnostic_item(cx, ty, sym::String)).then(|| RepeatKind::String)
+            (ty.is_str() || is_type_diagnostic_item(cx, ty, sym::String)).then_some(RepeatKind::String)
         }
     }
 }
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index cc1530f0ed0..29ec6e04286 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -369,7 +369,7 @@ declare_clippy_lint! {
     /// let x: Result<u32, &str> = Ok(10);
     /// x.expect_err("Testing expect_err");
     /// ```
-    #[clippy::version = "1.61.0"]
+    #[clippy::version = "1.62.0"]
     pub ERR_EXPECT,
     style,
     r#"using `.err().expect("")` when `.expect_err("")` can be used"#
@@ -2215,7 +2215,7 @@ declare_clippy_lint! {
     /// c.is_ascii_digit();
     /// c.is_ascii_hexdigit();
     /// ```
-    #[clippy::version = "1.61.0"]
+    #[clippy::version = "1.62.0"]
     pub IS_DIGIT_ASCII_RADIX,
     style,
     "use of `char::is_digit(..)` with literal radix of 10 or 16"
@@ -2235,7 +2235,7 @@ declare_clippy_lint! {
     /// let x = Some(3);
     /// x.as_ref();
     /// ```
-    #[clippy::version = "1.61.0"]
+    #[clippy::version = "1.62.0"]
     pub NEEDLESS_OPTION_TAKE,
     complexity,
     "using `.as_ref().take()` on a temporary value"
@@ -2737,6 +2737,12 @@ impl Methods {
                     }
                 },
                 ("take", []) => needless_option_take::check(cx, expr, recv),
+                ("then", [arg]) => {
+                    if !meets_msrv(self.msrv, msrvs::BOOL_THEN_SOME) {
+                        return;
+                    }
+                    unnecessary_lazy_eval::check(cx, expr, recv, arg, "then_some");
+                },
                 ("to_os_string" | "to_owned" | "to_path_buf" | "to_vec", []) => {
                     implicit_clone::check(cx, name, expr, recv);
                 },
diff --git a/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/clippy_lints/src/methods/unnecessary_lazy_eval.rs
index 865f6d0318e..a9c641b4606 100644
--- a/clippy_lints/src/methods/unnecessary_lazy_eval.rs
+++ b/clippy_lints/src/methods/unnecessary_lazy_eval.rs
@@ -20,8 +20,9 @@ pub(super) fn check<'tcx>(
 ) {
     let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option);
     let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result);
+    let is_bool = cx.typeck_results().expr_ty(recv).is_bool();
 
-    if is_option || is_result {
+    if is_option || is_result || is_bool {
         if let hir::ExprKind::Closure { body, .. } = arg.kind {
             let body = cx.tcx.hir().body(body);
             let body_expr = &body.value;
@@ -33,8 +34,10 @@ pub(super) fn check<'tcx>(
             if eager_or_lazy::switch_to_eager_eval(cx, body_expr) {
                 let msg = if is_option {
                     "unnecessary closure used to substitute value for `Option::None`"
-                } else {
+                } else if is_result {
                     "unnecessary closure used to substitute value for `Result::Err`"
+                } else {
+                    "unnecessary closure used with `bool::then`"
                 };
                 let applicability = if body
                     .params
diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs
index 093ec389335..5c45ee6d94a 100644
--- a/clippy_lints/src/new_without_default.rs
+++ b/clippy_lints/src/new_without_default.rs
@@ -88,15 +88,9 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
                             // shouldn't be implemented when it is hidden in docs
                             return;
                         }
-                        if impl_item
-                            .generics
-                            .params
-                            .iter()
-                            .any(|gen| matches!(gen.kind, hir::GenericParamKind::Type { .. }))
-                        {
-                            // when the result of `new()` depends on a type parameter we should not require
-                            // an
-                            // impl of `Default`
+                        if !impl_item.generics.params.is_empty() {
+                            // when the result of `new()` depends on a parameter we should not require
+                            // an impl of `Default`
                             return;
                         }
                         if_chain! {
diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs
index ea5a8f0858b..44f153cffac 100644
--- a/clippy_lints/src/option_if_let_else.rs
+++ b/clippy_lints/src/option_if_let_else.rs
@@ -146,7 +146,7 @@ fn detect_option_if_let_else<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) ->
                 });
                 if let ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(local_id), .. })) = e.kind {
                     match some_captures.get(local_id)
-                        .or_else(|| (method_sugg == "map_or_else").then(|| ()).and_then(|_| none_captures.get(local_id)))
+                        .or_else(|| (method_sugg == "map_or_else").then_some(()).and_then(|_| none_captures.get(local_id)))
                     {
                         Some(CaptureKind::Value | CaptureKind::Ref(Mutability::Mut)) => return None,
                         Some(CaptureKind::Ref(Mutability::Not)) if as_mut => return None,
diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs
index 25b73918c0a..8bacc6f6b32 100644
--- a/clippy_lints/src/ptr.rs
+++ b/clippy_lints/src/ptr.rs
@@ -501,7 +501,7 @@ fn check_mut_from_ref<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Optio
             .iter()
             .filter_map(get_rptr_lm)
             .filter(|&(lt, _, _)| lt.name == out.name)
-            .map(|(_, mutability, span)| (mutability == Mutability::Not).then(|| span))
+            .map(|(_, mutability, span)| (mutability == Mutability::Not).then_some(span))
             .collect();
         if let Some(args) = args
             && !args.is_empty()
diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs
index bf318c055da..5dcdab5b8ab 100644
--- a/clippy_lints/src/shadow.rs
+++ b/clippy_lints/src/shadow.rs
@@ -99,7 +99,7 @@ declare_clippy_lint! {
 
 #[derive(Default)]
 pub(crate) struct Shadow {
-    bindings: Vec<FxHashMap<Symbol, Vec<ItemLocalId>>>,
+    bindings: Vec<(FxHashMap<Symbol, Vec<ItemLocalId>>, LocalDefId)>,
 }
 
 impl_lint_pass!(Shadow => [SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED]);
@@ -121,7 +121,7 @@ impl<'tcx> LateLintPass<'tcx> for Shadow {
 
         let HirId { owner, local_id } = id;
         // get (or insert) the list of items for this owner and symbol
-        let data = self.bindings.last_mut().unwrap();
+        let (ref mut data, scope_owner) = *self.bindings.last_mut().unwrap();
         let items_with_name = data.entry(ident.name).or_default();
 
         // check other bindings with the same name, most recently seen first
@@ -131,7 +131,7 @@ impl<'tcx> LateLintPass<'tcx> for Shadow {
                 return;
             }
 
-            if is_shadow(cx, owner, prev, local_id) {
+            if is_shadow(cx, scope_owner, prev, local_id) {
                 let prev_hir_id = HirId { owner, local_id: prev };
                 lint_shadow(cx, pat, prev_hir_id, ident.span);
                 // only lint against the "nearest" shadowed binding
@@ -144,11 +144,9 @@ impl<'tcx> LateLintPass<'tcx> for Shadow {
 
     fn check_body(&mut self, cx: &LateContext<'_>, body: &Body<'_>) {
         let hir = cx.tcx.hir();
-        if !matches!(
-            hir.body_owner_kind(hir.body_owner_def_id(body.id())),
-            BodyOwnerKind::Closure
-        ) {
-            self.bindings.push(FxHashMap::default());
+        let owner_id = hir.body_owner_def_id(body.id());
+        if !matches!(hir.body_owner_kind(owner_id), BodyOwnerKind::Closure) {
+            self.bindings.push((FxHashMap::default(), owner_id));
         }
     }
 
diff --git a/clippy_lints/src/swap_ptr_to_ref.rs b/clippy_lints/src/swap_ptr_to_ref.rs
index 75d3b040c96..3cbbda80f3a 100644
--- a/clippy_lints/src/swap_ptr_to_ref.rs
+++ b/clippy_lints/src/swap_ptr_to_ref.rs
@@ -73,7 +73,7 @@ fn is_ptr_to_ref(cx: &LateContext<'_>, e: &Expr<'_>, ctxt: SyntaxContext) -> (bo
         && let ExprKind::Unary(UnOp::Deref, derefed_expr) = borrowed_expr.kind
         && cx.typeck_results().expr_ty(derefed_expr).is_unsafe_ptr()
     {
-        (true, (borrowed_expr.span.ctxt() == ctxt || derefed_expr.span.ctxt() == ctxt).then(|| derefed_expr.span))
+        (true, (borrowed_expr.span.ctxt() == ctxt || derefed_expr.span.ctxt() == ctxt).then_some(derefed_expr.span))
     } else {
         (false, None)
     }
diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs
index 025dd57e83a..04f16fd2161 100644
--- a/clippy_lints/src/undocumented_unsafe_blocks.rs
+++ b/clippy_lints/src/undocumented_unsafe_blocks.rs
@@ -265,14 +265,28 @@ fn span_from_macro_expansion_has_safety_comment(cx: &LateContext<'_>, span: Span
     }
 }
 
+fn get_body_search_span(cx: &LateContext<'_>) -> Option<Span> {
+    let body = cx.enclosing_body?;
+    let map = cx.tcx.hir();
+    let mut span = map.body(body).value.span;
+    for (_, node) in map.parent_iter(body.hir_id) {
+        match node {
+            Node::Expr(e) => span = e.span,
+            Node::Block(_) | Node::Arm(_) | Node::Stmt(_) | Node::Local(_) => (),
+            _ => break,
+        }
+    }
+    Some(span)
+}
+
 fn span_in_body_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool {
     let source_map = cx.sess().source_map();
     let ctxt = span.ctxt();
     if ctxt == SyntaxContext::root()
-        && let Some(body) = cx.enclosing_body
+        && let Some(search_span) = get_body_search_span(cx)
     {
         if let Ok(unsafe_line) = source_map.lookup_line(span.lo())
-            && let Some(body_span) = walk_span_to_context(cx.tcx.hir().body(body).value.span, SyntaxContext::root())
+            && let Some(body_span) = walk_span_to_context(search_span, SyntaxContext::root())
             && let Ok(body_line) = source_map.lookup_line(body_span.lo())
             && Lrc::ptr_eq(&unsafe_line.sf, &body_line.sf)
             && let Some(src) = unsafe_line.sf.src.as_deref()
diff --git a/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/clippy_lints/src/utils/internal_lints/metadata_collector.rs
index 6518e0a6ea0..3010fc0223c 100644
--- a/clippy_lints/src/utils/internal_lints/metadata_collector.rs
+++ b/clippy_lints/src/utils/internal_lints/metadata_collector.rs
@@ -843,7 +843,7 @@ fn get_lint_group(cx: &LateContext<'_>, lint_id: LintId) -> Option<String> {
 fn get_lint_level_from_group(lint_group: &str) -> Option<&'static str> {
     DEFAULT_LINT_LEVELS
         .iter()
-        .find_map(|(group_name, group_level)| (*group_name == lint_group).then(|| *group_level))
+        .find_map(|(group_name, group_level)| (*group_name == lint_group).then_some(*group_level))
 }
 
 pub(super) fn is_deprecated_lint(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs
index 67b2bc8c3f3..08b88947520 100644
--- a/clippy_lints/src/write.rs
+++ b/clippy_lints/src/write.rs
@@ -515,7 +515,7 @@ impl Write {
             args.push(arg, span);
         }
 
-        parser.errors.is_empty().then(move || args)
+        parser.errors.is_empty().then_some(args)
     }
 
     /// Checks the arguments of `print[ln]!` and `write[ln]!` calls. It will return a tuple of two
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index 9fa28e137f9..0e739303683 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -1016,7 +1016,7 @@ pub fn can_move_expr_to_closure<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'
         captures: HirIdMap::default(),
     };
     v.visit_expr(expr);
-    v.allow_closure.then(|| v.captures)
+    v.allow_closure.then_some(v.captures)
 }
 
 /// Returns the method names and argument list of nested method call expressions that make up
diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs
index b09c929f76e..9e238c6f1ac 100644
--- a/clippy_utils/src/msrvs.rs
+++ b/clippy_utils/src/msrvs.rs
@@ -12,6 +12,7 @@ macro_rules! msrv_aliases {
 
 // names may refer to stabilized feature flags or library items
 msrv_aliases! {
+    1,62,0 { BOOL_THEN_SOME }
     1,53,0 { OR_PATTERNS, MANUAL_BITS, BTREE_MAP_RETAIN, BTREE_SET_RETAIN }
     1,52,0 { STR_SPLIT_ONCE, REM_EUCLID_CONST }
     1,51,0 { BORROW_AS_PTR, UNSIGNED_ABS }
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index 6542e77113b..05429d05d9e 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -163,6 +163,7 @@ pub const STR_BYTES: [&str; 4] = ["core", "str", "<impl str>", "bytes"];
 pub const STR_CHARS: [&str; 4] = ["core", "str", "<impl str>", "chars"];
 pub const STR_ENDS_WITH: [&str; 4] = ["core", "str", "<impl str>", "ends_with"];
 pub const STR_FROM_UTF8: [&str; 4] = ["core", "str", "converts", "from_utf8"];
+pub const STR_FROM_UTF8_UNCHECKED: [&str; 4] = ["core", "str", "converts", "from_utf8_unchecked"];
 pub const STR_LEN: [&str; 4] = ["core", "str", "<impl str>", "len"];
 pub const STR_STARTS_WITH: [&str; 4] = ["core", "str", "<impl str>", "starts_with"];
 #[cfg(feature = "internal")]
diff --git a/clippy_utils/src/source.rs b/clippy_utils/src/source.rs
index f88a92fb11c..1197fe914de 100644
--- a/clippy_utils/src/source.rs
+++ b/clippy_utils/src/source.rs
@@ -353,7 +353,7 @@ pub fn snippet_with_context<'a>(
 /// span containing `m!(0)`.
 pub fn walk_span_to_context(span: Span, outer: SyntaxContext) -> Option<Span> {
     let outer_span = hygiene::walk_chain(span, outer);
-    (outer_span.ctxt() == outer).then(|| outer_span)
+    (outer_span.ctxt() == outer).then_some(outer_span)
 }
 
 /// Removes block comments from the given `Vec` of lines.
diff --git a/tests/ui/cast_size_32bit.stderr b/tests/ui/cast_size_32bit.stderr
index 7125f741c15..8990c3ba739 100644
--- a/tests/ui/cast_size_32bit.stderr
+++ b/tests/ui/cast_size_32bit.stderr
@@ -114,5 +114,5 @@ LL |     3_999_999_999usize as f64;
    |
    = note: `-D clippy::unnecessary-cast` implied by `-D warnings`
 
-error: aborting due to 20 previous errors
+error: aborting due to 18 previous errors
 
diff --git a/tests/ui/explicit_auto_deref.fixed b/tests/ui/explicit_auto_deref.fixed
index d4ff1b1566d..a650fdc1f89 100644
--- a/tests/ui/explicit_auto_deref.fixed
+++ b/tests/ui/explicit_auto_deref.fixed
@@ -211,4 +211,8 @@ fn main() {
     unsafe {
         var(0, &**x);
     }
+
+    let s = &"str";
+    let _ = || return *s;
+    let _ = || -> &'static str { return s };
 }
diff --git a/tests/ui/explicit_auto_deref.rs b/tests/ui/explicit_auto_deref.rs
index 99294a7947b..8f4f352576a 100644
--- a/tests/ui/explicit_auto_deref.rs
+++ b/tests/ui/explicit_auto_deref.rs
@@ -211,4 +211,8 @@ fn main() {
     unsafe {
         var(0, &**x);
     }
+
+    let s = &"str";
+    let _ = || return *s;
+    let _ = || -> &'static str { return *s };
 }
diff --git a/tests/ui/explicit_auto_deref.stderr b/tests/ui/explicit_auto_deref.stderr
index 55f956e37ae..92765307ea7 100644
--- a/tests/ui/explicit_auto_deref.stderr
+++ b/tests/ui/explicit_auto_deref.stderr
@@ -192,5 +192,11 @@ error: deref which would be done by auto-deref
 LL |     f_str(&&**ref_str); // `needless_borrow` will suggest removing only one reference
    |            ^^^^^^^^^^ help: try this: `ref_str`
 
-error: aborting due to 32 previous errors
+error: deref which would be done by auto-deref
+  --> $DIR/explicit_auto_deref.rs:217:41
+   |
+LL |     let _ = || -> &'static str { return *s };
+   |                                         ^^ help: try this: `s`
+
+error: aborting due to 33 previous errors
 
diff --git a/tests/ui/invalid_utf8_in_unchecked.rs b/tests/ui/invalid_utf8_in_unchecked.rs
new file mode 100644
index 00000000000..3dc096d3197
--- /dev/null
+++ b/tests/ui/invalid_utf8_in_unchecked.rs
@@ -0,0 +1,20 @@
+#![warn(clippy::invalid_utf8_in_unchecked)]
+
+fn main() {
+    // Valid
+    unsafe {
+        std::str::from_utf8_unchecked(&[99, 108, 105, 112, 112, 121]);
+        std::str::from_utf8_unchecked(&[b'c', b'l', b'i', b'p', b'p', b'y']);
+        std::str::from_utf8_unchecked(b"clippy");
+
+        let x = 0xA0;
+        std::str::from_utf8_unchecked(&[0xC0, x]);
+    }
+
+    // Invalid
+    unsafe {
+        std::str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]);
+        std::str::from_utf8_unchecked(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
+        std::str::from_utf8_unchecked(b"cl\x82ippy");
+    }
+}
diff --git a/tests/ui/invalid_utf8_in_unchecked.stderr b/tests/ui/invalid_utf8_in_unchecked.stderr
new file mode 100644
index 00000000000..c89cd2758ee
--- /dev/null
+++ b/tests/ui/invalid_utf8_in_unchecked.stderr
@@ -0,0 +1,22 @@
+error: non UTF-8 literal in `std::str::from_utf8_unchecked`
+  --> $DIR/invalid_utf8_in_unchecked.rs:16:9
+   |
+LL |         std::str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::invalid-utf8-in-unchecked` implied by `-D warnings`
+
+error: non UTF-8 literal in `std::str::from_utf8_unchecked`
+  --> $DIR/invalid_utf8_in_unchecked.rs:17:9
+   |
+LL |         std::str::from_utf8_unchecked(&[b'c', b'l', b'/x82', b'i', b'p', b'p', b'y']);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: non UTF-8 literal in `std::str::from_utf8_unchecked`
+  --> $DIR/invalid_utf8_in_unchecked.rs:18:9
+   |
+LL |         std::str::from_utf8_unchecked(b"cl/x82ippy");
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/new_without_default.rs b/tests/ui/new_without_default.rs
index 538927b1805..65809023f8d 100644
--- a/tests/ui/new_without_default.rs
+++ b/tests/ui/new_without_default.rs
@@ -212,3 +212,17 @@ impl DocHidden {
 }
 
 fn main() {}
+
+pub struct IgnoreConstGenericNew(usize);
+impl IgnoreConstGenericNew {
+    pub fn new<const N: usize>() -> Self {
+        Self(N)
+    }
+}
+
+pub struct IgnoreLifetimeNew;
+impl IgnoreLifetimeNew {
+    pub fn new<'a>() -> Self {
+        Self
+    }
+}
diff --git a/tests/ui/shadow.stderr b/tests/ui/shadow.stderr
index 3bd41d06260..43d76094d0e 100644
--- a/tests/ui/shadow.stderr
+++ b/tests/ui/shadow.stderr
@@ -265,5 +265,17 @@ note: previous binding is here
 LL | pub async fn foo2(_a: i32, _b: i64) {
    |                            ^^
 
-error: aborting due to 22 previous errors
+error: `x` shadows a previous, unrelated binding
+  --> $DIR/shadow.rs:94:21
+   |
+LL |         if let Some(x) = Some(1) { x } else { 1 }
+   |                     ^
+   |
+note: previous binding is here
+  --> $DIR/shadow.rs:93:13
+   |
+LL |         let x = 1;
+   |             ^
+
+error: aborting due to 23 previous errors
 
diff --git a/tests/ui/undocumented_unsafe_blocks.rs b/tests/ui/undocumented_unsafe_blocks.rs
index 33b6a82f9d2..08aee433215 100644
--- a/tests/ui/undocumented_unsafe_blocks.rs
+++ b/tests/ui/undocumented_unsafe_blocks.rs
@@ -250,6 +250,11 @@ fn from_proc_macro() {
     proc_macro_unsafe::unsafe_block!(token);
 }
 
+fn in_closure(x: *const u32) {
+    // Safety: reason
+    let _ = || unsafe { *x };
+}
+
 // Invalid comments
 
 #[rustfmt::skip]
@@ -351,9 +356,9 @@ mod unsafe_impl_smoke_test {
 
     #[rustfmt::skip]
     mod sub_mod2 {
-        // 
+        //
         // SAFETY: ok
-        // 
+        //
 
         unsafe impl B for (u32) {}
         unsafe trait B {}
diff --git a/tests/ui/undocumented_unsafe_blocks.stderr b/tests/ui/undocumented_unsafe_blocks.stderr
index b79949e9d06..c6a2127443b 100644
--- a/tests/ui/undocumented_unsafe_blocks.stderr
+++ b/tests/ui/undocumented_unsafe_blocks.stderr
@@ -1,5 +1,5 @@
 error: unsafe block missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:257:19
+  --> $DIR/undocumented_unsafe_blocks.rs:262:19
    |
 LL |     /* Safety: */ unsafe {}
    |                   ^^^^^^^^^
@@ -8,7 +8,7 @@ LL |     /* Safety: */ unsafe {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:261:5
+  --> $DIR/undocumented_unsafe_blocks.rs:266:5
    |
 LL |     unsafe {}
    |     ^^^^^^^^^
@@ -16,7 +16,7 @@ LL |     unsafe {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:265:14
+  --> $DIR/undocumented_unsafe_blocks.rs:270:14
    |
 LL |     let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
    |              ^^^^^^^^^^^^^
@@ -24,7 +24,7 @@ LL |     let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:265:29
+  --> $DIR/undocumented_unsafe_blocks.rs:270:29
    |
 LL |     let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
    |                             ^^^^^^^^^^^^^
@@ -32,7 +32,7 @@ LL |     let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:265:48
+  --> $DIR/undocumented_unsafe_blocks.rs:270:48
    |
 LL |     let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
    |                                                ^^^^^^^^^^^^^
@@ -40,7 +40,7 @@ LL |     let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:269:18
+  --> $DIR/undocumented_unsafe_blocks.rs:274:18
    |
 LL |     let _ = (42, unsafe {}, "test", unsafe {});
    |                  ^^^^^^^^^
@@ -48,7 +48,7 @@ LL |     let _ = (42, unsafe {}, "test", unsafe {});
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:269:37
+  --> $DIR/undocumented_unsafe_blocks.rs:274:37
    |
 LL |     let _ = (42, unsafe {}, "test", unsafe {});
    |                                     ^^^^^^^^^
@@ -56,7 +56,7 @@ LL |     let _ = (42, unsafe {}, "test", unsafe {});
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:273:14
+  --> $DIR/undocumented_unsafe_blocks.rs:278:14
    |
 LL |     let _ = *unsafe { &42 };
    |              ^^^^^^^^^^^^^^
@@ -64,7 +64,7 @@ LL |     let _ = *unsafe { &42 };
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:278:19
+  --> $DIR/undocumented_unsafe_blocks.rs:283:19
    |
 LL |     let _ = match unsafe {} {
    |                   ^^^^^^^^^
@@ -72,7 +72,7 @@ LL |     let _ = match unsafe {} {
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:284:14
+  --> $DIR/undocumented_unsafe_blocks.rs:289:14
    |
 LL |     let _ = &unsafe {};
    |              ^^^^^^^^^
@@ -80,7 +80,7 @@ LL |     let _ = &unsafe {};
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:288:14
+  --> $DIR/undocumented_unsafe_blocks.rs:293:14
    |
 LL |     let _ = [unsafe {}; 5];
    |              ^^^^^^^^^
@@ -88,7 +88,7 @@ LL |     let _ = [unsafe {}; 5];
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:292:13
+  --> $DIR/undocumented_unsafe_blocks.rs:297:13
    |
 LL |     let _ = unsafe {};
    |             ^^^^^^^^^
@@ -96,7 +96,7 @@ LL |     let _ = unsafe {};
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:302:8
+  --> $DIR/undocumented_unsafe_blocks.rs:307:8
    |
 LL |     t!(unsafe {});
    |        ^^^^^^^^^
@@ -104,7 +104,7 @@ LL |     t!(unsafe {});
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:308:13
+  --> $DIR/undocumented_unsafe_blocks.rs:313:13
    |
 LL |             unsafe {}
    |             ^^^^^^^^^
@@ -116,7 +116,7 @@ LL |     t!();
    = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: unsafe block missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:316:5
+  --> $DIR/undocumented_unsafe_blocks.rs:321:5
    |
 LL |     unsafe {} // SAFETY:
    |     ^^^^^^^^^
@@ -124,7 +124,7 @@ LL |     unsafe {} // SAFETY:
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:320:5
+  --> $DIR/undocumented_unsafe_blocks.rs:325:5
    |
 LL |     unsafe {
    |     ^^^^^^^^
@@ -132,7 +132,7 @@ LL |     unsafe {
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:330:5
+  --> $DIR/undocumented_unsafe_blocks.rs:335:5
    |
 LL |     unsafe {};
    |     ^^^^^^^^^
@@ -140,7 +140,7 @@ LL |     unsafe {};
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:334:20
+  --> $DIR/undocumented_unsafe_blocks.rs:339:20
    |
 LL |     println!("{}", unsafe { String::from_utf8_unchecked(vec![]) });
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -148,7 +148,7 @@ LL |     println!("{}", unsafe { String::from_utf8_unchecked(vec![]) });
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:341:5
+  --> $DIR/undocumented_unsafe_blocks.rs:346:5
    |
 LL |     unsafe impl A for () {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^
@@ -156,7 +156,7 @@ LL |     unsafe impl A for () {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:348:9
+  --> $DIR/undocumented_unsafe_blocks.rs:353:9
    |
 LL |         unsafe impl B for (u32) {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -164,7 +164,7 @@ LL |         unsafe impl B for (u32) {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:369:13
+  --> $DIR/undocumented_unsafe_blocks.rs:374:13
    |
 LL |             unsafe impl T for $t {}
    |             ^^^^^^^^^^^^^^^^^^^^^^^
@@ -176,7 +176,7 @@ LL |     no_safety_comment!(());
    = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: unsafe impl missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:394:13
+  --> $DIR/undocumented_unsafe_blocks.rs:399:13
    |
 LL |             unsafe impl T for $t {}
    |             ^^^^^^^^^^^^^^^^^^^^^^^
@@ -188,7 +188,7 @@ LL |     no_safety_comment!(());
    = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: unsafe impl missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:402:5
+  --> $DIR/undocumented_unsafe_blocks.rs:407:5
    |
 LL |     unsafe impl T for (i32) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -196,7 +196,7 @@ LL |     unsafe impl T for (i32) {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:394:13
+  --> $DIR/undocumented_unsafe_blocks.rs:399:13
    |
 LL |             unsafe impl T for $t {}
    |             ^^^^^^^^^^^^^^^^^^^^^^^
@@ -208,7 +208,7 @@ LL |     no_safety_comment!(u32);
    = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: unsafe impl missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:408:5
+  --> $DIR/undocumented_unsafe_blocks.rs:413:5
    |
 LL |     unsafe impl T for (bool) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -216,7 +216,7 @@ LL |     unsafe impl T for (bool) {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:454:5
+  --> $DIR/undocumented_unsafe_blocks.rs:459:5
    |
 LL |     unsafe impl NoComment for () {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -224,7 +224,7 @@ LL |     unsafe impl NoComment for () {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:458:19
+  --> $DIR/undocumented_unsafe_blocks.rs:463:19
    |
 LL |     /* SAFETY: */ unsafe impl InlineComment for () {}
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -232,7 +232,7 @@ LL |     /* SAFETY: */ unsafe impl InlineComment for () {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:462:5
+  --> $DIR/undocumented_unsafe_blocks.rs:467:5
    |
 LL |     unsafe impl TrailingComment for () {} // SAFETY:
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -240,7 +240,7 @@ LL |     unsafe impl TrailingComment for () {} // SAFETY:
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:467:5
+  --> $DIR/undocumented_unsafe_blocks.rs:472:5
    |
 LL |     unsafe impl Interference for () {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -248,7 +248,7 @@ LL |     unsafe impl Interference for () {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:474:5
+  --> $DIR/undocumented_unsafe_blocks.rs:479:5
    |
 LL |     unsafe impl ImplInFn for () {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -256,7 +256,7 @@ LL |     unsafe impl ImplInFn for () {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> $DIR/undocumented_unsafe_blocks.rs:483:1
+  --> $DIR/undocumented_unsafe_blocks.rs:488:1
    |
 LL | unsafe impl CrateRoot for () {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/unnecessary_lazy_eval.fixed b/tests/ui/unnecessary_lazy_eval.fixed
index 65fcdc43061..eed81796883 100644
--- a/tests/ui/unnecessary_lazy_eval.fixed
+++ b/tests/ui/unnecessary_lazy_eval.fixed
@@ -30,6 +30,7 @@ fn main() {
     let ext_opt = Some(42);
     let nested_opt = Some(Some(42));
     let nested_tuple_opt = Some(Some((42, 43)));
+    let cond = true;
 
     // Should lint - Option
     let _ = opt.unwrap_or(2);
@@ -42,6 +43,7 @@ fn main() {
     let _ = opt.get_or_insert(2);
     let _ = opt.ok_or(2);
     let _ = nested_tuple_opt.unwrap_or(Some((1, 2)));
+    let _ = cond.then_some(astronomers_pi);
 
     // Cases when unwrap is not called on a simple variable
     let _ = Some(10).unwrap_or(2);
diff --git a/tests/ui/unnecessary_lazy_eval.rs b/tests/ui/unnecessary_lazy_eval.rs
index 206080ed69a..1588db79b38 100644
--- a/tests/ui/unnecessary_lazy_eval.rs
+++ b/tests/ui/unnecessary_lazy_eval.rs
@@ -30,6 +30,7 @@ fn main() {
     let ext_opt = Some(42);
     let nested_opt = Some(Some(42));
     let nested_tuple_opt = Some(Some((42, 43)));
+    let cond = true;
 
     // Should lint - Option
     let _ = opt.unwrap_or_else(|| 2);
@@ -42,6 +43,7 @@ fn main() {
     let _ = opt.get_or_insert_with(|| 2);
     let _ = opt.ok_or_else(|| 2);
     let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2)));
+    let _ = cond.then(|| astronomers_pi);
 
     // Cases when unwrap is not called on a simple variable
     let _ = Some(10).unwrap_or_else(|| 2);
diff --git a/tests/ui/unnecessary_lazy_eval.stderr b/tests/ui/unnecessary_lazy_eval.stderr
index 7e4dd7730e7..83dc7fd832c 100644
--- a/tests/ui/unnecessary_lazy_eval.stderr
+++ b/tests/ui/unnecessary_lazy_eval.stderr
@@ -1,5 +1,5 @@
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:35:13
+  --> $DIR/unnecessary_lazy_eval.rs:36:13
    |
 LL |     let _ = opt.unwrap_or_else(|| 2);
    |             ^^^^--------------------
@@ -9,7 +9,7 @@ LL |     let _ = opt.unwrap_or_else(|| 2);
    = note: `-D clippy::unnecessary-lazy-evaluations` implied by `-D warnings`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:36:13
+  --> $DIR/unnecessary_lazy_eval.rs:37:13
    |
 LL |     let _ = opt.unwrap_or_else(|| astronomers_pi);
    |             ^^^^---------------------------------
@@ -17,7 +17,7 @@ LL |     let _ = opt.unwrap_or_else(|| astronomers_pi);
    |                 help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:37:13
+  --> $DIR/unnecessary_lazy_eval.rs:38:13
    |
 LL |     let _ = opt.unwrap_or_else(|| ext_str.some_field);
    |             ^^^^-------------------------------------
@@ -25,7 +25,7 @@ LL |     let _ = opt.unwrap_or_else(|| ext_str.some_field);
    |                 help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:39:13
+  --> $DIR/unnecessary_lazy_eval.rs:40:13
    |
 LL |     let _ = opt.and_then(|_| ext_opt);
    |             ^^^^---------------------
@@ -33,7 +33,7 @@ LL |     let _ = opt.and_then(|_| ext_opt);
    |                 help: use `and(..)` instead: `and(ext_opt)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:40:13
+  --> $DIR/unnecessary_lazy_eval.rs:41:13
    |
 LL |     let _ = opt.or_else(|| ext_opt);
    |             ^^^^-------------------
@@ -41,7 +41,7 @@ LL |     let _ = opt.or_else(|| ext_opt);
    |                 help: use `or(..)` instead: `or(ext_opt)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:41:13
+  --> $DIR/unnecessary_lazy_eval.rs:42:13
    |
 LL |     let _ = opt.or_else(|| None);
    |             ^^^^----------------
@@ -49,7 +49,7 @@ LL |     let _ = opt.or_else(|| None);
    |                 help: use `or(..)` instead: `or(None)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:42:13
+  --> $DIR/unnecessary_lazy_eval.rs:43:13
    |
 LL |     let _ = opt.get_or_insert_with(|| 2);
    |             ^^^^------------------------
@@ -57,7 +57,7 @@ LL |     let _ = opt.get_or_insert_with(|| 2);
    |                 help: use `get_or_insert(..)` instead: `get_or_insert(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:43:13
+  --> $DIR/unnecessary_lazy_eval.rs:44:13
    |
 LL |     let _ = opt.ok_or_else(|| 2);
    |             ^^^^----------------
@@ -65,15 +65,23 @@ LL |     let _ = opt.ok_or_else(|| 2);
    |                 help: use `ok_or(..)` instead: `ok_or(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:44:13
+  --> $DIR/unnecessary_lazy_eval.rs:45:13
    |
 LL |     let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2)));
    |             ^^^^^^^^^^^^^^^^^-------------------------------
    |                              |
    |                              help: use `unwrap_or(..)` instead: `unwrap_or(Some((1, 2)))`
 
+error: unnecessary closure used with `bool::then`
+  --> $DIR/unnecessary_lazy_eval.rs:46:13
+   |
+LL |     let _ = cond.then(|| astronomers_pi);
+   |             ^^^^^-----------------------
+   |                  |
+   |                  help: use `then_some(..)` instead: `then_some(astronomers_pi)`
+
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:47:13
+  --> $DIR/unnecessary_lazy_eval.rs:49:13
    |
 LL |     let _ = Some(10).unwrap_or_else(|| 2);
    |             ^^^^^^^^^--------------------
@@ -81,7 +89,7 @@ LL |     let _ = Some(10).unwrap_or_else(|| 2);
    |                      help: use `unwrap_or(..)` instead: `unwrap_or(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:48:13
+  --> $DIR/unnecessary_lazy_eval.rs:50:13
    |
 LL |     let _ = Some(10).and_then(|_| ext_opt);
    |             ^^^^^^^^^---------------------
@@ -89,7 +97,7 @@ LL |     let _ = Some(10).and_then(|_| ext_opt);
    |                      help: use `and(..)` instead: `and(ext_opt)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:49:28
+  --> $DIR/unnecessary_lazy_eval.rs:51:28
    |
 LL |     let _: Option<usize> = None.or_else(|| ext_opt);
    |                            ^^^^^-------------------
@@ -97,7 +105,7 @@ LL |     let _: Option<usize> = None.or_else(|| ext_opt);
    |                                 help: use `or(..)` instead: `or(ext_opt)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:50:13
+  --> $DIR/unnecessary_lazy_eval.rs:52:13
    |
 LL |     let _ = None.get_or_insert_with(|| 2);
    |             ^^^^^------------------------
@@ -105,7 +113,7 @@ LL |     let _ = None.get_or_insert_with(|| 2);
    |                  help: use `get_or_insert(..)` instead: `get_or_insert(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:51:35
+  --> $DIR/unnecessary_lazy_eval.rs:53:35
    |
 LL |     let _: Result<usize, usize> = None.ok_or_else(|| 2);
    |                                   ^^^^^----------------
@@ -113,7 +121,7 @@ LL |     let _: Result<usize, usize> = None.ok_or_else(|| 2);
    |                                        help: use `ok_or(..)` instead: `ok_or(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:52:28
+  --> $DIR/unnecessary_lazy_eval.rs:54:28
    |
 LL |     let _: Option<usize> = None.or_else(|| None);
    |                            ^^^^^----------------
@@ -121,7 +129,7 @@ LL |     let _: Option<usize> = None.or_else(|| None);
    |                                 help: use `or(..)` instead: `or(None)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:55:13
+  --> $DIR/unnecessary_lazy_eval.rs:57:13
    |
 LL |     let _ = deep.0.unwrap_or_else(|| 2);
    |             ^^^^^^^--------------------
@@ -129,7 +137,7 @@ LL |     let _ = deep.0.unwrap_or_else(|| 2);
    |                    help: use `unwrap_or(..)` instead: `unwrap_or(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:56:13
+  --> $DIR/unnecessary_lazy_eval.rs:58:13
    |
 LL |     let _ = deep.0.and_then(|_| ext_opt);
    |             ^^^^^^^---------------------
@@ -137,7 +145,7 @@ LL |     let _ = deep.0.and_then(|_| ext_opt);
    |                    help: use `and(..)` instead: `and(ext_opt)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:57:13
+  --> $DIR/unnecessary_lazy_eval.rs:59:13
    |
 LL |     let _ = deep.0.or_else(|| None);
    |             ^^^^^^^----------------
@@ -145,7 +153,7 @@ LL |     let _ = deep.0.or_else(|| None);
    |                    help: use `or(..)` instead: `or(None)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:58:13
+  --> $DIR/unnecessary_lazy_eval.rs:60:13
    |
 LL |     let _ = deep.0.get_or_insert_with(|| 2);
    |             ^^^^^^^------------------------
@@ -153,7 +161,7 @@ LL |     let _ = deep.0.get_or_insert_with(|| 2);
    |                    help: use `get_or_insert(..)` instead: `get_or_insert(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:59:13
+  --> $DIR/unnecessary_lazy_eval.rs:61:13
    |
 LL |     let _ = deep.0.ok_or_else(|| 2);
    |             ^^^^^^^----------------
@@ -161,7 +169,7 @@ LL |     let _ = deep.0.ok_or_else(|| 2);
    |                    help: use `ok_or(..)` instead: `ok_or(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:79:28
+  --> $DIR/unnecessary_lazy_eval.rs:81:28
    |
 LL |     let _: Option<usize> = None.or_else(|| Some(3));
    |                            ^^^^^-------------------
@@ -169,7 +177,7 @@ LL |     let _: Option<usize> = None.or_else(|| Some(3));
    |                                 help: use `or(..)` instead: `or(Some(3))`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:80:13
+  --> $DIR/unnecessary_lazy_eval.rs:82:13
    |
 LL |     let _ = deep.0.or_else(|| Some(3));
    |             ^^^^^^^-------------------
@@ -177,7 +185,7 @@ LL |     let _ = deep.0.or_else(|| Some(3));
    |                    help: use `or(..)` instead: `or(Some(3))`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:81:13
+  --> $DIR/unnecessary_lazy_eval.rs:83:13
    |
 LL |     let _ = opt.or_else(|| Some(3));
    |             ^^^^-------------------
@@ -185,7 +193,7 @@ LL |     let _ = opt.or_else(|| Some(3));
    |                 help: use `or(..)` instead: `or(Some(3))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:87:13
+  --> $DIR/unnecessary_lazy_eval.rs:89:13
    |
 LL |     let _ = res2.unwrap_or_else(|_| 2);
    |             ^^^^^---------------------
@@ -193,7 +201,7 @@ LL |     let _ = res2.unwrap_or_else(|_| 2);
    |                  help: use `unwrap_or(..)` instead: `unwrap_or(2)`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:88:13
+  --> $DIR/unnecessary_lazy_eval.rs:90:13
    |
 LL |     let _ = res2.unwrap_or_else(|_| astronomers_pi);
    |             ^^^^^----------------------------------
@@ -201,7 +209,7 @@ LL |     let _ = res2.unwrap_or_else(|_| astronomers_pi);
    |                  help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:89:13
+  --> $DIR/unnecessary_lazy_eval.rs:91:13
    |
 LL |     let _ = res2.unwrap_or_else(|_| ext_str.some_field);
    |             ^^^^^--------------------------------------
@@ -209,7 +217,7 @@ LL |     let _ = res2.unwrap_or_else(|_| ext_str.some_field);
    |                  help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:111:35
+  --> $DIR/unnecessary_lazy_eval.rs:113:35
    |
 LL |     let _: Result<usize, usize> = res.and_then(|_| Err(2));
    |                                   ^^^^--------------------
@@ -217,7 +225,7 @@ LL |     let _: Result<usize, usize> = res.and_then(|_| Err(2));
    |                                       help: use `and(..)` instead: `and(Err(2))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:112:35
+  --> $DIR/unnecessary_lazy_eval.rs:114:35
    |
 LL |     let _: Result<usize, usize> = res.and_then(|_| Err(astronomers_pi));
    |                                   ^^^^---------------------------------
@@ -225,7 +233,7 @@ LL |     let _: Result<usize, usize> = res.and_then(|_| Err(astronomers_pi));
    |                                       help: use `and(..)` instead: `and(Err(astronomers_pi))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:113:35
+  --> $DIR/unnecessary_lazy_eval.rs:115:35
    |
 LL |     let _: Result<usize, usize> = res.and_then(|_| Err(ext_str.some_field));
    |                                   ^^^^-------------------------------------
@@ -233,7 +241,7 @@ LL |     let _: Result<usize, usize> = res.and_then(|_| Err(ext_str.some_field))
    |                                       help: use `and(..)` instead: `and(Err(ext_str.some_field))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:115:35
+  --> $DIR/unnecessary_lazy_eval.rs:117:35
    |
 LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(2));
    |                                   ^^^^------------------
@@ -241,7 +249,7 @@ LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(2));
    |                                       help: use `or(..)` instead: `or(Ok(2))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:116:35
+  --> $DIR/unnecessary_lazy_eval.rs:118:35
    |
 LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(astronomers_pi));
    |                                   ^^^^-------------------------------
@@ -249,7 +257,7 @@ LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(astronomers_pi));
    |                                       help: use `or(..)` instead: `or(Ok(astronomers_pi))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:117:35
+  --> $DIR/unnecessary_lazy_eval.rs:119:35
    |
 LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(ext_str.some_field));
    |                                   ^^^^-----------------------------------
@@ -257,7 +265,7 @@ LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(ext_str.some_field));
    |                                       help: use `or(..)` instead: `or(Ok(ext_str.some_field))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:118:35
+  --> $DIR/unnecessary_lazy_eval.rs:120:35
    |
 LL |       let _: Result<usize, usize> = res.
    |  ___________________________________^
@@ -271,5 +279,5 @@ LL | |         or_else(|_| Ok(ext_str.some_field));
    |           |
    |           help: use `or(..)` instead: `or(Ok(ext_str.some_field))`
 
-error: aborting due to 33 previous errors
+error: aborting due to 34 previous errors
 
diff --git a/util/etc/vscode-tasks.json b/util/etc/vscode-tasks.json
index e0074510c9f..ab98f9b4154 100644
--- a/util/etc/vscode-tasks.json
+++ b/util/etc/vscode-tasks.json
@@ -8,15 +8,15 @@
             "problemMatcher": [],
             "group": {
                 "kind": "build",
-                "isDefault": true,
-            },
+                "isDefault": true
+            }
         },
         {
             "label": "cargo dev fmt",
             "type": "shell",
             "command": "cargo dev fmt",
             "problemMatcher": [],
-            "group": "none",
+            "group": "none"
         },
         {
             "label": "cargo uitest",
@@ -24,19 +24,19 @@
             "command": "cargo uitest",
             "options": {
                 "env": {
-                    "RUST_BACKTRACE": "1",
                     // This task will usually execute all UI tests inside `tests/ui` you can
                     // optionally uncomment the line below and only run a specific test.
                     //
                     // See: https://github.com/rust-lang/rust-clippy/blob/master/book/src/development/adding_lints.md#testing
                     //
                     // "TESTNAME": "<TODO>",
-                },
+                    "RUST_BACKTRACE": "1"
+                }
             },
             "problemMatcher": [],
             "group": {
                 "kind": "test",
-                "isDefault": true,
+                "isDefault": true
             }
         },
         {
@@ -44,14 +44,14 @@
             "type": "shell",
             "command": "cargo test",
             "problemMatcher": [],
-            "group": "test",
+            "group": "test"
         },
         {
             "label": "cargo dev bless",
             "type": "shell",
             "command": "cargo dev bless",
             "problemMatcher": [],
-            "group": "none",
-        },
-    ],
+            "group": "none"
+        }
+    ]
 }