about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbluthej <joffrey.bluthe@e.email>2023-03-26 19:11:38 +0200
committerGitHub <noreply@github.com>2023-03-26 19:11:38 +0200
commit1d168b31c39afbd83db07c09d6a190ee17532645 (patch)
tree0446f9eded6b983cd90c0e96ec2333f79aa129b7
parentd56c9417920ffb299cd0dcf8fc7cba1092bb29d7 (diff)
parent5ed64d4c612508ece912f170005abd7988865d10 (diff)
downloadrust-1d168b31c39afbd83db07c09d6a190ee17532645.tar.gz
rust-1d168b31c39afbd83db07c09d6a190ee17532645.zip
Merge branch 'rust-lang:master' into clear-with-drain
-rw-r--r--.cargo/config.toml3
-rw-r--r--.github/workflows/clippy_bors.yml2
-rw-r--r--CHANGELOG.md1
-rw-r--r--COPYRIGHT4
-rw-r--r--README.md4
-rw-r--r--book/src/development/adding_lints.md10
-rw-r--r--clippy_lints/src/booleans.rs25
-rw-r--r--clippy_lints/src/casts/cast_possible_truncation.rs42
-rw-r--r--clippy_lints/src/cognitive_complexity.rs2
-rw-r--r--clippy_lints/src/declared_lints.rs1
-rw-r--r--clippy_lints/src/derivable_impls.rs2
-rw-r--r--clippy_lints/src/derive.rs2
-rw-r--r--clippy_lints/src/disallowed_script_idents.rs2
-rw-r--r--clippy_lints/src/functions/must_use.rs15
-rw-r--r--clippy_lints/src/future_not_send.rs6
-rw-r--r--clippy_lints/src/infinite_iter.rs2
-rw-r--r--clippy_lints/src/lib.rs2
-rw-r--r--clippy_lints/src/loops/never_loop.rs3
-rw-r--r--clippy_lints/src/manual_async_fn.rs9
-rw-r--r--clippy_lints/src/matches/significant_drop_in_scrutinee.rs1
-rw-r--r--clippy_lints/src/methods/unnecessary_sort_by.rs4
-rw-r--r--clippy_lints/src/methods/unnecessary_to_owned.rs8
-rw-r--r--clippy_lints/src/no_effect.rs6
-rw-r--r--clippy_lints/src/partialeq_ne_impl.rs2
-rw-r--r--clippy_lints/src/shadow.rs3
-rw-r--r--clippy_lints/src/significant_drop_tightening.rs39
-rw-r--r--clippy_lints/src/suspicious_operation_groupings.rs3
-rw-r--r--clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs11
-rw-r--r--clippy_lints/src/transmute/utils.rs57
-rw-r--r--clippy_lints/src/unnecessary_struct_initialization.rs84
-rw-r--r--clippy_lints/src/utils/author.rs5
-rw-r--r--clippy_utils/src/ast_utils.rs2
-rw-r--r--clippy_utils/src/attrs.rs4
-rw-r--r--clippy_utils/src/check_proc_macro.rs1
-rw-r--r--clippy_utils/src/eager_or_lazy.rs8
-rw-r--r--clippy_utils/src/hir_utils.rs3
-rw-r--r--clippy_utils/src/lib.rs11
-rw-r--r--clippy_utils/src/macros.rs21
-rw-r--r--clippy_utils/src/qualify_min_const_fn.rs7
-rw-r--r--clippy_utils/src/sugg.rs2
-rw-r--r--clippy_utils/src/visitors.rs5
-rw-r--r--rust-toolchain2
-rw-r--r--rustc_tools_util/README.md4
-rw-r--r--tests/ui-internal/custom_ice_message.stderr1
-rw-r--r--tests/ui/author/blocks.stdout6
-rw-r--r--tests/ui/boxed_local.rs35
-rw-r--r--tests/ui/boxed_local.stderr8
-rw-r--r--tests/ui/cast.rs6
-rw-r--r--tests/ui/cast.stderr112
-rw-r--r--tests/ui/erasing_op.rs8
-rw-r--r--tests/ui/erasing_op.stderr10
-rw-r--r--tests/ui/integer_arithmetic.rs2
-rw-r--r--tests/ui/needless_update.rs2
-rw-r--r--tests/ui/no_effect.rs10
-rw-r--r--tests/ui/no_effect.stderr66
-rw-r--r--tests/ui/nonminimal_bool.rs29
-rw-r--r--tests/ui/overflow_check_conditional.rs9
-rw-r--r--tests/ui/overflow_check_conditional.stderr16
-rw-r--r--tests/ui/transmutes_expressible_as_ptr_casts.fixed8
-rw-r--r--tests/ui/transmutes_expressible_as_ptr_casts.rs8
-rw-r--r--tests/ui/transmutes_expressible_as_ptr_casts.stderr8
-rw-r--r--tests/ui/unnecessary_operation.fixed10
-rw-r--r--tests/ui/unnecessary_operation.rs10
-rw-r--r--tests/ui/unnecessary_operation.stderr46
-rw-r--r--tests/ui/unnecessary_struct_initialization.fixed73
-rw-r--r--tests/ui/unnecessary_struct_initialization.rs77
-rw-r--r--tests/ui/unnecessary_struct_initialization.stderr46
67 files changed, 715 insertions, 321 deletions
diff --git a/.cargo/config.toml b/.cargo/config.toml
index f3dd9275a42..4d80d3ce63d 100644
--- a/.cargo/config.toml
+++ b/.cargo/config.toml
@@ -11,3 +11,6 @@ target-dir = "target"
 
 [unstable]
 binary-dep-depinfo = true
+
+[profile.dev]
+split-debuginfo = "unpacked"
diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml
index 24e677ce8e1..93198aabdb5 100644
--- a/.github/workflows/clippy_bors.yml
+++ b/.github/workflows/clippy_bors.yml
@@ -180,6 +180,8 @@ jobs:
 
     # Run
     - name: Build Integration Test
+      env:
+        CARGO_PROFILE_DEV_SPLIT_DEBUGINFO: off
       run: cargo test --test integration --features integration --no-run
 
     # Upload
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 81d0ff80968..8fde8c6d902 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4988,6 +4988,7 @@ Released 2018-09-13
 [`unnecessary_safety_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_safety_doc
 [`unnecessary_self_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_self_imports
 [`unnecessary_sort_by`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_sort_by
+[`unnecessary_struct_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_struct_initialization
 [`unnecessary_to_owned`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_to_owned
 [`unnecessary_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_unwrap
 [`unnecessary_wraps`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps
diff --git a/COPYRIGHT b/COPYRIGHT
index a6be75b5e31..82703b18fd7 100644
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -1,3 +1,5 @@
+// REUSE-IgnoreStart
+
 Copyright 2014-2022 The Rust Project Developers
 
 Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
@@ -5,3 +7,5 @@ http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
 <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 option. All files in the project carrying such notice may not be
 copied, modified, or distributed except according to those terms.
+
+// REUSE-IgnoreEnd
diff --git a/README.md b/README.md
index 3e7379ace7e..b69ed8900a4 100644
--- a/README.md
+++ b/README.md
@@ -275,6 +275,8 @@ If you want to contribute to Clippy, you can find more information in [CONTRIBUT
 
 ## License
 
+<!-- REUSE-IgnoreStart -->
+
 Copyright 2014-2022 The Rust Project Developers
 
 Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
@@ -282,3 +284,5 @@ Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 <LICENSE-MIT or [https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT)>, at your
 option. Files in the project may not be
 copied, modified, or distributed except according to those terms.
+
+<!-- REUSE-IgnoreEnd -->
diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md
index f57dc627dce..0f5ee7103de 100644
--- a/book/src/development/adding_lints.md
+++ b/book/src/development/adding_lints.md
@@ -18,6 +18,7 @@ because that's clearly a non-descriptive name.
     - [Cargo lints](#cargo-lints)
   - [Rustfix tests](#rustfix-tests)
   - [Testing manually](#testing-manually)
+  - [Running directly](#running-directly)
   - [Lint declaration](#lint-declaration)
   - [Lint registration](#lint-registration)
   - [Lint passes](#lint-passes)
@@ -186,6 +187,15 @@ cargo dev lint input.rs
 from the working copy root. With tests in place, let's have a look at
 implementing our lint now.
 
+## Running directly
+
+While it's easier to just use `cargo dev lint`, it might be desirable to get
+`target/release/cargo-clippy` and `target/release/clippy-driver` to work as well in some cases.
+By default, they don't work because clippy dynamically links rustc. To help them find rustc,
+add the path printed by`rustc --print target-libdir` (ran inside this workspace so that the rustc version matches)
+to your library search path.
+On linux, this can be done by setting the `LD_LIBRARY_PATH` environment variable to that path.
+
 ## Lint declaration
 
 Let's start by opening the new file created in the `clippy_lints` crate at
diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs
index e8106beec37..29fde9336c0 100644
--- a/clippy_lints/src/booleans.rs
+++ b/clippy_lints/src/booleans.rs
@@ -495,18 +495,19 @@ struct NotSimplificationVisitor<'a, 'tcx> {
 
 impl<'a, 'tcx> Visitor<'tcx> for NotSimplificationVisitor<'a, 'tcx> {
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
-        if let ExprKind::Unary(UnOp::Not, inner) = &expr.kind {
-            if let Some(suggestion) = simplify_not(self.cx, inner) {
-                span_lint_and_sugg(
-                    self.cx,
-                    NONMINIMAL_BOOL,
-                    expr.span,
-                    "this boolean expression can be simplified",
-                    "try",
-                    suggestion,
-                    Applicability::MachineApplicable,
-                );
-            }
+        if let ExprKind::Unary(UnOp::Not, inner) = &expr.kind &&
+            !inner.span.from_expansion() &&
+            let Some(suggestion) = simplify_not(self.cx, inner)
+        {
+            span_lint_and_sugg(
+                self.cx,
+                NONMINIMAL_BOOL,
+                expr.span,
+                "this boolean expression can be simplified",
+                "try",
+                suggestion,
+                Applicability::MachineApplicable,
+            );
         }
 
         walk_expr(self, expr);
diff --git a/clippy_lints/src/casts/cast_possible_truncation.rs b/clippy_lints/src/casts/cast_possible_truncation.rs
index 823970e35ab..95c2ecbf791 100644
--- a/clippy_lints/src/casts/cast_possible_truncation.rs
+++ b/clippy_lints/src/casts/cast_possible_truncation.rs
@@ -2,8 +2,9 @@ use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
 use clippy_utils::expr_or_init;
 use clippy_utils::source::snippet;
+use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::{get_discriminant_value, is_isize_or_usize};
-use rustc_errors::{Applicability, SuggestionStyle};
+use rustc_errors::{Applicability, Diagnostic, SuggestionStyle};
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::LateContext;
@@ -163,19 +164,34 @@ pub(super) fn check(
         _ => return,
     };
 
-    let name_of_cast_from = snippet(cx, cast_expr.span, "..");
-    let cast_to_snip = snippet(cx, cast_to_span, "..");
-    let suggestion = format!("{cast_to_snip}::try_from({name_of_cast_from})");
-
     span_lint_and_then(cx, CAST_POSSIBLE_TRUNCATION, expr.span, &msg, |diag| {
         diag.help("if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...");
-        diag.span_suggestion_with_style(
-            expr.span,
-            "... or use `try_from` and handle the error accordingly",
-            suggestion,
-            Applicability::Unspecified,
-            // always show the suggestion in a separate line
-            SuggestionStyle::ShowAlways,
-        );
+        if !cast_from.is_floating_point() {
+            offer_suggestion(cx, expr, cast_expr, cast_to_span, diag);
+        }
     });
 }
+
+fn offer_suggestion(
+    cx: &LateContext<'_>,
+    expr: &Expr<'_>,
+    cast_expr: &Expr<'_>,
+    cast_to_span: Span,
+    diag: &mut Diagnostic,
+) {
+    let cast_to_snip = snippet(cx, cast_to_span, "..");
+    let suggestion = if cast_to_snip == "_" {
+        format!("{}.try_into()", Sugg::hir(cx, cast_expr, "..").maybe_par())
+    } else {
+        format!("{cast_to_snip}::try_from({})", Sugg::hir(cx, cast_expr, ".."))
+    };
+
+    diag.span_suggestion_with_style(
+        expr.span,
+        "... or use `try_from` and handle the error accordingly",
+        suggestion,
+        Applicability::Unspecified,
+        // always show the suggestion in a separate line
+        SuggestionStyle::ShowAlways,
+    );
+}
diff --git a/clippy_lints/src/cognitive_complexity.rs b/clippy_lints/src/cognitive_complexity.rs
index e8531157e0f..a8926b29ac8 100644
--- a/clippy_lints/src/cognitive_complexity.rs
+++ b/clippy_lints/src/cognitive_complexity.rs
@@ -143,7 +143,7 @@ impl<'tcx> LateLintPass<'tcx> for CognitiveComplexity {
         span: Span,
         def_id: LocalDefId,
     ) {
-        if !cx.tcx.has_attr(def_id.to_def_id(), sym::test) {
+        if !cx.tcx.has_attr(def_id, sym::test) {
             let expr = if is_async_fn(kind) {
                 match get_async_fn_body(cx.tcx, body) {
                     Some(b) => b,
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index f7b108c923a..15b557bded2 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -619,6 +619,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::unnamed_address::VTABLE_ADDRESS_COMPARISONS_INFO,
     crate::unnecessary_owned_empty_strings::UNNECESSARY_OWNED_EMPTY_STRINGS_INFO,
     crate::unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS_INFO,
+    crate::unnecessary_struct_initialization::UNNECESSARY_STRUCT_INITIALIZATION_INFO,
     crate::unnecessary_wraps::UNNECESSARY_WRAPS_INFO,
     crate::unnested_or_patterns::UNNESTED_OR_PATTERNS_INFO,
     crate::unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME_INFO,
diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs
index 8a5a28c6b3d..8f68f90a2a1 100644
--- a/clippy_lints/src/derivable_impls.rs
+++ b/clippy_lints/src/derivable_impls.rs
@@ -181,7 +181,7 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
                 self_ty,
                 ..
             }) = item.kind;
-            if !cx.tcx.has_attr(item.owner_id.to_def_id(), sym::automatically_derived);
+            if !cx.tcx.has_attr(item.owner_id, sym::automatically_derived);
             if !item.span.from_expansion();
             if let Some(def_id) = trait_ref.trait_def_id();
             if cx.tcx.is_diagnostic_item(sym::Default, def_id);
diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs
index 1a9dad47839..f425dd5fb70 100644
--- a/clippy_lints/src/derive.rs
+++ b/clippy_lints/src/derive.rs
@@ -212,7 +212,7 @@ impl<'tcx> LateLintPass<'tcx> for Derive {
         }) = item.kind
         {
             let ty = cx.tcx.type_of(item.owner_id).subst_identity();
-            let is_automatically_derived = cx.tcx.has_attr(item.owner_id.to_def_id(), sym::automatically_derived);
+            let is_automatically_derived = cx.tcx.has_attr(item.owner_id, sym::automatically_derived);
 
             check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived);
             check_ord_partial_ord(cx, item.span, trait_ref, ty, is_automatically_derived);
diff --git a/clippy_lints/src/disallowed_script_idents.rs b/clippy_lints/src/disallowed_script_idents.rs
index 084190f0013..c9fad98e437 100644
--- a/clippy_lints/src/disallowed_script_idents.rs
+++ b/clippy_lints/src/disallowed_script_idents.rs
@@ -32,7 +32,7 @@ declare_clippy_lint! {
     /// ### Example
     /// ```rust
     /// // Assuming that `clippy.toml` contains the following line:
-    /// // allowed-locales = ["Latin", "Cyrillic"]
+    /// // allowed-scripts = ["Latin", "Cyrillic"]
     /// let counter = 10; // OK, latin is allowed.
     /// let счётчик = 10; // OK, cyrillic is allowed.
     /// let zähler = 10; // OK, it's still latin.
diff --git a/clippy_lints/src/functions/must_use.rs b/clippy_lints/src/functions/must_use.rs
index 29bdc46b647..1e9e826631c 100644
--- a/clippy_lints/src/functions/must_use.rs
+++ b/clippy_lints/src/functions/must_use.rs
@@ -22,13 +22,13 @@ use super::{DOUBLE_MUST_USE, MUST_USE_CANDIDATE, MUST_USE_UNIT};
 
 pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
     let attrs = cx.tcx.hir().attrs(item.hir_id());
-    let attr = cx.tcx.get_attr(item.owner_id.to_def_id(), sym::must_use);
+    let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
     if let hir::ItemKind::Fn(ref sig, _generics, ref body_id) = item.kind {
         let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
         let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
         if let Some(attr) = attr {
             check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr);
-        } else if is_public && !is_proc_macro(cx.sess(), attrs) && !attrs.iter().any(|a| a.has_name(sym::no_mangle)) {
+        } else if is_public && !is_proc_macro(attrs) && !attrs.iter().any(|a| a.has_name(sym::no_mangle)) {
             check_must_use_candidate(
                 cx,
                 sig.decl,
@@ -47,13 +47,10 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp
         let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
         let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
         let attrs = cx.tcx.hir().attrs(item.hir_id());
-        let attr = cx.tcx.get_attr(item.owner_id.to_def_id(), sym::must_use);
+        let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
         if let Some(attr) = attr {
             check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr);
-        } else if is_public
-            && !is_proc_macro(cx.sess(), attrs)
-            && trait_ref_of_method(cx, item.owner_id.def_id).is_none()
-        {
+        } else if is_public && !is_proc_macro(attrs) && trait_ref_of_method(cx, item.owner_id.def_id).is_none() {
             check_must_use_candidate(
                 cx,
                 sig.decl,
@@ -73,12 +70,12 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr
         let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
 
         let attrs = cx.tcx.hir().attrs(item.hir_id());
-        let attr = cx.tcx.get_attr(item.owner_id.to_def_id(), sym::must_use);
+        let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
         if let Some(attr) = attr {
             check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr);
         } else if let hir::TraitFn::Provided(eid) = *eid {
             let body = cx.tcx.hir().body(eid);
-            if attr.is_none() && is_public && !is_proc_macro(cx.sess(), attrs) {
+            if attr.is_none() && is_public && !is_proc_macro(attrs) {
                 check_must_use_candidate(
                     cx,
                     sig.decl,
diff --git a/clippy_lints/src/future_not_send.rs b/clippy_lints/src/future_not_send.rs
index 9fb73a371b8..ed0bd58c770 100644
--- a/clippy_lints/src/future_not_send.rs
+++ b/clippy_lints/src/future_not_send.rs
@@ -9,7 +9,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{sym, Span};
 use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
-use rustc_trait_selection::traits::{self, FulfillmentError};
+use rustc_trait_selection::traits::{self, FulfillmentError, ObligationCtxt};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -79,8 +79,10 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
                 let send_trait = cx.tcx.get_diagnostic_item(sym::Send).unwrap();
                 let span = decl.output.span();
                 let infcx = cx.tcx.infer_ctxt().build();
+                let ocx = ObligationCtxt::new(&infcx);
                 let cause = traits::ObligationCause::misc(span, fn_def_id);
-                let send_errors = traits::fully_solve_bound(&infcx, cause, cx.param_env, ret_ty, send_trait);
+                ocx.register_bound(cause, cx.param_env, ret_ty, send_trait);
+                let send_errors = ocx.select_all_or_error();
                 if !send_errors.is_empty() {
                     span_lint_and_then(
                         cx,
diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs
index d1d2db27c6f..fe28c526be3 100644
--- a/clippy_lints/src/infinite_iter.rs
+++ b/clippy_lints/src/infinite_iter.rs
@@ -167,7 +167,7 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
             Finite
         },
         ExprKind::Block(block, _) => block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)),
-        ExprKind::Box(e) | ExprKind::AddrOf(BorrowKind::Ref, _, e) => is_infinite(cx, e),
+        ExprKind::AddrOf(BorrowKind::Ref, _, e) => is_infinite(cx, e),
         ExprKind::Call(path, _) => {
             if let ExprKind::Path(ref qpath) = path.kind {
                 cx.qpath_res(qpath, path.hir_id)
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 100cba45679..c9210bf73f8 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -302,6 +302,7 @@ mod unit_types;
 mod unnamed_address;
 mod unnecessary_owned_empty_strings;
 mod unnecessary_self_imports;
+mod unnecessary_struct_initialization;
 mod unnecessary_wraps;
 mod unnested_or_patterns;
 mod unsafe_removed_from_name;
@@ -938,6 +939,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(let_with_type_underscore::UnderscoreTyped));
     store.register_late_pass(|_| Box::new(allow_attributes::AllowAttribute));
     store.register_late_pass(move |_| Box::new(manual_main_separator_str::ManualMainSeparatorStr::new(msrv())));
+    store.register_late_pass(|_| Box::new(unnecessary_struct_initialization::UnnecessaryStruct));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
 
diff --git a/clippy_lints/src/loops/never_loop.rs b/clippy_lints/src/loops/never_loop.rs
index b1bc10802e1..f0a1b1dfe56 100644
--- a/clippy_lints/src/loops/never_loop.rs
+++ b/clippy_lints/src/loops/never_loop.rs
@@ -124,8 +124,7 @@ fn stmt_to_expr<'tcx>(stmt: &Stmt<'tcx>) -> Option<(&'tcx Expr<'tcx>, Option<&'t
 #[allow(clippy::too_many_lines)]
 fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: HirId) -> NeverLoopResult {
     match expr.kind {
-        ExprKind::Box(e)
-        | ExprKind::Unary(_, e)
+        ExprKind::Unary(_, e)
         | ExprKind::Cast(e, _)
         | ExprKind::Type(e, _)
         | ExprKind::Field(e, _)
diff --git a/clippy_lints/src/manual_async_fn.rs b/clippy_lints/src/manual_async_fn.rs
index c7254b32d0b..577bc1d661d 100644
--- a/clippy_lints/src/manual_async_fn.rs
+++ b/clippy_lints/src/manual_async_fn.rs
@@ -1,5 +1,4 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::match_function_call_with_def_id;
 use clippy_utils::source::{position_before_rarrow, snippet_block, snippet_opt};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
@@ -184,16 +183,10 @@ fn captures_all_lifetimes(inputs: &[Ty<'_>], output_lifetimes: &[LifetimeName])
 fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) -> Option<&'tcx Body<'tcx>> {
     if_chain! {
         if let Some(block_expr) = block.expr;
-        if let Some(args) = cx
-            .tcx
-            .lang_items()
-            .identity_future_fn()
-            .and_then(|def_id| match_function_call_with_def_id(cx, block_expr, def_id));
-        if args.len() == 1;
         if let Expr {
             kind: ExprKind::Closure(&Closure { body, .. }),
             ..
-        } = args[0];
+        } = block_expr;
         let closure_body = cx.tcx.hir().body(body);
         if closure_body.generator_kind == Some(GeneratorKind::Async(AsyncGeneratorKind::Block));
         then {
diff --git a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
index b33a2478172..04225beeb70 100644
--- a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
+++ b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
@@ -321,7 +321,6 @@ impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> {
                     self.has_significant_drop = true;
                 }
             }
-            ExprKind::Box(..) |
             ExprKind::Array(..) |
             ExprKind::Call(..) |
             ExprKind::Unary(..) |
diff --git a/clippy_lints/src/methods/unnecessary_sort_by.rs b/clippy_lints/src/methods/unnecessary_sort_by.rs
index 5201da52bbf..67618f7038a 100644
--- a/clippy_lints/src/methods/unnecessary_sort_by.rs
+++ b/clippy_lints/src/methods/unnecessary_sort_by.rs
@@ -33,10 +33,6 @@ struct SortByKeyDetection {
 /// contains a and the other replaces it with b)
 fn mirrored_exprs(a_expr: &Expr<'_>, a_ident: &Ident, b_expr: &Expr<'_>, b_ident: &Ident) -> bool {
     match (&a_expr.kind, &b_expr.kind) {
-        // Two boxes with mirrored contents
-        (ExprKind::Box(left_expr), ExprKind::Box(right_expr)) => {
-            mirrored_exprs(left_expr, a_ident, right_expr, b_ident)
-        },
         // Two arrays with mirrored contents
         (ExprKind::Array(left_exprs), ExprKind::Array(right_exprs)) => {
             iter::zip(*left_exprs, *right_exprs).all(|(left, right)| mirrored_exprs(left, a_ident, right, b_ident))
diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs
index df26b36b7b3..4c4c003ca46 100644
--- a/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -369,10 +369,10 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
             Node::Item(item) => {
                 if let ItemKind::Fn(_, _, body_id) = &item.kind
                 && let output_ty = return_ty(cx, item.owner_id)
-                && Inherited::build(cx.tcx, item.owner_id.def_id).enter(|inherited| {
-                    let fn_ctxt = FnCtxt::new(inherited, cx.param_env, item.owner_id.def_id);
-                    fn_ctxt.can_coerce(ty, output_ty)
-                }) {
+                && let inherited = Inherited::new(cx.tcx, item.owner_id.def_id)
+                && let fn_ctxt = FnCtxt::new(&inherited, cx.param_env, item.owner_id.def_id)
+                && fn_ctxt.can_coerce(ty, output_ty)
+                {
                     if has_lifetime(output_ty) && has_lifetime(ty) {
                         return false;
                     }
diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs
index 79c1ae4861e..e3712190e67 100644
--- a/clippy_lints/src/no_effect.rs
+++ b/clippy_lints/src/no_effect.rs
@@ -127,8 +127,7 @@ fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
         | ExprKind::Type(inner, _)
         | ExprKind::Unary(_, inner)
         | ExprKind::Field(inner, _)
-        | ExprKind::AddrOf(_, _, inner)
-        | ExprKind::Box(inner) => has_no_effect(cx, inner),
+        | ExprKind::AddrOf(_, _, inner) => has_no_effect(cx, inner),
         ExprKind::Struct(_, fields, ref base) => {
             !has_drop(cx, cx.typeck_results().expr_ty(expr))
                 && fields.iter().all(|field| has_no_effect(cx, field.expr))
@@ -234,8 +233,7 @@ fn reduce_expression<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<Vec
         | ExprKind::Type(inner, _)
         | ExprKind::Unary(_, inner)
         | ExprKind::Field(inner, _)
-        | ExprKind::AddrOf(_, _, inner)
-        | ExprKind::Box(inner) => reduce_expression(cx, inner).or_else(|| Some(vec![inner])),
+        | ExprKind::AddrOf(_, _, inner) => reduce_expression(cx, inner).or_else(|| Some(vec![inner])),
         ExprKind::Struct(_, fields, ref base) => {
             if has_drop(cx, cx.typeck_results().expr_ty(expr)) {
                 None
diff --git a/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs
index 5aa3c6f2f93..a8c4823fe53 100644
--- a/clippy_lints/src/partialeq_ne_impl.rs
+++ b/clippy_lints/src/partialeq_ne_impl.rs
@@ -36,7 +36,7 @@ impl<'tcx> LateLintPass<'tcx> for PartialEqNeImpl {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
         if_chain! {
             if let ItemKind::Impl(Impl { of_trait: Some(ref trait_ref), items: impl_items, .. }) = item.kind;
-            if !cx.tcx.has_attr(item.owner_id.to_def_id(), sym::automatically_derived);
+            if !cx.tcx.has_attr(item.owner_id, sym::automatically_derived);
             if let Some(eq_trait) = cx.tcx.lang_items().eq_trait();
             if trait_ref.path.res.def_id() == eq_trait;
             then {
diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs
index 87f966ced0d..ae7d19624ba 100644
--- a/clippy_lints/src/shadow.rs
+++ b/clippy_lints/src/shadow.rs
@@ -213,8 +213,7 @@ fn is_self_shadow(cx: &LateContext<'_>, pat: &Pat<'_>, mut expr: &Expr<'_>, hir_
     }
     loop {
         expr = match expr.kind {
-            ExprKind::Box(e)
-            | ExprKind::AddrOf(_, _, e)
+            ExprKind::AddrOf(_, _, e)
             | ExprKind::Block(
                 &Block {
                     stmts: [],
diff --git a/clippy_lints/src/significant_drop_tightening.rs b/clippy_lints/src/significant_drop_tightening.rs
index e2d90edec5a..869358fb1ba 100644
--- a/clippy_lints/src/significant_drop_tightening.rs
+++ b/clippy_lints/src/significant_drop_tightening.rs
@@ -1,9 +1,9 @@
-use crate::FxHashSet;
 use clippy_utils::{
     diagnostics::span_lint_and_then,
     get_attr,
     source::{indent_of, snippet},
 };
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{Applicability, Diagnostic};
 use rustc_hir::{
     self as hir,
@@ -58,6 +58,7 @@ impl_lint_pass!(SignificantDropTightening<'_> => [SIGNIFICANT_DROP_TIGHTENING]);
 pub struct SignificantDropTightening<'tcx> {
     /// Auxiliary structure used to avoid having to verify the same type multiple times.
     seen_types: FxHashSet<Ty<'tcx>>,
+    type_cache: FxHashMap<Ty<'tcx>, bool>,
 }
 
 impl<'tcx> SignificantDropTightening<'tcx> {
@@ -118,7 +119,7 @@ impl<'tcx> SignificantDropTightening<'tcx> {
         stmt: &hir::Stmt<'_>,
         cb: impl Fn(&mut SigDropAuxParams),
     ) {
-        let mut sig_drop_finder = SigDropFinder::new(cx, &mut self.seen_types);
+        let mut sig_drop_finder = SigDropFinder::new(cx, &mut self.seen_types, &mut self.type_cache);
         sig_drop_finder.visit_expr(expr);
         if sig_drop_finder.has_sig_drop {
             cb(sdap);
@@ -296,15 +297,24 @@ impl Default for SigDropAuxParams {
 struct SigDropChecker<'cx, 'sdt, 'tcx> {
     cx: &'cx LateContext<'tcx>,
     seen_types: &'sdt mut FxHashSet<Ty<'tcx>>,
+    type_cache: &'sdt mut FxHashMap<Ty<'tcx>, bool>,
 }
 
 impl<'cx, 'sdt, 'tcx> SigDropChecker<'cx, 'sdt, 'tcx> {
-    pub(crate) fn new(cx: &'cx LateContext<'tcx>, seen_types: &'sdt mut FxHashSet<Ty<'tcx>>) -> Self {
+    pub(crate) fn new(
+        cx: &'cx LateContext<'tcx>,
+        seen_types: &'sdt mut FxHashSet<Ty<'tcx>>,
+        type_cache: &'sdt mut FxHashMap<Ty<'tcx>, bool>,
+    ) -> Self {
         seen_types.clear();
-        Self { cx, seen_types }
+        Self {
+            cx,
+            seen_types,
+            type_cache,
+        }
     }
 
-    pub(crate) fn has_sig_drop_attr(&mut self, ty: Ty<'tcx>) -> bool {
+    pub(crate) fn has_sig_drop_attr_uncached(&mut self, ty: Ty<'tcx>) -> bool {
         if let Some(adt) = ty.ty_adt_def() {
             let mut iter = get_attr(
                 self.cx.sess(),
@@ -340,6 +350,16 @@ impl<'cx, 'sdt, 'tcx> SigDropChecker<'cx, 'sdt, 'tcx> {
         }
     }
 
+    pub(crate) fn has_sig_drop_attr(&mut self, ty: Ty<'tcx>) -> bool {
+        // The borrow checker prevents us from using something fancier like or_insert_with.
+        if let Some(ty) = self.type_cache.get(&ty) {
+            return *ty;
+        }
+        let value = self.has_sig_drop_attr_uncached(ty);
+        self.type_cache.insert(ty, value);
+        value
+    }
+
     fn has_seen_ty(&mut self, ty: Ty<'tcx>) -> bool {
         !self.seen_types.insert(ty)
     }
@@ -353,11 +373,15 @@ struct SigDropFinder<'cx, 'sdt, 'tcx> {
 }
 
 impl<'cx, 'sdt, 'tcx> SigDropFinder<'cx, 'sdt, 'tcx> {
-    fn new(cx: &'cx LateContext<'tcx>, seen_types: &'sdt mut FxHashSet<Ty<'tcx>>) -> Self {
+    fn new(
+        cx: &'cx LateContext<'tcx>,
+        seen_types: &'sdt mut FxHashSet<Ty<'tcx>>,
+        type_cache: &'sdt mut FxHashMap<Ty<'tcx>, bool>,
+    ) -> Self {
         Self {
             cx,
             has_sig_drop: false,
-            sig_drop_checker: SigDropChecker::new(cx, seen_types),
+            sig_drop_checker: SigDropChecker::new(cx, seen_types, type_cache),
         }
     }
 }
@@ -380,7 +404,6 @@ impl<'cx, 'sdt, 'tcx> Visitor<'tcx> for SigDropFinder<'cx, 'sdt, 'tcx> {
             | hir::ExprKind::Assign(..)
             | hir::ExprKind::AssignOp(..)
             | hir::ExprKind::Binary(..)
-            | hir::ExprKind::Box(..)
             | hir::ExprKind::Call(..)
             | hir::ExprKind::Field(..)
             | hir::ExprKind::If(..)
diff --git a/clippy_lints/src/suspicious_operation_groupings.rs b/clippy_lints/src/suspicious_operation_groupings.rs
index e111c7d2291..8aa47b62ebf 100644
--- a/clippy_lints/src/suspicious_operation_groupings.rs
+++ b/clippy_lints/src/suspicious_operation_groupings.rs
@@ -596,8 +596,7 @@ fn ident_difference_expr_with_base_location(
         | (MethodCall(_), MethodCall(_))
         | (Call(_, _), Call(_, _))
         | (ConstBlock(_), ConstBlock(_))
-        | (Array(_), Array(_))
-        | (Box(_), Box(_)) => {
+        | (Array(_), Array(_)) => {
             // keep going
         },
         _ => {
diff --git a/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs b/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
index 8530b43243f..85cd74f23ef 100644
--- a/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
+++ b/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
@@ -2,8 +2,9 @@ use super::utils::check_cast;
 use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::sugg::Sugg;
+use rustc_ast::ExprPrecedence;
 use rustc_errors::Applicability;
-use rustc_hir::Expr;
+use rustc_hir::{Expr, Node};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{cast::CastKind, Ty};
 
@@ -19,7 +20,7 @@ pub(super) fn check<'tcx>(
 ) -> bool {
     use CastKind::{AddrPtrCast, ArrayPtrCast, FnPtrAddrCast, FnPtrPtrCast, PtrAddrCast, PtrPtrCast};
     let mut app = Applicability::MachineApplicable;
-    let sugg = match check_cast(cx, e, from_ty, to_ty) {
+    let mut sugg = match check_cast(cx, e, from_ty, to_ty) {
         Some(PtrPtrCast | AddrPtrCast | ArrayPtrCast | FnPtrPtrCast | FnPtrAddrCast) => {
             Sugg::hir_with_context(cx, arg, e.span.ctxt(), "..", &mut app)
                 .as_ty(to_ty.to_string())
@@ -39,6 +40,12 @@ pub(super) fn check<'tcx>(
         _ => return false,
     };
 
+    if let Node::Expr(parent) = cx.tcx.hir().get_parent(e.hir_id)
+        && parent.precedence().order() > ExprPrecedence::Cast.order()
+    {
+        sugg = format!("({sugg})");
+    }
+
     span_lint_and_sugg(
         cx,
         TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS,
diff --git a/clippy_lints/src/transmute/utils.rs b/clippy_lints/src/transmute/utils.rs
index cddaf9450ea..62efd13b8d9 100644
--- a/clippy_lints/src/transmute/utils.rs
+++ b/clippy_lints/src/transmute/utils.rs
@@ -33,38 +33,37 @@ pub(super) fn check_cast<'tcx>(
     let hir_id = e.hir_id;
     let local_def_id = hir_id.owner.def_id;
 
-    Inherited::build(cx.tcx, local_def_id).enter(|inherited| {
-        let fn_ctxt = FnCtxt::new(inherited, cx.param_env, local_def_id);
+    let inherited = Inherited::new(cx.tcx, local_def_id);
+    let fn_ctxt = FnCtxt::new(&inherited, cx.param_env, local_def_id);
 
-        // If we already have errors, we can't be sure we can pointer cast.
+    // If we already have errors, we can't be sure we can pointer cast.
+    assert!(
+        !fn_ctxt.errors_reported_since_creation(),
+        "Newly created FnCtxt contained errors"
+    );
+
+    if let Ok(check) = cast::CastCheck::new(
+        &fn_ctxt,
+        e,
+        from_ty,
+        to_ty,
+        // We won't show any error to the user, so we don't care what the span is here.
+        DUMMY_SP,
+        DUMMY_SP,
+        hir::Constness::NotConst,
+    ) {
+        let res = check.do_check(&fn_ctxt);
+
+        // do_check's documentation says that it might return Ok and create
+        // errors in the fcx instead of returning Err in some cases. Those cases
+        // should be filtered out before getting here.
         assert!(
             !fn_ctxt.errors_reported_since_creation(),
-            "Newly created FnCtxt contained errors"
+            "`fn_ctxt` contained errors after cast check!"
         );
 
-        if let Ok(check) = cast::CastCheck::new(
-            &fn_ctxt,
-            e,
-            from_ty,
-            to_ty,
-            // We won't show any error to the user, so we don't care what the span is here.
-            DUMMY_SP,
-            DUMMY_SP,
-            hir::Constness::NotConst,
-        ) {
-            let res = check.do_check(&fn_ctxt);
-
-            // do_check's documentation says that it might return Ok and create
-            // errors in the fcx instead of returning Err in some cases. Those cases
-            // should be filtered out before getting here.
-            assert!(
-                !fn_ctxt.errors_reported_since_creation(),
-                "`fn_ctxt` contained errors after cast check!"
-            );
-
-            res.ok()
-        } else {
-            None
-        }
-    })
+        res.ok()
+    } else {
+        None
+    }
 }
diff --git a/clippy_lints/src/unnecessary_struct_initialization.rs b/clippy_lints/src/unnecessary_struct_initialization.rs
new file mode 100644
index 00000000000..af0b4b1592f
--- /dev/null
+++ b/clippy_lints/src/unnecessary_struct_initialization.rs
@@ -0,0 +1,84 @@
+use clippy_utils::{diagnostics::span_lint_and_sugg, get_parent_expr, path_to_local, source::snippet, ty::is_copy};
+use rustc_hir::{BindingAnnotation, Expr, ExprKind, Node, PatKind, UnOp};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for initialization of a `struct` by copying a base without setting
+    /// any field.
+    ///
+    /// ### Why is this bad?
+    /// Readibility suffers from unnecessary struct building.
+    ///
+    /// ### Example
+    /// ```rust
+    /// struct S { s: String }
+    ///
+    /// let a = S { s: String::from("Hello, world!") };
+    /// let b = S { ..a };
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// struct S { s: String }
+    ///
+    /// let a = S { s: String::from("Hello, world!") };
+    /// let b = a;
+    /// ```
+    #[clippy::version = "1.70.0"]
+    pub UNNECESSARY_STRUCT_INITIALIZATION,
+    complexity,
+    "struct built from a base that can be written mode concisely"
+}
+declare_lint_pass!(UnnecessaryStruct => [UNNECESSARY_STRUCT_INITIALIZATION]);
+
+impl LateLintPass<'_> for UnnecessaryStruct {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+        if let ExprKind::Struct(_, &[], Some(base)) = expr.kind {
+            if let Some(parent) = get_parent_expr(cx, expr) &&
+                let parent_ty = cx.typeck_results().expr_ty_adjusted(parent) &&
+                parent_ty.is_any_ptr()
+            {
+                if is_copy(cx, cx.typeck_results().expr_ty(expr)) && path_to_local(base).is_some() {
+                    // When the type implements `Copy`, a reference to the new struct works on the
+                    // copy. Using the original would borrow it.
+                    return;
+                }
+
+                if parent_ty.is_mutable_ptr() && !is_mutable(cx, base) {
+                    // The original can be used in a mutable reference context only if it is mutable.
+                    return;
+                }
+            }
+
+            // TODO: do not propose to replace *XX if XX is not Copy
+            if let ExprKind::Unary(UnOp::Deref, target) = base.kind &&
+                matches!(target.kind, ExprKind::Path(..)) &&
+                !is_copy(cx, cx.typeck_results().expr_ty(expr))
+            {
+                // `*base` cannot be used instead of the struct in the general case if it is not Copy.
+                return;
+            }
+
+            span_lint_and_sugg(
+                cx,
+                UNNECESSARY_STRUCT_INITIALIZATION,
+                expr.span,
+                "unnecessary struct building",
+                "replace with",
+                snippet(cx, base.span, "..").into_owned(),
+                rustc_errors::Applicability::MachineApplicable,
+            );
+        }
+    }
+}
+
+fn is_mutable(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+    if let Some(hir_id) = path_to_local(expr) &&
+        let Node::Pat(pat) = cx.tcx.hir().get(hir_id)
+    {
+        matches!(pat.kind, PatKind::Binding(BindingAnnotation::MUT, ..))
+    } else {
+        true
+    }
+}
diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs
index f31c3fdb095..bc4adf1596d 100644
--- a/clippy_lints/src/utils/author.rs
+++ b/clippy_lints/src/utils/author.rs
@@ -395,11 +395,6 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
                 }
                 self.expr(field!(let_expr.init));
             },
-            ExprKind::Box(inner) => {
-                bind!(self, inner);
-                kind!("Box({inner})");
-                self.expr(inner);
-            },
             ExprKind::Array(elements) => {
                 bind!(self, elements);
                 kind!("Array({elements})");
diff --git a/clippy_utils/src/ast_utils.rs b/clippy_utils/src/ast_utils.rs
index d82098523e3..809d654603a 100644
--- a/clippy_utils/src/ast_utils.rs
+++ b/clippy_utils/src/ast_utils.rs
@@ -143,7 +143,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
         (Paren(l), _) => eq_expr(l, r),
         (_, Paren(r)) => eq_expr(l, r),
         (Err, Err) => true,
-        (Box(l), Box(r)) | (Try(l), Try(r)) | (Await(l), Await(r)) => eq_expr(l, r),
+        (Try(l), Try(r)) | (Await(l), Await(r)) => eq_expr(l, r),
         (Array(l), Array(r)) => over(l, r, |l, r| eq_expr(l, r)),
         (Tup(l), Tup(r)) => over(l, r, |l, r| eq_expr(l, r)),
         (Repeat(le, ls), Repeat(re, rs)) => eq_expr(le, re) && eq_expr(&ls.value, &rs.value),
diff --git a/clippy_utils/src/attrs.rs b/clippy_utils/src/attrs.rs
index 7987a233bdc..b4ad42a5027 100644
--- a/clippy_utils/src/attrs.rs
+++ b/clippy_utils/src/attrs.rs
@@ -145,8 +145,8 @@ pub fn get_unique_attr<'a>(
 
 /// Return true if the attributes contain any of `proc_macro`,
 /// `proc_macro_derive` or `proc_macro_attribute`, false otherwise
-pub fn is_proc_macro(sess: &Session, attrs: &[ast::Attribute]) -> bool {
-    attrs.iter().any(|attr| sess.is_proc_macro_attr(attr))
+pub fn is_proc_macro(attrs: &[ast::Attribute]) -> bool {
+    attrs.iter().any(rustc_ast::Attribute::is_proc_macro_attr)
 }
 
 /// Return true if the attributes contain `#[doc(hidden)]`
diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs
index 43f0df145f0..d3a6929f67e 100644
--- a/clippy_utils/src/check_proc_macro.rs
+++ b/clippy_utils/src/check_proc_macro.rs
@@ -112,7 +112,6 @@ fn qpath_search_pat(path: &QPath<'_>) -> (Pat, Pat) {
 /// Get the search patterns to use for the given expression
 fn expr_search_pat(tcx: TyCtxt<'_>, e: &Expr<'_>) -> (Pat, Pat) {
     match e.kind {
-        ExprKind::Box(e) => (Pat::Str("box"), expr_search_pat(tcx, e).1),
         ExprKind::ConstBlock(_) => (Pat::Str("const"), Pat::Str("}")),
         ExprKind::Tup([]) => (Pat::Str(")"), Pat::Str("(")),
         ExprKind::Unary(UnOp::Deref, e) => (Pat::Str("*"), expr_search_pat(tcx, e).1),
diff --git a/clippy_utils/src/eager_or_lazy.rs b/clippy_utils/src/eager_or_lazy.rs
index ee2f816f181..28c85717061 100644
--- a/clippy_utils/src/eager_or_lazy.rs
+++ b/clippy_utils/src/eager_or_lazy.rs
@@ -199,11 +199,9 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
                 },
 
                 // Memory allocation, custom operator, loop, or call to an unknown function
-                ExprKind::Box(_)
-                | ExprKind::Unary(..)
-                | ExprKind::Binary(..)
-                | ExprKind::Loop(..)
-                | ExprKind::Call(..) => self.eagerness = Lazy,
+                ExprKind::Unary(..) | ExprKind::Binary(..) | ExprKind::Loop(..) | ExprKind::Call(..) => {
+                    self.eagerness = Lazy;
+                },
 
                 ExprKind::ConstBlock(_)
                 | ExprKind::Array(_)
diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs
index 0603755f8a9..3a6d23ca5c1 100644
--- a/clippy_utils/src/hir_utils.rs
+++ b/clippy_utils/src/hir_utils.rs
@@ -249,7 +249,6 @@ impl HirEqInterExpr<'_, '_, '_> {
                 both(&li.label, &ri.label, |l, r| l.ident.name == r.ident.name)
                     && both(le, re, |l, r| self.eq_expr(l, r))
             },
-            (&ExprKind::Box(l), &ExprKind::Box(r)) => self.eq_expr(l, r),
             (&ExprKind::Call(l_fun, l_args), &ExprKind::Call(r_fun, r_args)) => {
                 self.inner.allow_side_effects && self.eq_expr(l_fun, r_fun) && self.eq_exprs(l_args, r_args)
             },
@@ -628,7 +627,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                     self.hash_expr(j);
                 }
             },
-            ExprKind::Box(e) | ExprKind::DropTemps(e) | ExprKind::Yield(e, _) => {
+            ExprKind::DropTemps(e) | ExprKind::Yield(e, _) => {
                 self.hash_expr(e);
             },
             ExprKind::Call(fun, args) => {
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index 0fdbd7a6341..e8225feb33d 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -1923,16 +1923,7 @@ pub fn is_async_fn(kind: FnKind<'_>) -> bool {
 
 /// Peels away all the compiler generated code surrounding the body of an async function,
 pub fn get_async_fn_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'tcx Expr<'tcx>> {
-    if let ExprKind::Call(
-        _,
-        &[
-            Expr {
-                kind: ExprKind::Closure(&Closure { body, .. }),
-                ..
-            },
-        ],
-    ) = body.value.kind
-    {
+    if let ExprKind::Closure(&Closure { body, .. }) = body.value.kind {
         if let ExprKind::Block(
             Block {
                 stmts: [],
diff --git a/clippy_utils/src/macros.rs b/clippy_utils/src/macros.rs
index e135bd9feee..c0e32068eca 100644
--- a/clippy_utils/src/macros.rs
+++ b/clippy_utils/src/macros.rs
@@ -533,6 +533,14 @@ struct FormatArgsValues<'tcx> {
 }
 
 impl<'tcx> FormatArgsValues<'tcx> {
+    fn new_empty(format_string_span: SpanData) -> Self {
+        Self {
+            value_args: Vec::new(),
+            pos_to_value_index: Vec::new(),
+            format_string_span,
+        }
+    }
+
     fn new(args: &'tcx Expr<'tcx>, format_string_span: SpanData) -> Self {
         let mut pos_to_value_index = Vec::new();
         let mut value_args = Vec::new();
@@ -997,12 +1005,13 @@ impl<'tcx> FormatArgsExpn<'tcx> {
             .find(|&name| matches!(name, sym::const_format_args | sym::format_args | sym::format_args_nl))?;
         let newline = macro_name == sym::format_args_nl;
 
+        // ::core::fmt::Arguments::new_const(pieces)
         // ::core::fmt::Arguments::new_v1(pieces, args)
         // ::core::fmt::Arguments::new_v1_formatted(pieces, args, fmt, _unsafe_arg)
-        if let ExprKind::Call(callee, [pieces, args, rest @ ..]) = expr.kind
+        if let ExprKind::Call(callee, [pieces, rest @ ..]) = expr.kind
             && let ExprKind::Path(QPath::TypeRelative(ty, seg)) = callee.kind
             && let TyKind::Path(QPath::LangItem(LangItem::FormatArguments, _, _)) = ty.kind
-            && matches!(seg.ident.as_str(), "new_v1" | "new_v1_formatted")
+            && matches!(seg.ident.as_str(), "new_const" | "new_v1" | "new_v1_formatted")
         {
             let format_string = FormatString::new(cx, pieces)?;
 
@@ -1026,7 +1035,7 @@ impl<'tcx> FormatArgsExpn<'tcx> {
                 return None;
             }
 
-            let positions = if let Some(fmt_arg) = rest.first() {
+            let positions = if let Some(fmt_arg) = rest.get(1) {
                 // If the argument contains format specs, `new_v1_formatted(_, _, fmt, _)`, parse
                 // them.
 
@@ -1042,7 +1051,11 @@ impl<'tcx> FormatArgsExpn<'tcx> {
                 }))
             };
 
-            let values = FormatArgsValues::new(args, format_string.span.data());
+            let values = if let Some(args) = rest.first() {
+                FormatArgsValues::new(args, format_string.span.data())
+            } else {
+                FormatArgsValues::new_empty(format_string.span.data())
+            };
 
             let args = izip!(positions, parsed_args, parser.arg_places)
                 .map(|(position, parsed_arg, arg_span)| {
diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs
index c00800291db..d66640ba0b7 100644
--- a/clippy_utils/src/qualify_min_const_fn.rs
+++ b/clippy_utils/src/qualify_min_const_fn.rs
@@ -37,7 +37,7 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv)
                 | ty::PredicateKind::ConstEvaluatable(..)
                 | ty::PredicateKind::ConstEquate(..)
                 | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue,
-                ty::PredicateKind::AliasEq(..) => panic!("alias eq predicate on function: {predicate:#?}"),
+                ty::PredicateKind::AliasRelate(..) => panic!("alias relate predicate on function: {predicate:#?}"),
                 ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {predicate:#?}"),
                 ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {predicate:#?}"),
                 ty::PredicateKind::Subtype(_) => panic!("subtype predicate on function: {predicate:#?}"),
@@ -176,6 +176,10 @@ fn check_rvalue<'tcx>(
             // FIXME(dyn-star)
             unimplemented!()
         },
+        Rvalue::Cast(CastKind::Transmute, _, _) => Err((
+            span,
+            "transmute can attempt to turn pointers into integers, so is unstable in const fn".into(),
+        )),
         // binops are fine on integers
         Rvalue::BinaryOp(_, box (lhs, rhs)) | Rvalue::CheckedBinaryOp(_, box (lhs, rhs)) => {
             check_operand(tcx, lhs, span, body)?;
@@ -241,6 +245,7 @@ fn check_statement<'tcx>(
         | StatementKind::StorageDead(_)
         | StatementKind::Retag { .. }
         | StatementKind::AscribeUserType(..)
+        | StatementKind::PlaceMention(..)
         | StatementKind::Coverage(..)
         | StatementKind::ConstEvalCounter
         | StatementKind::Nop => Ok(()),
diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs
index 65f39daf89f..a5a4a921d94 100644
--- a/clippy_utils/src/sugg.rs
+++ b/clippy_utils/src/sugg.rs
@@ -125,7 +125,6 @@ impl<'a> Sugg<'a> {
 
         match expr.kind {
             hir::ExprKind::AddrOf(..)
-            | hir::ExprKind::Box(..)
             | hir::ExprKind::If(..)
             | hir::ExprKind::Let(..)
             | hir::ExprKind::Closure { .. }
@@ -180,7 +179,6 @@ impl<'a> Sugg<'a> {
         match expr.kind {
             _ if expr.span.ctxt() != ctxt => Sugg::NonParen(snippet_with_context(cx, expr.span, ctxt, default, app).0),
             ast::ExprKind::AddrOf(..)
-            | ast::ExprKind::Box(..)
             | ast::ExprKind::Closure { .. }
             | ast::ExprKind::If(..)
             | ast::ExprKind::Let(..)
diff --git a/clippy_utils/src/visitors.rs b/clippy_utils/src/visitors.rs
index d27a20bd4df..1dc19bac984 100644
--- a/clippy_utils/src/visitors.rs
+++ b/clippy_utils/src/visitors.rs
@@ -599,10 +599,7 @@ pub fn for_each_unconsumed_temporary<'tcx, B>(
             | ExprKind::Let(&Let { init: e, .. }) => {
                 helper(typeck, false, e, f)?;
             },
-            ExprKind::Block(&Block { expr: Some(e), .. }, _)
-            | ExprKind::Box(e)
-            | ExprKind::Cast(e, _)
-            | ExprKind::Unary(_, e) => {
+            ExprKind::Block(&Block { expr: Some(e), .. }, _) | ExprKind::Cast(e, _) | ExprKind::Unary(_, e) => {
                 helper(typeck, true, e, f)?;
             },
             ExprKind::Call(callee, args) => {
diff --git a/rust-toolchain b/rust-toolchain
index d788c6359d7..0b2458ea007 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2023-03-10"
+channel = "nightly-2023-03-24"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
diff --git a/rustc_tools_util/README.md b/rustc_tools_util/README.md
index eefc661f963..e197ea048a0 100644
--- a/rustc_tools_util/README.md
+++ b/rustc_tools_util/README.md
@@ -49,6 +49,8 @@ The changelog for `rustc_tools_util` is available under:
 
 ## License
 
+<!-- REUSE-IgnoreStart -->
+
 Copyright 2014-2022 The Rust Project Developers
 
 Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
@@ -56,3 +58,5 @@ http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
 <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 option. All files in the project carrying such notice may not be
 copied, modified, or distributed except according to those terms.
+
+<!-- REUSE-IgnoreEnd -->
diff --git a/tests/ui-internal/custom_ice_message.stderr b/tests/ui-internal/custom_ice_message.stderr
index 7ed0ef0274f..b4619e980f3 100644
--- a/tests/ui-internal/custom_ice_message.stderr
+++ b/tests/ui-internal/custom_ice_message.stderr
@@ -9,3 +9,4 @@ note: we would appreciate a bug report: https://github.com/rust-lang/rust-clippy
 
 note: Clippy version: foo
 
+thread panicked while panicking. aborting.
diff --git a/tests/ui/author/blocks.stdout b/tests/ui/author/blocks.stdout
index c6acf24c21e..eb3e5189c82 100644
--- a/tests/ui/author/blocks.stdout
+++ b/tests/ui/author/blocks.stdout
@@ -43,11 +43,7 @@ if let ExprKind::Block(block, None) = expr.kind
 if let ExprKind::Closure(CaptureBy::Value, fn_decl, body_id, _, None) = expr.kind
     && let FnRetTy::DefaultReturn(_) = fn_decl.output
     && expr1 = &cx.tcx.hir().body(body_id).value
-    && let ExprKind::Call(func, args) = expr1.kind
-    && let ExprKind::Path(ref qpath) = func.kind
-    && matches!(qpath, QPath::LangItem(LangItem::IdentityFuture, _))
-    && args.len() == 1
-    && let ExprKind::Closure(CaptureBy::Value, fn_decl1, body_id1, _, Some(Movability::Static)) = args[0].kind
+    && let ExprKind::Closure(CaptureBy::Value, fn_decl1, body_id1, _, Some(Movability::Static)) = expr1.kind
     && let FnRetTy::DefaultReturn(_) = fn_decl1.output
     && expr2 = &cx.tcx.hir().body(body_id1).value
     && let ExprKind::Block(block, None) = expr2.kind
diff --git a/tests/ui/boxed_local.rs b/tests/ui/boxed_local.rs
index 4639f00a8d8..79b6d33fc77 100644
--- a/tests/ui/boxed_local.rs
+++ b/tests/ui/boxed_local.rs
@@ -1,4 +1,3 @@
-#![feature(box_syntax)]
 #![feature(lint_reasons)]
 #![allow(
     clippy::borrowed_box,
@@ -34,7 +33,7 @@ fn ok_box_trait(boxed_trait: &Box<dyn Z>) {
 }
 
 fn warn_call() {
-    let x = box A;
+    let x = Box::new(A);
     x.foo();
 }
 
@@ -43,41 +42,41 @@ fn warn_arg(x: Box<A>) {
 }
 
 fn nowarn_closure_arg() {
-    let x = Some(box A);
+    let x = Some(Box::new(A));
     x.map_or((), |x| take_ref(&x));
 }
 
 fn warn_rename_call() {
-    let x = box A;
+    let x = Box::new(A);
 
     let y = x;
     y.foo(); // via autoderef
 }
 
 fn warn_notuse() {
-    let bz = box A;
+    let bz = Box::new(A);
 }
 
 fn warn_pass() {
-    let bz = box A;
+    let bz = Box::new(A);
     take_ref(&bz); // via deref coercion
 }
 
 fn nowarn_return() -> Box<A> {
-    box A // moved out, "escapes"
+    Box::new(A) // moved out, "escapes"
 }
 
 fn nowarn_move() {
-    let bx = box A;
+    let bx = Box::new(A);
     drop(bx) // moved in, "escapes"
 }
 fn nowarn_call() {
-    let bx = box A;
+    let bx = Box::new(A);
     bx.clone(); // method only available to Box, not via autoderef
 }
 
 fn nowarn_pass() {
-    let bx = box A;
+    let bx = Box::new(A);
     take_box(&bx); // fn needs &Box
 }
 
@@ -86,30 +85,20 @@ fn take_ref(x: &A) {}
 
 fn nowarn_ref_take() {
     // false positive, should actually warn
-    let x = box A;
+    let x = Box::new(A);
     let y = &x;
     take_box(y);
 }
 
 fn nowarn_match() {
-    let x = box A; // moved into a match
+    let x = Box::new(A); // moved into a match
     match x {
         y => drop(y),
     }
 }
 
 fn warn_match() {
-    let x = box A;
-    match &x {
-        // not moved
-        y => (),
-    }
-}
-
-fn nowarn_large_array() {
-    // should not warn, is large array
-    // and should not be on stack
-    let x = box [1; 10000];
+    let x = Box::new(A);
     match &x {
         // not moved
         y => (),
diff --git a/tests/ui/boxed_local.stderr b/tests/ui/boxed_local.stderr
index 9036529f39c..10d78fbc0ab 100644
--- a/tests/ui/boxed_local.stderr
+++ b/tests/ui/boxed_local.stderr
@@ -1,5 +1,5 @@
 error: local variable doesn't need to be boxed here
-  --> $DIR/boxed_local.rs:41:13
+  --> $DIR/boxed_local.rs:40:13
    |
 LL | fn warn_arg(x: Box<A>) {
    |             ^
@@ -7,19 +7,19 @@ LL | fn warn_arg(x: Box<A>) {
    = note: `-D clippy::boxed-local` implied by `-D warnings`
 
 error: local variable doesn't need to be boxed here
-  --> $DIR/boxed_local.rs:132:12
+  --> $DIR/boxed_local.rs:121:12
    |
 LL | pub fn new(_needs_name: Box<PeekableSeekable<&()>>) -> () {}
    |            ^^^^^^^^^^^
 
 error: local variable doesn't need to be boxed here
-  --> $DIR/boxed_local.rs:196:44
+  --> $DIR/boxed_local.rs:185:44
    |
 LL |         fn default_impl_x(self: Box<Self>, x: Box<u32>) -> u32 {
    |                                            ^
 
 error: local variable doesn't need to be boxed here
-  --> $DIR/boxed_local.rs:203:16
+  --> $DIR/boxed_local.rs:192:16
    |
 LL |         fn foo(x: Box<u32>) {}
    |                ^
diff --git a/tests/ui/cast.rs b/tests/ui/cast.rs
index 8b2673c2a7f..a86b85706a3 100644
--- a/tests/ui/cast.rs
+++ b/tests/ui/cast.rs
@@ -29,6 +29,12 @@ fn main() {
     1f64 as isize;
     1f64 as usize;
     1f32 as u32 as u16;
+    {
+        let _x: i8 = 1i32 as _;
+        1f32 as i32;
+        1f64 as i32;
+        1f32 as u8;
+    }
     // Test clippy::cast_possible_wrap
     1u8 as i8;
     1u16 as i16;
diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr
index 451078de23b..65ecf1aa37a 100644
--- a/tests/ui/cast.stderr
+++ b/tests/ui/cast.stderr
@@ -44,10 +44,6 @@ LL |     1f32 as i32;
    |
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
    = note: `-D clippy::cast-possible-truncation` implied by `-D warnings`
-help: ... or use `try_from` and handle the error accordingly
-   |
-LL |     i32::try_from(1f32);
-   |     ~~~~~~~~~~~~~~~~~~~
 
 error: casting `f32` to `u32` may truncate the value
   --> $DIR/cast.rs:25:5
@@ -56,10 +52,6 @@ LL |     1f32 as u32;
    |     ^^^^^^^^^^^
    |
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
-help: ... or use `try_from` and handle the error accordingly
-   |
-LL |     u32::try_from(1f32);
-   |     ~~~~~~~~~~~~~~~~~~~
 
 error: casting `f32` to `u32` may lose the sign of the value
   --> $DIR/cast.rs:25:5
@@ -76,10 +68,6 @@ LL |     1f64 as f32;
    |     ^^^^^^^^^^^
    |
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
-help: ... or use `try_from` and handle the error accordingly
-   |
-LL |     f32::try_from(1f64);
-   |     ~~~~~~~~~~~~~~~~~~~
 
 error: casting `i32` to `i8` may truncate the value
   --> $DIR/cast.rs:27:5
@@ -112,10 +100,6 @@ LL |     1f64 as isize;
    |     ^^^^^^^^^^^^^
    |
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
-help: ... or use `try_from` and handle the error accordingly
-   |
-LL |     isize::try_from(1f64);
-   |     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `f64` to `usize` may truncate the value
   --> $DIR/cast.rs:30:5
@@ -124,10 +108,6 @@ LL |     1f64 as usize;
    |     ^^^^^^^^^^^^^
    |
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
-help: ... or use `try_from` and handle the error accordingly
-   |
-LL |     usize::try_from(1f64);
-   |     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `f64` to `usize` may lose the sign of the value
   --> $DIR/cast.rs:30:5
@@ -154,10 +134,6 @@ LL |     1f32 as u32 as u16;
    |     ^^^^^^^^^^^
    |
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
-help: ... or use `try_from` and handle the error accordingly
-   |
-LL |     u32::try_from(1f32) as u16;
-   |     ~~~~~~~~~~~~~~~~~~~
 
 error: casting `f32` to `u32` may lose the sign of the value
   --> $DIR/cast.rs:31:5
@@ -165,8 +141,50 @@ error: casting `f32` to `u32` may lose the sign of the value
 LL |     1f32 as u32 as u16;
    |     ^^^^^^^^^^^
 
+error: casting `i32` to `i8` may truncate the value
+  --> $DIR/cast.rs:33:22
+   |
+LL |         let _x: i8 = 1i32 as _;
+   |                      ^^^^^^^^^
+   |
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+   |
+LL |         let _x: i8 = 1i32.try_into();
+   |                      ~~~~~~~~~~~~~~~
+
+error: casting `f32` to `i32` may truncate the value
+  --> $DIR/cast.rs:34:9
+   |
+LL |         1f32 as i32;
+   |         ^^^^^^^^^^^
+   |
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+
+error: casting `f64` to `i32` may truncate the value
+  --> $DIR/cast.rs:35:9
+   |
+LL |         1f64 as i32;
+   |         ^^^^^^^^^^^
+   |
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+
+error: casting `f32` to `u8` may truncate the value
+  --> $DIR/cast.rs:36:9
+   |
+LL |         1f32 as u8;
+   |         ^^^^^^^^^^
+   |
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+
+error: casting `f32` to `u8` may lose the sign of the value
+  --> $DIR/cast.rs:36:9
+   |
+LL |         1f32 as u8;
+   |         ^^^^^^^^^^
+
 error: casting `u8` to `i8` may wrap around the value
-  --> $DIR/cast.rs:33:5
+  --> $DIR/cast.rs:39:5
    |
 LL |     1u8 as i8;
    |     ^^^^^^^^^
@@ -174,43 +192,43 @@ LL |     1u8 as i8;
    = note: `-D clippy::cast-possible-wrap` implied by `-D warnings`
 
 error: casting `u16` to `i16` may wrap around the value
-  --> $DIR/cast.rs:34:5
+  --> $DIR/cast.rs:40:5
    |
 LL |     1u16 as i16;
    |     ^^^^^^^^^^^
 
 error: casting `u32` to `i32` may wrap around the value
-  --> $DIR/cast.rs:35:5
+  --> $DIR/cast.rs:41:5
    |
 LL |     1u32 as i32;
    |     ^^^^^^^^^^^
 
 error: casting `u64` to `i64` may wrap around the value
-  --> $DIR/cast.rs:36:5
+  --> $DIR/cast.rs:42:5
    |
 LL |     1u64 as i64;
    |     ^^^^^^^^^^^
 
 error: casting `usize` to `isize` may wrap around the value
-  --> $DIR/cast.rs:37:5
+  --> $DIR/cast.rs:43:5
    |
 LL |     1usize as isize;
    |     ^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> $DIR/cast.rs:40:5
+  --> $DIR/cast.rs:46:5
    |
 LL |     -1i32 as u32;
    |     ^^^^^^^^^^^^
 
 error: casting `isize` to `usize` may lose the sign of the value
-  --> $DIR/cast.rs:42:5
+  --> $DIR/cast.rs:48:5
    |
 LL |     -1isize as usize;
    |     ^^^^^^^^^^^^^^^^
 
 error: casting `i64` to `i8` may truncate the value
-  --> $DIR/cast.rs:109:5
+  --> $DIR/cast.rs:115:5
    |
 LL |     (-99999999999i64).min(1) as i8; // should be linted because signed
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -222,7 +240,7 @@ LL |     i8::try_from((-99999999999i64).min(1)); // should be linted because sig
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `u64` to `u8` may truncate the value
-  --> $DIR/cast.rs:121:5
+  --> $DIR/cast.rs:127:5
    |
 LL |     999999u64.clamp(0, 256) as u8; // should still be linted
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -234,7 +252,7 @@ LL |     u8::try_from(999999u64.clamp(0, 256)); // should still be linted
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `main::E2` to `u8` may truncate the value
-  --> $DIR/cast.rs:142:21
+  --> $DIR/cast.rs:148:21
    |
 LL |             let _ = self as u8;
    |                     ^^^^^^^^^^
@@ -246,7 +264,7 @@ LL |             let _ = u8::try_from(self);
    |                     ~~~~~~~~~~~~~~~~~~
 
 error: casting `main::E2::B` to `u8` will truncate the value
-  --> $DIR/cast.rs:143:21
+  --> $DIR/cast.rs:149:21
    |
 LL |             let _ = Self::B as u8;
    |                     ^^^^^^^^^^^^^
@@ -254,7 +272,7 @@ LL |             let _ = Self::B as u8;
    = note: `-D clippy::cast-enum-truncation` implied by `-D warnings`
 
 error: casting `main::E5` to `i8` may truncate the value
-  --> $DIR/cast.rs:179:21
+  --> $DIR/cast.rs:185:21
    |
 LL |             let _ = self as i8;
    |                     ^^^^^^^^^^
@@ -266,13 +284,13 @@ LL |             let _ = i8::try_from(self);
    |                     ~~~~~~~~~~~~~~~~~~
 
 error: casting `main::E5::A` to `i8` will truncate the value
-  --> $DIR/cast.rs:180:21
+  --> $DIR/cast.rs:186:21
    |
 LL |             let _ = Self::A as i8;
    |                     ^^^^^^^^^^^^^
 
 error: casting `main::E6` to `i16` may truncate the value
-  --> $DIR/cast.rs:194:21
+  --> $DIR/cast.rs:200:21
    |
 LL |             let _ = self as i16;
    |                     ^^^^^^^^^^^
@@ -284,7 +302,7 @@ LL |             let _ = i16::try_from(self);
    |                     ~~~~~~~~~~~~~~~~~~~
 
 error: casting `main::E7` to `usize` may truncate the value on targets with 32-bit wide pointers
-  --> $DIR/cast.rs:209:21
+  --> $DIR/cast.rs:215:21
    |
 LL |             let _ = self as usize;
    |                     ^^^^^^^^^^^^^
@@ -296,7 +314,7 @@ LL |             let _ = usize::try_from(self);
    |                     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `main::E10` to `u16` may truncate the value
-  --> $DIR/cast.rs:250:21
+  --> $DIR/cast.rs:256:21
    |
 LL |             let _ = self as u16;
    |                     ^^^^^^^^^^^
@@ -308,7 +326,7 @@ LL |             let _ = u16::try_from(self);
    |                     ~~~~~~~~~~~~~~~~~~~
 
 error: casting `u32` to `u8` may truncate the value
-  --> $DIR/cast.rs:258:13
+  --> $DIR/cast.rs:264:13
    |
 LL |     let c = (q >> 16) as u8;
    |             ^^^^^^^^^^^^^^^
@@ -316,11 +334,11 @@ LL |     let c = (q >> 16) as u8;
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
-LL |     let c = u8::try_from((q >> 16));
-   |             ~~~~~~~~~~~~~~~~~~~~~~~
+LL |     let c = u8::try_from(q >> 16);
+   |             ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `u32` to `u8` may truncate the value
-  --> $DIR/cast.rs:261:13
+  --> $DIR/cast.rs:267:13
    |
 LL |     let c = (q / 1000) as u8;
    |             ^^^^^^^^^^^^^^^^
@@ -328,8 +346,8 @@ LL |     let c = (q / 1000) as u8;
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
-LL |     let c = u8::try_from((q / 1000));
-   |             ~~~~~~~~~~~~~~~~~~~~~~~~
+LL |     let c = u8::try_from(q / 1000);
+   |             ~~~~~~~~~~~~~~~~~~~~~~
 
-error: aborting due to 36 previous errors
+error: aborting due to 41 previous errors
 
diff --git a/tests/ui/erasing_op.rs b/tests/ui/erasing_op.rs
index ae2fad0086d..74985029e00 100644
--- a/tests/ui/erasing_op.rs
+++ b/tests/ui/erasing_op.rs
@@ -31,9 +31,7 @@ impl core::ops::Mul<i32> for Vec1 {
 
 #[allow(clippy::no_effect)]
 #[warn(clippy::erasing_op)]
-fn main() {
-    let x: u8 = 0;
-
+fn test(x: u8) {
     x * 0;
     0 & x;
     0 / x;
@@ -41,3 +39,7 @@ fn main() {
     0 * Vec1 { x: 5 };
     Vec1 { x: 5 } * 0;
 }
+
+fn main() {
+    test(0)
+}
diff --git a/tests/ui/erasing_op.stderr b/tests/ui/erasing_op.stderr
index 165ed9bfe58..97941252355 100644
--- a/tests/ui/erasing_op.stderr
+++ b/tests/ui/erasing_op.stderr
@@ -1,5 +1,5 @@
 error: this operation will always return zero. This is likely not the intended outcome
-  --> $DIR/erasing_op.rs:37:5
+  --> $DIR/erasing_op.rs:35:5
    |
 LL |     x * 0;
    |     ^^^^^
@@ -7,25 +7,25 @@ LL |     x * 0;
    = note: `-D clippy::erasing-op` implied by `-D warnings`
 
 error: this operation will always return zero. This is likely not the intended outcome
-  --> $DIR/erasing_op.rs:38:5
+  --> $DIR/erasing_op.rs:36:5
    |
 LL |     0 & x;
    |     ^^^^^
 
 error: this operation will always return zero. This is likely not the intended outcome
-  --> $DIR/erasing_op.rs:39:5
+  --> $DIR/erasing_op.rs:37:5
    |
 LL |     0 / x;
    |     ^^^^^
 
 error: this operation will always return zero. This is likely not the intended outcome
-  --> $DIR/erasing_op.rs:41:5
+  --> $DIR/erasing_op.rs:39:5
    |
 LL |     0 * Vec1 { x: 5 };
    |     ^^^^^^^^^^^^^^^^^
 
 error: this operation will always return zero. This is likely not the intended outcome
-  --> $DIR/erasing_op.rs:42:5
+  --> $DIR/erasing_op.rs:40:5
    |
 LL |     Vec1 { x: 5 } * 0;
    |     ^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/integer_arithmetic.rs b/tests/ui/integer_arithmetic.rs
index 67f24b4548a..8dfdee662b9 100644
--- a/tests/ui/integer_arithmetic.rs
+++ b/tests/ui/integer_arithmetic.rs
@@ -4,7 +4,7 @@
 #[rustfmt::skip]
 fn main() {
     let mut i = 1i32;
-    let mut var1 = 0i32;
+    let mut var1 = 13i32;
     let mut var2 = -1i32;
     1 + i;
     i * 2;
diff --git a/tests/ui/needless_update.rs b/tests/ui/needless_update.rs
index b93ff048a62..4e8517cad10 100644
--- a/tests/ui/needless_update.rs
+++ b/tests/ui/needless_update.rs
@@ -1,5 +1,5 @@
 #![warn(clippy::needless_update)]
-#![allow(clippy::no_effect)]
+#![allow(clippy::no_effect, clippy::unnecessary_struct_initialization)]
 
 struct S {
     pub a: i32,
diff --git a/tests/ui/no_effect.rs b/tests/ui/no_effect.rs
index f08eb092e6b..1e42e1fbabf 100644
--- a/tests/ui/no_effect.rs
+++ b/tests/ui/no_effect.rs
@@ -1,7 +1,12 @@
-#![feature(box_syntax, fn_traits, unboxed_closures)]
+#![feature(fn_traits, unboxed_closures)]
 #![warn(clippy::no_effect_underscore_binding)]
 #![allow(dead_code, path_statements)]
-#![allow(clippy::deref_addrof, clippy::redundant_field_names, clippy::uninlined_format_args)]
+#![allow(
+    clippy::deref_addrof,
+    clippy::redundant_field_names,
+    clippy::uninlined_format_args,
+    clippy::unnecessary_struct_initialization
+)]
 
 struct Unit;
 struct Tuple(i32);
@@ -102,7 +107,6 @@ fn main() {
     *&42;
     &6;
     (5, 6, 7);
-    box 42;
     ..;
     5..;
     ..5;
diff --git a/tests/ui/no_effect.stderr b/tests/ui/no_effect.stderr
index 6a1e636f9a6..f10f2bcf2a8 100644
--- a/tests/ui/no_effect.stderr
+++ b/tests/ui/no_effect.stderr
@@ -1,5 +1,5 @@
 error: statement with no effect
-  --> $DIR/no_effect.rs:92:5
+  --> $DIR/no_effect.rs:97:5
    |
 LL |     0;
    |     ^^
@@ -7,157 +7,151 @@ LL |     0;
    = note: `-D clippy::no-effect` implied by `-D warnings`
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:93:5
+  --> $DIR/no_effect.rs:98:5
    |
 LL |     s2;
    |     ^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:94:5
+  --> $DIR/no_effect.rs:99:5
    |
 LL |     Unit;
    |     ^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:95:5
+  --> $DIR/no_effect.rs:100:5
    |
 LL |     Tuple(0);
    |     ^^^^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:96:5
+  --> $DIR/no_effect.rs:101:5
    |
 LL |     Struct { field: 0 };
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:97:5
+  --> $DIR/no_effect.rs:102:5
    |
 LL |     Struct { ..s };
    |     ^^^^^^^^^^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:98:5
+  --> $DIR/no_effect.rs:103:5
    |
 LL |     Union { a: 0 };
    |     ^^^^^^^^^^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:99:5
+  --> $DIR/no_effect.rs:104:5
    |
 LL |     Enum::Tuple(0);
    |     ^^^^^^^^^^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:100:5
+  --> $DIR/no_effect.rs:105:5
    |
 LL |     Enum::Struct { field: 0 };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:101:5
+  --> $DIR/no_effect.rs:106:5
    |
 LL |     5 + 6;
    |     ^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:102:5
+  --> $DIR/no_effect.rs:107:5
    |
 LL |     *&42;
    |     ^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:103:5
+  --> $DIR/no_effect.rs:108:5
    |
 LL |     &6;
    |     ^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:104:5
+  --> $DIR/no_effect.rs:109:5
    |
 LL |     (5, 6, 7);
    |     ^^^^^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:105:5
-   |
-LL |     box 42;
-   |     ^^^^^^^
-
-error: statement with no effect
-  --> $DIR/no_effect.rs:106:5
+  --> $DIR/no_effect.rs:110:5
    |
 LL |     ..;
    |     ^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:107:5
+  --> $DIR/no_effect.rs:111:5
    |
 LL |     5..;
    |     ^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:108:5
+  --> $DIR/no_effect.rs:112:5
    |
 LL |     ..5;
    |     ^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:109:5
+  --> $DIR/no_effect.rs:113:5
    |
 LL |     5..6;
    |     ^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:110:5
+  --> $DIR/no_effect.rs:114:5
    |
 LL |     5..=6;
    |     ^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:111:5
+  --> $DIR/no_effect.rs:115:5
    |
 LL |     [42, 55];
    |     ^^^^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:112:5
+  --> $DIR/no_effect.rs:116:5
    |
 LL |     [42, 55][1];
    |     ^^^^^^^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:113:5
+  --> $DIR/no_effect.rs:117:5
    |
 LL |     (42, 55).1;
    |     ^^^^^^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:114:5
+  --> $DIR/no_effect.rs:118:5
    |
 LL |     [42; 55];
    |     ^^^^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:115:5
+  --> $DIR/no_effect.rs:119:5
    |
 LL |     [42; 55][13];
    |     ^^^^^^^^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:117:5
+  --> $DIR/no_effect.rs:121:5
    |
 LL |     || x += 5;
    |     ^^^^^^^^^^
 
 error: statement with no effect
-  --> $DIR/no_effect.rs:119:5
+  --> $DIR/no_effect.rs:123:5
    |
 LL |     FooString { s: s };
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: binding to `_` prefixed variable with no side-effect
-  --> $DIR/no_effect.rs:120:5
+  --> $DIR/no_effect.rs:124:5
    |
 LL |     let _unused = 1;
    |     ^^^^^^^^^^^^^^^^
@@ -165,22 +159,22 @@ LL |     let _unused = 1;
    = note: `-D clippy::no-effect-underscore-binding` implied by `-D warnings`
 
 error: binding to `_` prefixed variable with no side-effect
-  --> $DIR/no_effect.rs:121:5
+  --> $DIR/no_effect.rs:125:5
    |
 LL |     let _penguin = || println!("Some helpful closure");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: binding to `_` prefixed variable with no side-effect
-  --> $DIR/no_effect.rs:122:5
+  --> $DIR/no_effect.rs:126:5
    |
 LL |     let _duck = Struct { field: 0 };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: binding to `_` prefixed variable with no side-effect
-  --> $DIR/no_effect.rs:123:5
+  --> $DIR/no_effect.rs:127:5
    |
 LL |     let _cat = [2, 4, 6, 8][2];
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 30 previous errors
+error: aborting due to 29 previous errors
 
diff --git a/tests/ui/nonminimal_bool.rs b/tests/ui/nonminimal_bool.rs
index e9b4367ca65..3b5a374b4a7 100644
--- a/tests/ui/nonminimal_bool.rs
+++ b/tests/ui/nonminimal_bool.rs
@@ -63,3 +63,32 @@ fn issue9428() {
         println!("foo");
     }
 }
+
+fn issue_10523() {
+    macro_rules! a {
+        ($v:expr) => {
+            $v.is_some()
+        };
+    }
+    let x: Option<u32> = None;
+    if !a!(x) {}
+}
+
+fn issue_10523_1() {
+    macro_rules! a {
+        ($v:expr) => {
+            !$v.is_some()
+        };
+    }
+    let x: Option<u32> = None;
+    if a!(x) {}
+}
+
+fn issue_10523_2() {
+    macro_rules! a {
+        () => {
+            !None::<u32>.is_some()
+        };
+    }
+    if a!() {}
+}
diff --git a/tests/ui/overflow_check_conditional.rs b/tests/ui/overflow_check_conditional.rs
index 5db75f5291b..e1e30114081 100644
--- a/tests/ui/overflow_check_conditional.rs
+++ b/tests/ui/overflow_check_conditional.rs
@@ -1,9 +1,6 @@
 #![warn(clippy::overflow_check_conditional)]
 
-fn main() {
-    let a: u32 = 1;
-    let b: u32 = 2;
-    let c: u32 = 3;
+fn test(a: u32, b: u32, c: u32) {
     if a + b < a {}
     if a > a + b {}
     if a + b < b {}
@@ -23,3 +20,7 @@ fn main() {
     if i > i + j {}
     if i - j < i {}
 }
+
+fn main() {
+    test(1, 2, 3)
+}
diff --git a/tests/ui/overflow_check_conditional.stderr b/tests/ui/overflow_check_conditional.stderr
index 1b8b146b60a..92d1d8ef911 100644
--- a/tests/ui/overflow_check_conditional.stderr
+++ b/tests/ui/overflow_check_conditional.stderr
@@ -1,5 +1,5 @@
 error: you are trying to use classic C overflow conditions that will fail in Rust
-  --> $DIR/overflow_check_conditional.rs:7:8
+  --> $DIR/overflow_check_conditional.rs:4:8
    |
 LL |     if a + b < a {}
    |        ^^^^^^^^^
@@ -7,43 +7,43 @@ LL |     if a + b < a {}
    = note: `-D clippy::overflow-check-conditional` implied by `-D warnings`
 
 error: you are trying to use classic C overflow conditions that will fail in Rust
-  --> $DIR/overflow_check_conditional.rs:8:8
+  --> $DIR/overflow_check_conditional.rs:5:8
    |
 LL |     if a > a + b {}
    |        ^^^^^^^^^
 
 error: you are trying to use classic C overflow conditions that will fail in Rust
-  --> $DIR/overflow_check_conditional.rs:9:8
+  --> $DIR/overflow_check_conditional.rs:6:8
    |
 LL |     if a + b < b {}
    |        ^^^^^^^^^
 
 error: you are trying to use classic C overflow conditions that will fail in Rust
-  --> $DIR/overflow_check_conditional.rs:10:8
+  --> $DIR/overflow_check_conditional.rs:7:8
    |
 LL |     if b > a + b {}
    |        ^^^^^^^^^
 
 error: you are trying to use classic C underflow conditions that will fail in Rust
-  --> $DIR/overflow_check_conditional.rs:11:8
+  --> $DIR/overflow_check_conditional.rs:8:8
    |
 LL |     if a - b > b {}
    |        ^^^^^^^^^
 
 error: you are trying to use classic C underflow conditions that will fail in Rust
-  --> $DIR/overflow_check_conditional.rs:12:8
+  --> $DIR/overflow_check_conditional.rs:9:8
    |
 LL |     if b < a - b {}
    |        ^^^^^^^^^
 
 error: you are trying to use classic C underflow conditions that will fail in Rust
-  --> $DIR/overflow_check_conditional.rs:13:8
+  --> $DIR/overflow_check_conditional.rs:10:8
    |
 LL |     if a - b > a {}
    |        ^^^^^^^^^
 
 error: you are trying to use classic C underflow conditions that will fail in Rust
-  --> $DIR/overflow_check_conditional.rs:14:8
+  --> $DIR/overflow_check_conditional.rs:11:8
    |
 LL |     if a < a - b {}
    |        ^^^^^^^^^
diff --git a/tests/ui/transmutes_expressible_as_ptr_casts.fixed b/tests/ui/transmutes_expressible_as_ptr_casts.fixed
index 55307506eb3..cc84ba25bd0 100644
--- a/tests/ui/transmutes_expressible_as_ptr_casts.fixed
+++ b/tests/ui/transmutes_expressible_as_ptr_casts.fixed
@@ -4,7 +4,7 @@
 // would otherwise be responsible for
 #![warn(clippy::useless_transmute)]
 #![warn(clippy::transmute_ptr_to_ptr)]
-#![allow(dead_code, unused_unsafe, clippy::borrow_as_ptr)]
+#![allow(unused, clippy::borrow_as_ptr)]
 
 use std::mem::{size_of, transmute};
 
@@ -77,3 +77,9 @@ fn cannot_be_expressed_as_pointer_cast(in_param: Single) -> Pair {
 
     unsafe { transmute::<Single, Pair>(in_param) }
 }
+
+fn issue_10449() {
+    fn f() {}
+
+    let _x: u8 = unsafe { *(f as *const u8) };
+}
diff --git a/tests/ui/transmutes_expressible_as_ptr_casts.rs b/tests/ui/transmutes_expressible_as_ptr_casts.rs
index e7360f3f9dc..aa65ab4dd24 100644
--- a/tests/ui/transmutes_expressible_as_ptr_casts.rs
+++ b/tests/ui/transmutes_expressible_as_ptr_casts.rs
@@ -4,7 +4,7 @@
 // would otherwise be responsible for
 #![warn(clippy::useless_transmute)]
 #![warn(clippy::transmute_ptr_to_ptr)]
-#![allow(dead_code, unused_unsafe, clippy::borrow_as_ptr)]
+#![allow(unused, clippy::borrow_as_ptr)]
 
 use std::mem::{size_of, transmute};
 
@@ -77,3 +77,9 @@ fn cannot_be_expressed_as_pointer_cast(in_param: Single) -> Pair {
 
     unsafe { transmute::<Single, Pair>(in_param) }
 }
+
+fn issue_10449() {
+    fn f() {}
+
+    let _x: u8 = unsafe { *std::mem::transmute::<fn(), *const u8>(f) };
+}
diff --git a/tests/ui/transmutes_expressible_as_ptr_casts.stderr b/tests/ui/transmutes_expressible_as_ptr_casts.stderr
index e862fcb67a4..58f5162c78e 100644
--- a/tests/ui/transmutes_expressible_as_ptr_casts.stderr
+++ b/tests/ui/transmutes_expressible_as_ptr_casts.stderr
@@ -58,5 +58,11 @@ error: transmute from a reference to a pointer
 LL |     unsafe { transmute::<&[i32; 1], *const u8>(in_param) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `in_param as *const [i32; 1] as *const u8`
 
-error: aborting due to 9 previous errors
+error: transmute from `fn()` to `*const u8` which could be expressed as a pointer cast instead
+  --> $DIR/transmutes_expressible_as_ptr_casts.rs:84:28
+   |
+LL |     let _x: u8 = unsafe { *std::mem::transmute::<fn(), *const u8>(f) };
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(f as *const u8)`
+
+error: aborting due to 10 previous errors
 
diff --git a/tests/ui/unnecessary_operation.fixed b/tests/ui/unnecessary_operation.fixed
index d37163570ab..b046694f8c6 100644
--- a/tests/ui/unnecessary_operation.fixed
+++ b/tests/ui/unnecessary_operation.fixed
@@ -1,7 +1,12 @@
 // run-rustfix
 
-#![feature(box_syntax)]
-#![allow(clippy::deref_addrof, dead_code, unused, clippy::no_effect)]
+#![allow(
+    clippy::deref_addrof,
+    dead_code,
+    unused,
+    clippy::no_effect,
+    clippy::unnecessary_struct_initialization
+)]
 #![warn(clippy::unnecessary_operation)]
 
 struct Tuple(i32);
@@ -59,7 +64,6 @@ fn main() {
     5;6;get_number();
     get_number();
     get_number();
-    get_number();
     5;get_number();
     42;get_number();
     assert!([42, 55].len() > get_usize());
diff --git a/tests/ui/unnecessary_operation.rs b/tests/ui/unnecessary_operation.rs
index a14fd4bca0e..9ed9679e938 100644
--- a/tests/ui/unnecessary_operation.rs
+++ b/tests/ui/unnecessary_operation.rs
@@ -1,7 +1,12 @@
 // run-rustfix
 
-#![feature(box_syntax)]
-#![allow(clippy::deref_addrof, dead_code, unused, clippy::no_effect)]
+#![allow(
+    clippy::deref_addrof,
+    dead_code,
+    unused,
+    clippy::no_effect,
+    clippy::unnecessary_struct_initialization
+)]
 #![warn(clippy::unnecessary_operation)]
 
 struct Tuple(i32);
@@ -57,7 +62,6 @@ fn main() {
     *&get_number();
     &get_number();
     (5, 6, get_number());
-    box get_number();
     get_number()..;
     ..get_number();
     5..get_number();
diff --git a/tests/ui/unnecessary_operation.stderr b/tests/ui/unnecessary_operation.stderr
index f66d08ecb82..a1d0d93998a 100644
--- a/tests/ui/unnecessary_operation.stderr
+++ b/tests/ui/unnecessary_operation.stderr
@@ -1,5 +1,5 @@
 error: unnecessary operation
-  --> $DIR/unnecessary_operation.rs:51:5
+  --> $DIR/unnecessary_operation.rs:56:5
    |
 LL |     Tuple(get_number());
    |     ^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
@@ -7,109 +7,103 @@ LL |     Tuple(get_number());
    = note: `-D clippy::unnecessary-operation` implied by `-D warnings`
 
 error: unnecessary operation
-  --> $DIR/unnecessary_operation.rs:52:5
+  --> $DIR/unnecessary_operation.rs:57:5
    |
 LL |     Struct { field: get_number() };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
 error: unnecessary operation
-  --> $DIR/unnecessary_operation.rs:53:5
+  --> $DIR/unnecessary_operation.rs:58:5
    |
 LL |     Struct { ..get_struct() };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_struct();`
 
 error: unnecessary operation
-  --> $DIR/unnecessary_operation.rs:54:5
+  --> $DIR/unnecessary_operation.rs:59:5
    |
 LL |     Enum::Tuple(get_number());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
 error: unnecessary operation
-  --> $DIR/unnecessary_operation.rs:55:5
+  --> $DIR/unnecessary_operation.rs:60:5
    |
 LL |     Enum::Struct { field: get_number() };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
 error: unnecessary operation
-  --> $DIR/unnecessary_operation.rs:56:5
+  --> $DIR/unnecessary_operation.rs:61:5
    |
 LL |     5 + get_number();
    |     ^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;get_number();`
 
 error: unnecessary operation
-  --> $DIR/unnecessary_operation.rs:57:5
+  --> $DIR/unnecessary_operation.rs:62:5
    |
 LL |     *&get_number();
    |     ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
 error: unnecessary operation
-  --> $DIR/unnecessary_operation.rs:58:5
+  --> $DIR/unnecessary_operation.rs:63:5
    |
 LL |     &get_number();
    |     ^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
 error: unnecessary operation
-  --> $DIR/unnecessary_operation.rs:59:5
+  --> $DIR/unnecessary_operation.rs:64:5
    |
 LL |     (5, 6, get_number());
    |     ^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;6;get_number();`
 
 error: unnecessary operation
-  --> $DIR/unnecessary_operation.rs:60:5
-   |
-LL |     box get_number();
-   |     ^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
-
-error: unnecessary operation
-  --> $DIR/unnecessary_operation.rs:61:5
+  --> $DIR/unnecessary_operation.rs:65:5
    |
 LL |     get_number()..;
    |     ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
 error: unnecessary operation
-  --> $DIR/unnecessary_operation.rs:62:5
+  --> $DIR/unnecessary_operation.rs:66:5
    |
 LL |     ..get_number();
    |     ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
 error: unnecessary operation
-  --> $DIR/unnecessary_operation.rs:63:5
+  --> $DIR/unnecessary_operation.rs:67:5
    |
 LL |     5..get_number();
    |     ^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;get_number();`
 
 error: unnecessary operation
-  --> $DIR/unnecessary_operation.rs:64:5
+  --> $DIR/unnecessary_operation.rs:68:5
    |
 LL |     [42, get_number()];
    |     ^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `42;get_number();`
 
 error: unnecessary operation
-  --> $DIR/unnecessary_operation.rs:65:5
+  --> $DIR/unnecessary_operation.rs:69:5
    |
 LL |     [42, 55][get_usize()];
    |     ^^^^^^^^^^^^^^^^^^^^^^ help: statement can be written as: `assert!([42, 55].len() > get_usize());`
 
 error: unnecessary operation
-  --> $DIR/unnecessary_operation.rs:66:5
+  --> $DIR/unnecessary_operation.rs:70:5
    |
 LL |     (42, get_number()).1;
    |     ^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `42;get_number();`
 
 error: unnecessary operation
-  --> $DIR/unnecessary_operation.rs:67:5
+  --> $DIR/unnecessary_operation.rs:71:5
    |
 LL |     [get_number(); 55];
    |     ^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
 error: unnecessary operation
-  --> $DIR/unnecessary_operation.rs:68:5
+  --> $DIR/unnecessary_operation.rs:72:5
    |
 LL |     [42; 55][get_usize()];
    |     ^^^^^^^^^^^^^^^^^^^^^^ help: statement can be written as: `assert!([42; 55].len() > get_usize());`
 
 error: unnecessary operation
-  --> $DIR/unnecessary_operation.rs:69:5
+  --> $DIR/unnecessary_operation.rs:73:5
    |
 LL | /     {
 LL | |         get_number()
@@ -117,12 +111,12 @@ LL | |     };
    | |______^ help: statement can be reduced to: `get_number();`
 
 error: unnecessary operation
-  --> $DIR/unnecessary_operation.rs:72:5
+  --> $DIR/unnecessary_operation.rs:76:5
    |
 LL | /     FooString {
 LL | |         s: String::from("blah"),
 LL | |     };
    | |______^ help: statement can be reduced to: `String::from("blah");`
 
-error: aborting due to 20 previous errors
+error: aborting due to 19 previous errors
 
diff --git a/tests/ui/unnecessary_struct_initialization.fixed b/tests/ui/unnecessary_struct_initialization.fixed
new file mode 100644
index 00000000000..b47129e4a36
--- /dev/null
+++ b/tests/ui/unnecessary_struct_initialization.fixed
@@ -0,0 +1,73 @@
+// run-rustfix
+
+#![allow(unused)]
+#![warn(clippy::unnecessary_struct_initialization)]
+
+struct S {
+    f: String,
+}
+
+#[derive(Clone, Copy)]
+struct T {
+    f: u32,
+}
+
+struct U {
+    f: u32,
+}
+
+impl Clone for U {
+    fn clone(&self) -> Self {
+        // Do not lint: `Self` does not implement `Copy`
+        Self { ..*self }
+    }
+}
+
+#[derive(Copy)]
+struct V {
+    f: u32,
+}
+
+impl Clone for V {
+    fn clone(&self) -> Self {
+        // Lint: `Self` implements `Copy`
+        *self
+    }
+}
+
+fn main() {
+    // Should lint: `a` would be consumed anyway
+    let a = S { f: String::from("foo") };
+    let mut b = a;
+
+    // Should lint: `b` would be consumed, and is mutable
+    let c = &mut b;
+
+    // Should not lint as `d` is not mutable
+    let d = S { f: String::from("foo") };
+    let e = &mut S { ..d };
+
+    // Should lint as `f` would be consumed anyway
+    let f = S { f: String::from("foo") };
+    let g = &f;
+
+    // Should lint: the result of an expression is mutable
+    let h = &mut *Box::new(S { f: String::from("foo") });
+
+    // Should not lint: `m` would be both alive and borrowed
+    let m = T { f: 17 };
+    let n = &T { ..m };
+
+    // Should not lint: `m` should not be modified
+    let o = &mut T { ..m };
+    o.f = 32;
+    assert_eq!(m.f, 17);
+
+    // Should not lint: `m` should not be modified
+    let o = &mut T { ..m } as *mut T;
+    unsafe { &mut *o }.f = 32;
+    assert_eq!(m.f, 17);
+
+    // Should lint: the result of an expression is mutable and temporary
+    let p = &mut *Box::new(T { f: 5 });
+}
diff --git a/tests/ui/unnecessary_struct_initialization.rs b/tests/ui/unnecessary_struct_initialization.rs
new file mode 100644
index 00000000000..63b11c626e5
--- /dev/null
+++ b/tests/ui/unnecessary_struct_initialization.rs
@@ -0,0 +1,77 @@
+// run-rustfix
+
+#![allow(unused)]
+#![warn(clippy::unnecessary_struct_initialization)]
+
+struct S {
+    f: String,
+}
+
+#[derive(Clone, Copy)]
+struct T {
+    f: u32,
+}
+
+struct U {
+    f: u32,
+}
+
+impl Clone for U {
+    fn clone(&self) -> Self {
+        // Do not lint: `Self` does not implement `Copy`
+        Self { ..*self }
+    }
+}
+
+#[derive(Copy)]
+struct V {
+    f: u32,
+}
+
+impl Clone for V {
+    fn clone(&self) -> Self {
+        // Lint: `Self` implements `Copy`
+        Self { ..*self }
+    }
+}
+
+fn main() {
+    // Should lint: `a` would be consumed anyway
+    let a = S { f: String::from("foo") };
+    let mut b = S { ..a };
+
+    // Should lint: `b` would be consumed, and is mutable
+    let c = &mut S { ..b };
+
+    // Should not lint as `d` is not mutable
+    let d = S { f: String::from("foo") };
+    let e = &mut S { ..d };
+
+    // Should lint as `f` would be consumed anyway
+    let f = S { f: String::from("foo") };
+    let g = &S { ..f };
+
+    // Should lint: the result of an expression is mutable
+    let h = &mut S {
+        ..*Box::new(S { f: String::from("foo") })
+    };
+
+    // Should not lint: `m` would be both alive and borrowed
+    let m = T { f: 17 };
+    let n = &T { ..m };
+
+    // Should not lint: `m` should not be modified
+    let o = &mut T { ..m };
+    o.f = 32;
+    assert_eq!(m.f, 17);
+
+    // Should not lint: `m` should not be modified
+    let o = &mut T { ..m } as *mut T;
+    unsafe { &mut *o }.f = 32;
+    assert_eq!(m.f, 17);
+
+    // Should lint: the result of an expression is mutable and temporary
+    let p = &mut T {
+        ..*Box::new(T { f: 5 })
+    };
+}
diff --git a/tests/ui/unnecessary_struct_initialization.stderr b/tests/ui/unnecessary_struct_initialization.stderr
new file mode 100644
index 00000000000..ca497057702
--- /dev/null
+++ b/tests/ui/unnecessary_struct_initialization.stderr
@@ -0,0 +1,46 @@
+error: unnecessary struct building
+  --> $DIR/unnecessary_struct_initialization.rs:34:9
+   |
+LL |         Self { ..*self }
+   |         ^^^^^^^^^^^^^^^^ help: replace with: `*self`
+   |
+   = note: `-D clippy::unnecessary-struct-initialization` implied by `-D warnings`
+
+error: unnecessary struct building
+  --> $DIR/unnecessary_struct_initialization.rs:41:17
+   |
+LL |     let mut b = S { ..a };
+   |                 ^^^^^^^^^ help: replace with: `a`
+
+error: unnecessary struct building
+  --> $DIR/unnecessary_struct_initialization.rs:44:18
+   |
+LL |     let c = &mut S { ..b };
+   |                  ^^^^^^^^^ help: replace with: `b`
+
+error: unnecessary struct building
+  --> $DIR/unnecessary_struct_initialization.rs:52:14
+   |
+LL |     let g = &S { ..f };
+   |              ^^^^^^^^^ help: replace with: `f`
+
+error: unnecessary struct building
+  --> $DIR/unnecessary_struct_initialization.rs:55:18
+   |
+LL |       let h = &mut S {
+   |  __________________^
+LL | |         ..*Box::new(S { f: String::from("foo") })
+LL | |     };
+   | |_____^ help: replace with: `*Box::new(S { f: String::from("foo") })`
+
+error: unnecessary struct building
+  --> $DIR/unnecessary_struct_initialization.rs:74:18
+   |
+LL |       let p = &mut T {
+   |  __________________^
+LL | |         ..*Box::new(T { f: 5 })
+LL | |     };
+   | |_____^ help: replace with: `*Box::new(T { f: 5 })`
+
+error: aborting due to 6 previous errors
+