about summary refs log tree commit diff
diff options
context:
space:
mode:
authorThe Miri Conjob Bot <miri@cron.bot>2023-08-12 05:33:13 +0000
committerThe Miri Conjob Bot <miri@cron.bot>2023-08-12 05:33:13 +0000
commitb122fa6d6a4cfd380a1a3e41a436e560100ea8b9 (patch)
tree9686e408db723e928ea465aba698b17ca2f2f888
parent85de27ee87a75eedc67a5b8d50d71f199ee7e9e5 (diff)
parent6f5b4e358145066dfe76251e89eb40c531c4bb51 (diff)
downloadrust-b122fa6d6a4cfd380a1a3e41a436e560100ea8b9.tar.gz
rust-b122fa6d6a4cfd380a1a3e41a436e560100ea8b9.zip
Merge from rustc
-rw-r--r--.mailmap3
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs4
-rw-r--r--compiler/rustc_ast_passes/messages.ftl7
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs99
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs30
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs40
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/jit.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs25
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs26
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/mono_item.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs20
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs18
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs1
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs2
-rw-r--r--compiler/rustc_hir/src/hir.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs51
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs29
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs9
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs18
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs2
-rw-r--r--compiler/rustc_interface/src/passes.rs15
-rw-r--r--compiler/rustc_interface/src/queries.rs8
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp19
-rw-r--r--compiler/rustc_metadata/src/creader.rs6
-rw-r--r--compiler/rustc_metadata/src/dependency_format.rs3
-rw-r--r--compiler/rustc_metadata/src/fs.rs2
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs17
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs4
-rw-r--r--compiler/rustc_middle/src/dep_graph/dep_node.rs4
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs2
-rw-r--r--compiler/rustc_middle/src/middle/exported_symbols.rs2
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs4
-rw-r--r--compiler/rustc_middle/src/ty/context.rs61
-rw-r--r--compiler/rustc_passes/src/entry.rs2
-rw-r--r--compiler/rustc_passes/src/reachable.rs8
-rw-r--r--compiler/rustc_passes/src/weak_lang_items.rs2
-rw-r--r--compiler/rustc_resolve/src/late.rs6
-rw-r--r--compiler/rustc_session/src/session.rs54
-rw-r--r--compiler/rustc_smir/src/rustc_internal/mod.rs12
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs36
-rw-r--r--compiler/rustc_smir/src/stable_mir/mod.rs9
-rw-r--r--compiler/rustc_smir/src/stable_mir/ty.rs21
-rw-r--r--compiler/rustc_symbol_mangling/src/lib.rs2
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs7
-rw-r--r--compiler/rustc_trait_selection/src/solve/search_graph/cache.rs32
-rw-r--r--compiler/rustc_trait_selection/src/solve/search_graph/mod.rs65
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs2
-rw-r--r--compiler/rustc_type_ir/src/sty.rs4
-rw-r--r--library/alloc/src/collections/linked_list.rs24
-rw-r--r--library/alloc/src/rc.rs6
-rw-r--r--library/core/src/ptr/const_ptr.rs15
-rw-r--r--library/core/src/ptr/mut_ptr.rs14
-rw-r--r--library/std/Cargo.toml12
-rw-r--r--library/std/src/fs.rs3
-rw-r--r--library/std/src/io/readbuf.rs1
-rw-r--r--library/std/src/lib.rs8
-rw-r--r--library/std/src/net/tcp.rs2
-rw-r--r--library/std/src/os/unix/net/stream.rs1
-rw-r--r--library/std/src/process.rs2
-rw-r--r--library/std/src/sync/barrier.rs7
-rw-r--r--library/std/src/sys/hermit/fs.rs1
-rw-r--r--library/std/src/sys/unix/fs.rs1
-rw-r--r--library/std/src/sys/unix/stdio.rs2
-rw-r--r--src/bootstrap/compile.rs2
-rw-r--r--src/bootstrap/config.rs18
-rw-r--r--src/doc/unstable-book/src/compiler-flags/profile_sample_use.md2
-rw-r--r--src/tools/clippy/CHANGELOG.md3
-rw-r--r--src/tools/clippy/clippy_dev/src/main.rs2
-rw-r--r--src/tools/clippy/clippy_dev/src/setup/vscode.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs64
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/derive.rs50
-rw-r--r--src/tools/clippy/clippy_lints/src/doc.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/eta_reduction.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs52
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/never_loop.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_float_methods.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/expect_used.rs44
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs87
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unwrap_expect_used.rs83
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs53
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_inline.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_reference.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs207
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/mod.rs43
-rw-r--r--src/tools/clippy/clippy_lints/src/option_if_let_else.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/question_mark.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_locals.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs20
-rw-r--r--src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs48
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs5
-rw-r--r--src/tools/clippy/rust-toolchain2
-rw-r--r--src/tools/clippy/tests/ui-internal/custom_ice_message.stderr3
-rw-r--r--src/tools/clippy/tests/ui-toml/expect_used/expect_used.stderr4
-rw-r--r--src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr39
-rw-r--r--src/tools/clippy/tests/ui/const_comparisons.rs93
-rw-r--r--src/tools/clippy/tests/ui/const_comparisons.stderr228
-rw-r--r--src/tools/clippy/tests/ui/expect.stderr6
-rw-r--r--src/tools/clippy/tests/ui/filter_map_bool_then.fixed16
-rw-r--r--src/tools/clippy/tests/ui/filter_map_bool_then.rs16
-rw-r--r--src/tools/clippy/tests/ui/filter_map_bool_then.stderr18
-rw-r--r--src/tools/clippy/tests/ui/get_unwrap.stderr39
-rw-r--r--src/tools/clippy/tests/ui/ignored_unit_patterns.fixed17
-rw-r--r--src/tools/clippy/tests/ui/ignored_unit_patterns.rs17
-rw-r--r--src/tools/clippy/tests/ui/ignored_unit_patterns.stderr28
-rw-r--r--src/tools/clippy/tests/ui/mut_reference.rs15
-rw-r--r--src/tools/clippy/tests/ui/mut_reference.stderr8
-rw-r--r--src/tools/clippy/tests/ui/ptr_as_ptr.fixed16
-rw-r--r--src/tools/clippy/tests/ui/ptr_as_ptr.rs16
-rw-r--r--src/tools/clippy/tests/ui/ptr_as_ptr.stderr28
-rw-r--r--src/tools/clippy/tests/ui/question_mark.fixed17
-rw-r--r--src/tools/clippy/tests/ui/question_mark.rs17
-rw-r--r--src/tools/clippy/tests/ui/question_mark.stderr6
-rw-r--r--src/tools/clippy/tests/ui/range_contains.fixed2
-rw-r--r--src/tools/clippy/tests/ui/range_contains.rs2
-rw-r--r--src/tools/clippy/tests/ui/range_contains.stderr42
-rw-r--r--src/tools/clippy/tests/ui/redundant_guards.fixed13
-rw-r--r--src/tools/clippy/tests/ui/redundant_guards.rs13
-rw-r--r--src/tools/clippy/tests/ui/redundant_guards.stderr16
-rw-r--r--src/tools/clippy/tests/ui/redundant_locals.rs9
-rw-r--r--src/tools/clippy/tests/ui/redundant_locals.stderr22
-rw-r--r--src/tools/clippy/tests/ui/redundant_type_annotations.rs20
-rw-r--r--src/tools/clippy/tests/ui/redundant_type_annotations.stderr28
-rw-r--r--src/tools/clippy/tests/ui/rename.fixed2
-rw-r--r--src/tools/clippy/tests/ui/rename.rs2
-rw-r--r--src/tools/clippy/tests/ui/suspicious_xor_used_as_pow.stderr10
-rw-r--r--src/tools/clippy/tests/ui/unwrap.stderr9
-rw-r--r--src/tools/clippy/tests/ui/unwrap_expect_used.rs11
-rw-r--r--src/tools/clippy/tests/ui/unwrap_expect_used.stderr24
-rw-r--r--src/tools/miri/src/bin/miri.rs2
-rw-r--r--src/tools/tidy/src/deps.rs1
-rw-r--r--src/tools/tidy/src/pal.rs1
-rw-r--r--tests/codegen/method-declaration.rs26
-rw-r--r--tests/codegen/ptr-arithmetic.rs34
-rw-r--r--tests/ui/async-await/in-trait/return-type-suggestion.rs1
-rw-r--r--tests/ui/async-await/in-trait/return-type-suggestion.stderr4
-rw-r--r--tests/ui/fmt/suggest-inline-args.rs28
-rw-r--r--tests/ui/fmt/suggest-inline-args.stderr57
-rw-r--r--tests/ui/implied-bounds/implied_bounds_entailment_skip_non_outlives.rs23
-rw-r--r--tests/ui/implied-bounds/trait-where-clause-implied.rs15
-rw-r--r--tests/ui/lazy-type-alias/leading-where-clause.fixed15
-rw-r--r--tests/ui/lazy-type-alias/leading-where-clause.rs16
-rw-r--r--tests/ui/lazy-type-alias/leading-where-clause.stderr16
-rw-r--r--tests/ui/lazy-type-alias/trailing-where-clause.rs13
-rw-r--r--tests/ui/lazy-type-alias/trailing-where-clause.stderr22
-rw-r--r--tests/ui/return/return-struct.rs24
-rw-r--r--tests/ui/return/return-struct.stderr35
-rw-r--r--tests/ui/sanitize/issue-114275-cfi-const-expr-in-arry-len.rs15
-rw-r--r--tests/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr2
-rw-r--r--tests/ui/suggestions/missing-semicolon.fixed38
-rw-r--r--tests/ui/suggestions/missing-semicolon.rs38
-rw-r--r--tests/ui/suggestions/missing-semicolon.stderr75
-rw-r--r--tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.rs (renamed from tests/ui/traits/new-solver/runaway-impl-candidate-selection.rs)0
-rw-r--r--tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.stderr (renamed from tests/ui/traits/new-solver/runaway-impl-candidate-selection.stderr)0
-rw-r--r--tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs (renamed from tests/ui/traits/new-solver/coinduction/fixpoint-exponential-growth.rs)0
-rw-r--r--tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr (renamed from tests/ui/traits/new-solver/coinduction/fixpoint-exponential-growth.stderr)0
-rw-r--r--tests/ui/traits/new-solver/cycles/coinduction/incompleteness-unstable-result.rs (renamed from tests/ui/traits/new-solver/coinduction/incompleteness-unstable-result.rs)0
-rw-r--r--tests/ui/traits/new-solver/cycles/coinduction/incompleteness-unstable-result.stderr (renamed from tests/ui/traits/new-solver/coinduction/incompleteness-unstable-result.stderr)0
-rw-r--r--tests/ui/traits/new-solver/cycles/double-cycle-inductive-coinductive.rs37
-rw-r--r--tests/ui/traits/new-solver/cycles/double-cycle-inductive-coinductive.stderr29
-rw-r--r--tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.rs48
-rw-r--r--tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.stderr16
-rw-r--r--tests/ui/traits/new-solver/cycles/inductive-cycle-but-ok.rs44
-rw-r--r--tests/ui/traits/new-solver/cycles/inductive-cycle-discarded-coinductive-constraints.rs36
-rw-r--r--tests/ui/traits/new-solver/cycles/inductive-not-on-stack.rs2
-rw-r--r--tests/ui/traits/new-solver/cycles/inductive-not-on-stack.stderr15
-rw-r--r--tests/ui/traits/new-solver/cycles/leak-check-coinductive-cycle.rs (renamed from tests/ui/traits/new-solver/leak-check-coinductive-cycle.rs)2
-rw-r--r--tests/ui/traits/new-solver/cycles/provisional-result-done.rs (renamed from tests/ui/traits/new-solver/provisional-result-done.rs)0
-rw-r--r--tests/ui/traits/new-solver/dyn-any-dont-prefer-impl.rs4
-rw-r--r--tests/ui/traits/new-solver/overflow/exponential-trait-goals.rs (renamed from tests/ui/traits/new-solver/exponential-trait-goals.rs)0
-rw-r--r--tests/ui/traits/new-solver/overflow/exponential-trait-goals.stderr (renamed from tests/ui/traits/new-solver/exponential-trait-goals.stderr)0
-rw-r--r--tests/ui/traits/new-solver/overflow/recursive-self-normalization-2.rs (renamed from tests/ui/traits/new-solver/recursive-self-normalization-2.rs)0
-rw-r--r--tests/ui/traits/new-solver/overflow/recursive-self-normalization-2.stderr (renamed from tests/ui/traits/new-solver/recursive-self-normalization-2.stderr)0
-rw-r--r--tests/ui/traits/new-solver/overflow/recursive-self-normalization.rs (renamed from tests/ui/traits/new-solver/recursive-self-normalization.rs)0
-rw-r--r--tests/ui/traits/new-solver/overflow/recursive-self-normalization.stderr (renamed from tests/ui/traits/new-solver/recursive-self-normalization.stderr)0
-rw-r--r--tests/ui/where-clauses/where-clause-placement-type-alias.stderr6
-rw-r--r--triagebot.toml3
194 files changed, 2663 insertions, 767 deletions
diff --git a/.mailmap b/.mailmap
index 601064b77d4..c072f6282f1 100644
--- a/.mailmap
+++ b/.mailmap
@@ -458,6 +458,7 @@ Philipp Matthias Schäfer <philipp.matthias.schaefer@posteo.de>
 phosphorus <steepout@qq.com>
 Pierre Krieger <pierre.krieger1708@gmail.com>
 pierwill <pierwill@users.noreply.github.com> <19642016+pierwill@users.noreply.github.com>
+Pietro Albini <pietro@pietroalbini.org> <pietro@pietroalbini.io> <pietro.albini@ferrous-systems.com>
 Pradyumna Rahul <prkinformed@gmail.com>
 Przemysław Wesołek <jest@go.art.pl> Przemek Wesołek <jest@go.art.pl>
 r00ster <r00ster91@protonmail.com>
@@ -495,6 +496,8 @@ Ryan Wiedemann <Ryan1729@gmail.com>
 S Pradeep Kumar <gohanpra@gmail.com>
 Sam Radhakrishnan <sk09idm@gmail.com>
 Samuel Tardieu <sam@rfc1149.net>
+Santiago Pastorino <spastorino@gmail.com>
+Santiago Pastorino <spastorino@gmail.com> <santiago@wyeworks.com>
 Scott McMurray <scottmcm@users.noreply.github.com>
 Scott Olson <scott@solson.me> Scott Olson <scott@scott-olson.org>
 Sean Gillespie <sean.william.g@gmail.com> swgillespie <sean.william.g@gmail.com>
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 0aeff22ca9f..89775bdee26 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -457,7 +457,7 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> {
 
     // Don't hash unless necessary, because it's expensive.
     let opt_hir_hash =
-        if tcx.sess.needs_crate_hash() { Some(compute_hir_hash(tcx, &owners)) } else { None };
+        if tcx.needs_crate_hash() { Some(compute_hir_hash(tcx, &owners)) } else { None };
     hir::Crate { owners, opt_hir_hash }
 }
 
@@ -648,7 +648,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let bodies = SortedMap::from_presorted_elements(bodies);
 
         // Don't hash unless necessary, because it's expensive.
-        let (opt_hash_including_bodies, attrs_hash) = if self.tcx.sess.needs_crate_hash() {
+        let (opt_hash_including_bodies, attrs_hash) = if self.tcx.needs_crate_hash() {
             self.tcx.with_stable_hashing_context(|mut hcx| {
                 let mut stable_hasher = StableHasher::new();
                 hcx.with_hir_bodies(node.def_id(), &bodies, |hcx| {
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index 2f0ac0c2b19..f323bb4c254 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -239,5 +239,10 @@ ast_passes_visibility_not_permitted =
     .individual_impl_items = place qualifiers on individual impl items instead
     .individual_foreign_items = place qualifiers on individual foreign items instead
 
-ast_passes_where_after_type_alias = where clauses are not allowed after the type for type aliases
+ast_passes_where_clause_after_type_alias = where clauses are not allowed after the type for type aliases
+    .note = see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+    .help = add `#![feature(lazy_type_alias)]` to the crate attributes to enable
+
+ast_passes_where_clause_before_type_alias = where clauses are not allowed before the type for type aliases
     .note = see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
+    .suggestion = move it to the end of the type declaration
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index af594a00705..79fc9e4382f 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -136,40 +136,42 @@ impl<'a> AstValidator<'a> {
         }
     }
 
-    fn check_gat_where(
+    fn check_type_alias_where_clause_location(
         &mut self,
-        id: NodeId,
-        before_predicates: &[WherePredicate],
-        where_clauses: (ast::TyAliasWhereClause, ast::TyAliasWhereClause),
-    ) {
-        if !before_predicates.is_empty() {
-            let mut state = State::new();
-            if !where_clauses.1.0 {
-                state.space();
-                state.word_space("where");
-            } else {
+        ty_alias: &TyAlias,
+    ) -> Result<(), errors::WhereClauseBeforeTypeAlias> {
+        let before_predicates =
+            ty_alias.generics.where_clause.predicates.split_at(ty_alias.where_predicates_split).0;
+
+        if ty_alias.ty.is_none() || before_predicates.is_empty() {
+            return Ok(());
+        }
+
+        let mut state = State::new();
+        if !ty_alias.where_clauses.1.0 {
+            state.space();
+            state.word_space("where");
+        } else {
+            state.word_space(",");
+        }
+        let mut first = true;
+        for p in before_predicates {
+            if !first {
                 state.word_space(",");
             }
-            let mut first = true;
-            for p in before_predicates.iter() {
-                if !first {
-                    state.word_space(",");
-                }
-                first = false;
-                state.print_where_predicate(p);
-            }
-            let suggestion = state.s.eof();
-            self.lint_buffer.buffer_lint_with_diagnostic(
-                DEPRECATED_WHERE_CLAUSE_LOCATION,
-                id,
-                where_clauses.0.1,
-                fluent::ast_passes_deprecated_where_clause_location,
-                BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(
-                    where_clauses.1.1.shrink_to_hi(),
-                    suggestion,
-                ),
-            );
+            first = false;
+            state.print_where_predicate(p);
         }
+
+        let span = ty_alias.where_clauses.0.1;
+        Err(errors::WhereClauseBeforeTypeAlias {
+            span,
+            sugg: errors::WhereClauseBeforeTypeAliasSugg {
+                left: span,
+                snippet: state.s.eof(),
+                right: ty_alias.where_clauses.1.1.shrink_to_hi(),
+            },
+        })
     }
 
     fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) {
@@ -1009,7 +1011,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     replace_span: self.ending_semi_or_hi(item.span),
                 });
             }
-            ItemKind::TyAlias(box TyAlias { defaultness, where_clauses, bounds, ty, .. }) => {
+            ItemKind::TyAlias(
+                ty_alias @ box TyAlias { defaultness, bounds, where_clauses, ty, .. },
+            ) => {
                 self.check_defaultness(item.span, *defaultness);
                 if ty.is_none() {
                     self.session.emit_err(errors::TyAliasWithoutBody {
@@ -1018,9 +1022,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     });
                 }
                 self.check_type_no_bounds(bounds, "this context");
-                if where_clauses.1.0 {
-                    self.err_handler()
-                        .emit_err(errors::WhereAfterTypeAlias { span: where_clauses.1.1 });
+
+                if self.session.features_untracked().lazy_type_alias {
+                    if let Err(err) = self.check_type_alias_where_clause_location(ty_alias) {
+                        self.err_handler().emit_err(err);
+                    }
+                } else if where_clauses.1.0 {
+                    self.err_handler().emit_err(errors::WhereClauseAfterTypeAlias {
+                        span: where_clauses.1.1,
+                        help: self.session.is_nightly_build().then_some(()),
+                    });
                 }
             }
             _ => {}
@@ -1313,18 +1324,18 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             }
         }
 
-        if let AssocItemKind::Type(box TyAlias {
-            generics,
-            where_clauses,
-            where_predicates_split,
-            ty: Some(_),
-            ..
-        }) = &item.kind
+        if let AssocItemKind::Type(ty_alias) = &item.kind
+            && let Err(err) = self.check_type_alias_where_clause_location(ty_alias)
         {
-            self.check_gat_where(
+            self.lint_buffer.buffer_lint_with_diagnostic(
+                DEPRECATED_WHERE_CLAUSE_LOCATION,
                 item.id,
-                generics.where_clause.predicates.split_at(*where_predicates_split).0,
-                *where_clauses,
+                err.span,
+                fluent::ast_passes_deprecated_where_clause_location,
+                BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(
+                    err.sugg.right,
+                    err.sugg.snippet,
+                ),
             );
         }
 
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index ab8015c4a43..a6f217d4780 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -496,11 +496,37 @@ pub struct FieldlessUnion {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_where_after_type_alias)]
+#[diag(ast_passes_where_clause_after_type_alias)]
 #[note]
-pub struct WhereAfterTypeAlias {
+pub struct WhereClauseAfterTypeAlias {
     #[primary_span]
     pub span: Span,
+    #[help]
+    pub help: Option<()>,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_where_clause_before_type_alias)]
+#[note]
+pub struct WhereClauseBeforeTypeAlias {
+    #[primary_span]
+    pub span: Span,
+    #[subdiagnostic]
+    pub sugg: WhereClauseBeforeTypeAliasSugg,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(
+    ast_passes_suggestion,
+    applicability = "machine-applicable",
+    style = "verbose"
+)]
+pub struct WhereClauseBeforeTypeAliasSugg {
+    #[suggestion_part(code = "")]
+    pub left: Span,
+    pub snippet: String,
+    #[suggestion_part(code = "{snippet}")]
+    pub right: Span,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 590db12a4cd..ede95dbf897 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -1,6 +1,6 @@
 use rustc_ast::ptr::P;
-use rustc_ast::token;
 use rustc_ast::tokenstream::TokenStream;
+use rustc_ast::{token, StmtKind};
 use rustc_ast::{
     Expr, ExprKind, FormatAlignment, FormatArgPosition, FormatArgPositionKind, FormatArgs,
     FormatArgsPiece, FormatArgument, FormatArgumentKind, FormatArguments, FormatCount,
@@ -163,7 +163,7 @@ fn make_format_args(
 
     let MacroInput { fmtstr: efmt, mut args, is_direct_literal } = input;
 
-    let (fmt_str, fmt_style, fmt_span) = match expr_to_spanned_string(ecx, efmt, msg) {
+    let (fmt_str, fmt_style, fmt_span) = match expr_to_spanned_string(ecx, efmt.clone(), msg) {
         Ok(mut fmt) if append_newline => {
             fmt.0 = Symbol::intern(&format!("{}\n", fmt.0));
             fmt
@@ -171,17 +171,33 @@ fn make_format_args(
         Ok(fmt) => fmt,
         Err(err) => {
             if let Some((mut err, suggested)) = err {
-                let sugg_fmt = match args.explicit_args().len() {
-                    0 => "{}".to_string(),
-                    _ => format!("{}{{}}", "{} ".repeat(args.explicit_args().len())),
-                };
                 if !suggested {
-                    err.span_suggestion(
-                        unexpanded_fmt_span.shrink_to_lo(),
-                        "you might be missing a string literal to format with",
-                        format!("\"{sugg_fmt}\", "),
-                        Applicability::MaybeIncorrect,
-                    );
+                    if let ExprKind::Block(block, None) = &efmt.kind
+                        && block.stmts.len() == 1
+                        && let StmtKind::Expr(expr) = &block.stmts[0].kind
+                        && let ExprKind::Path(None, path) = &expr.kind
+                            && path.is_potential_trivial_const_arg()
+                    {
+                        err.multipart_suggestion(
+                            "quote your inlined format argument to use as string literal",
+                            vec![
+                                (unexpanded_fmt_span.shrink_to_hi(), "\"".to_string()),
+                                (unexpanded_fmt_span.shrink_to_lo(), "\"".to_string()),
+                            ],
+                             Applicability::MaybeIncorrect,
+                        );
+                    } else {
+                        let sugg_fmt = match args.explicit_args().len() {
+                            0 => "{}".to_string(),
+                            _ => format!("{}{{}}", "{} ".repeat(args.explicit_args().len())),
+                        };
+                        err.span_suggestion(
+                            unexpanded_fmt_span.shrink_to_lo(),
+                            "you might be missing a string literal to format with",
+                            format!("\"{sugg_fmt}\", "),
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
                 }
                 err.emit();
             }
diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
index 3ea38842148..1c606494f38 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
@@ -98,7 +98,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
         tcx.sess.fatal("JIT mode doesn't work with `cargo check`");
     }
 
-    if !tcx.sess.crate_types().contains(&rustc_session::config::CrateType::Executable) {
+    if !tcx.crate_types().contains(&rustc_session::config::CrateType::Executable) {
         tcx.sess.fatal("can't jit non-executable crate");
     }
 
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index b4f7e20e05d..24fd5bbf8c5 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -209,7 +209,7 @@ pub unsafe fn create_module<'ll>(
         // PIE is potentially more effective than PIC, but can only be used in executables.
         // If all our outputs are executables, then we can relax PIC to PIE.
         if reloc_model == RelocModel::Pie
-            || sess.crate_types().iter().all(|ty| *ty == CrateType::Executable)
+            || tcx.crate_types().iter().all(|ty| *ty == CrateType::Executable)
         {
             llvm::LLVMRustSetModulePIELevel(llmod);
         }
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index db9ba0abbde..97a99e51056 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -12,8 +12,7 @@ use rustc_middle::bug;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::coverage::CodeRegion;
 use rustc_middle::ty::TyCtxt;
-
-use std::ffi::CString;
+use rustc_span::Symbol;
 
 /// Generates and exports the Coverage Map.
 ///
@@ -89,7 +88,10 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
 
     // Encode all filenames referenced by counters/expressions in this module
     let filenames_buffer = llvm::build_byte_buffer(|filenames_buffer| {
-        coverageinfo::write_filenames_section_to_buffer(&mapgen.filenames, filenames_buffer);
+        coverageinfo::write_filenames_section_to_buffer(
+            mapgen.filenames.iter().map(Symbol::as_str),
+            filenames_buffer,
+        );
     });
 
     let filenames_size = filenames_buffer.len();
@@ -117,7 +119,7 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
 }
 
 struct CoverageMapGenerator {
-    filenames: FxIndexSet<CString>,
+    filenames: FxIndexSet<Symbol>,
 }
 
 impl CoverageMapGenerator {
@@ -128,11 +130,10 @@ impl CoverageMapGenerator {
         // Since rustc generates coverage maps with relative paths, the
         // compilation directory can be combined with the relative paths
         // to get absolute paths, if needed.
-        let working_dir =
-            tcx.sess.opts.working_dir.remapped_path_if_available().to_string_lossy().to_string();
-        let c_filename =
-            CString::new(working_dir).expect("null error converting filename to C string");
-        filenames.insert(c_filename);
+        let working_dir = Symbol::intern(
+            &tcx.sess.opts.working_dir.remapped_path_if_available().to_string_lossy(),
+        );
+        filenames.insert(working_dir);
         Self { filenames }
     }
 
@@ -170,10 +171,8 @@ impl CoverageMapGenerator {
                     current_file_id += 1;
                 }
                 current_file_name = Some(file_name);
-                let c_filename = CString::new(file_name.to_string())
-                    .expect("null error converting filename to C string");
-                debug!("  file_id: {} = '{:?}'", current_file_id, c_filename);
-                let (filenames_index, _) = self.filenames.insert_full(c_filename);
+                debug!("  file_id: {} = '{:?}'", current_file_id, file_name);
+                let (filenames_index, _) = self.filenames.insert_full(file_name);
                 virtual_file_mapping.push(filenames_index as u32);
             }
             debug!("Adding counter {:?} to map for {:?}", counter, region);
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
index afceb7531e6..621fd36b2a3 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
@@ -25,7 +25,6 @@ use rustc_middle::ty::Instance;
 use rustc_middle::ty::Ty;
 
 use std::cell::RefCell;
-use std::ffi::CString;
 
 pub(crate) mod ffi;
 pub(crate) mod map_data;
@@ -332,21 +331,32 @@ fn create_pgo_func_name_var<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
     instance: Instance<'tcx>,
 ) -> &'ll llvm::Value {
-    let mangled_fn_name = CString::new(cx.tcx.symbol_name(instance).name)
-        .expect("error converting function name to C string");
+    let mangled_fn_name: &str = cx.tcx.symbol_name(instance).name;
     let llfn = cx.get_fn(instance);
-    unsafe { llvm::LLVMRustCoverageCreatePGOFuncNameVar(llfn, mangled_fn_name.as_ptr()) }
+    unsafe {
+        llvm::LLVMRustCoverageCreatePGOFuncNameVar(
+            llfn,
+            mangled_fn_name.as_ptr().cast(),
+            mangled_fn_name.len(),
+        )
+    }
 }
 
 pub(crate) fn write_filenames_section_to_buffer<'a>(
-    filenames: impl IntoIterator<Item = &'a CString>,
+    filenames: impl IntoIterator<Item = &'a str>,
     buffer: &RustString,
 ) {
-    let c_str_vec = filenames.into_iter().map(|cstring| cstring.as_ptr()).collect::<Vec<_>>();
+    let (pointers, lengths) = filenames
+        .into_iter()
+        .map(|s: &str| (s.as_ptr().cast(), s.len()))
+        .unzip::<_, _, Vec<_>, Vec<_>>();
+
     unsafe {
         llvm::LLVMRustCoverageWriteFilenamesSectionToBuffer(
-            c_str_vec.as_ptr(),
-            c_str_vec.len(),
+            pointers.as_ptr(),
+            pointers.len(),
+            lengths.as_ptr(),
+            lengths.len(),
             buffer,
         );
     }
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
index ef7c661936a..425e935bc9f 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
@@ -92,7 +92,7 @@ pub fn needs_gdb_debug_scripts_section(cx: &CodegenCx<'_, '_>) -> bool {
     // each rlib could produce a different set of visualizers that would be embedded
     // in the `.debug_gdb_scripts` section. For that reason, we make sure that the
     // section is only emitted for leaf crates.
-    let embed_visualizers = cx.sess().crate_types().iter().any(|&crate_type| match crate_type {
+    let embed_visualizers = cx.tcx.crate_types().iter().any(|&crate_type| match crate_type {
         CrateType::Executable | CrateType::Dylib | CrateType::Cdylib | CrateType::Staticlib => {
             // These are crate types for which we will embed pretty printers since they
             // are treated as leaf crates.
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 112b4a173a5..84157d1e25c 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -1707,6 +1707,8 @@ extern "C" {
     pub fn LLVMRustCoverageWriteFilenamesSectionToBuffer(
         Filenames: *const *const c_char,
         FilenamesLen: size_t,
+        Lengths: *const size_t,
+        LengthsLen: size_t,
         BufferOut: &RustString,
     );
 
@@ -1721,7 +1723,11 @@ extern "C" {
         BufferOut: &RustString,
     );
 
-    pub fn LLVMRustCoverageCreatePGOFuncNameVar(F: &Value, FuncName: *const c_char) -> &Value;
+    pub fn LLVMRustCoverageCreatePGOFuncNameVar(
+        F: &Value,
+        FuncName: *const c_char,
+        FuncNameLen: size_t,
+    ) -> &Value;
     pub fn LLVMRustCoverageHashByteArray(Bytes: *const c_char, NumBytes: size_t) -> u64;
 
     #[allow(improper_ctypes)]
diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs
index e8cda626f54..38e8220569a 100644
--- a/compiler/rustc_codegen_llvm/src/mono_item.rs
+++ b/compiler/rustc_codegen_llvm/src/mono_item.rs
@@ -111,7 +111,7 @@ impl CodegenCx<'_, '_> {
         }
 
         // Symbols from executables can't really be imported any further.
-        let all_exe = self.tcx.sess.crate_types().iter().all(|ty| *ty == CrateType::Executable);
+        let all_exe = self.tcx.crate_types().iter().all(|ty| *ty == CrateType::Executable);
         let is_declaration_for_linker =
             is_declaration || linkage == llvm::Linkage::AvailableExternallyLinkage;
         if all_exe && !is_declaration_for_linker {
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index cd6201648ee..bb65c3c81d9 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -69,7 +69,7 @@ pub fn link_binary<'a>(
     let _timer = sess.timer("link_binary");
     let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
     let mut tempfiles_for_stdout_output: Vec<PathBuf> = Vec::new();
-    for &crate_type in sess.crate_types().iter() {
+    for &crate_type in &codegen_results.crate_info.crate_types {
         // Ignore executable crates if we have -Z no-codegen, as they will error.
         if (sess.opts.unstable_opts.no_codegen || !sess.opts.output_types.should_codegen())
             && !output_metadata
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index a1e322f4b31..11afe0fbc3c 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -1703,7 +1703,7 @@ fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec<String> {
         return Vec::new();
     }
 
-    let stable_crate_id = tcx.sess.local_stable_crate_id();
+    let stable_crate_id = tcx.stable_crate_id(LOCAL_CRATE);
     let proc_macro_decls_name = tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id);
     let metadata_symbol_name = exported_symbols::metadata_symbol_name(tcx);
 
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 326b28ad104..8fb2ccb7e8a 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -19,7 +19,7 @@ use rustc_session::config::{CrateType, OomStrategy};
 use rustc_target::spec::SanitizerSet;
 
 pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
-    crates_export_threshold(&tcx.sess.crate_types())
+    crates_export_threshold(tcx.crate_types())
 }
 
 fn crate_export_threshold(crate_type: CrateType) -> SymbolExportLevel {
@@ -290,8 +290,8 @@ fn exported_symbols_provider_local(
         }));
     }
 
-    if tcx.sess.crate_types().contains(&CrateType::Dylib)
-        || tcx.sess.crate_types().contains(&CrateType::ProcMacro)
+    if tcx.crate_types().contains(&CrateType::Dylib)
+        || tcx.crate_types().contains(&CrateType::ProcMacro)
     {
         let symbol_name = metadata_symbol_name(tcx);
         let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name));
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 40718525741..f485af00bca 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -123,7 +123,7 @@ pub struct ModuleConfig {
 impl ModuleConfig {
     fn new(
         kind: ModuleKind,
-        sess: &Session,
+        tcx: TyCtxt<'_>,
         no_builtins: bool,
         is_compiler_builtins: bool,
     ) -> ModuleConfig {
@@ -135,6 +135,7 @@ impl ModuleConfig {
             };
         }
 
+        let sess = tcx.sess;
         let opt_level_and_size = if_regular!(Some(sess.opts.optimize), None);
 
         let save_temps = sess.opts.cg.save_temps;
@@ -166,7 +167,7 @@ impl ModuleConfig {
             // `#![no_builtins]` is assumed to not participate in LTO and
             // instead goes on to generate object code.
             EmitObj::Bitcode
-        } else if need_bitcode_in_object(sess) {
+        } else if need_bitcode_in_object(tcx) {
             EmitObj::ObjectCode(BitcodeSection::Full)
         } else {
             EmitObj::ObjectCode(BitcodeSection::None)
@@ -414,9 +415,10 @@ pub struct CompiledModules {
     pub allocator_module: Option<CompiledModule>,
 }
 
-fn need_bitcode_in_object(sess: &Session) -> bool {
+fn need_bitcode_in_object(tcx: TyCtxt<'_>) -> bool {
+    let sess = tcx.sess;
     let requested_for_rlib = sess.opts.cg.embed_bitcode
-        && sess.crate_types().contains(&CrateType::Rlib)
+        && tcx.crate_types().contains(&CrateType::Rlib)
         && sess.opts.output_types.contains_key(&OutputType::Exe);
     let forced_by_target = sess.target.forces_embed_bitcode;
     requested_for_rlib || forced_by_target
@@ -450,11 +452,11 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
     let crate_info = CrateInfo::new(tcx, target_cpu);
 
     let regular_config =
-        ModuleConfig::new(ModuleKind::Regular, sess, no_builtins, is_compiler_builtins);
+        ModuleConfig::new(ModuleKind::Regular, tcx, no_builtins, is_compiler_builtins);
     let metadata_config =
-        ModuleConfig::new(ModuleKind::Metadata, sess, no_builtins, is_compiler_builtins);
+        ModuleConfig::new(ModuleKind::Metadata, tcx, no_builtins, is_compiler_builtins);
     let allocator_config =
-        ModuleConfig::new(ModuleKind::Allocator, sess, no_builtins, is_compiler_builtins);
+        ModuleConfig::new(ModuleKind::Allocator, tcx, no_builtins, is_compiler_builtins);
 
     let (shared_emitter, shared_emitter_main) = SharedEmitter::new();
     let (codegen_worker_send, codegen_worker_receive) = channel();
@@ -1092,7 +1094,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
     };
 
     let cgcx = CodegenContext::<B> {
-        crate_types: sess.crate_types().to_vec(),
+        crate_types: tcx.crate_types().to_vec(),
         each_linked_rlib_for_lto,
         lto: sess.lto(),
         fewer_names: sess.fewer_names(),
@@ -2063,7 +2065,7 @@ fn msvc_imps_needed(tcx: TyCtxt<'_>) -> bool {
     );
 
     tcx.sess.target.is_like_windows &&
-        tcx.sess.crate_types().iter().any(|ct| *ct == CrateType::Rlib) &&
+        tcx.crate_types().iter().any(|ct| *ct == CrateType::Rlib) &&
     // ThinLTO can't handle this workaround in all cases, so we don't
     // emit the `__imp_` symbols. Instead we make them unnecessary by disallowing
     // dynamic linking when linker plugin LTO is enabled.
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 4819ab22723..aa003e4e898 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -779,18 +779,13 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
 
 impl CrateInfo {
     pub fn new(tcx: TyCtxt<'_>, target_cpu: String) -> CrateInfo {
-        let exported_symbols = tcx
-            .sess
-            .crate_types()
+        let crate_types = tcx.crate_types().to_vec();
+        let exported_symbols = crate_types
             .iter()
             .map(|&c| (c, crate::back::linker::exported_symbols(tcx, c)))
             .collect();
-        let linked_symbols = tcx
-            .sess
-            .crate_types()
-            .iter()
-            .map(|&c| (c, crate::back::linker::linked_symbols(tcx, c)))
-            .collect();
+        let linked_symbols =
+            crate_types.iter().map(|&c| (c, crate::back::linker::linked_symbols(tcx, c))).collect();
         let local_crate_name = tcx.crate_name(LOCAL_CRATE);
         let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
         let subsystem = attr::first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem);
@@ -829,6 +824,7 @@ impl CrateInfo {
 
         let mut info = CrateInfo {
             target_cpu,
+            crate_types,
             exported_symbols,
             linked_symbols,
             local_crate_name,
@@ -916,7 +912,7 @@ impl CrateInfo {
                 });
         }
 
-        let embed_visualizers = tcx.sess.crate_types().iter().any(|&crate_type| match crate_type {
+        let embed_visualizers = tcx.crate_types().iter().any(|&crate_type| match crate_type {
             CrateType::Executable | CrateType::Dylib | CrateType::Cdylib => {
                 // These are crate types for which we invoke the linker and can embed
                 // NatVis visualizers.
@@ -1013,7 +1009,7 @@ fn determine_cgu_reuse<'tcx>(tcx: TyCtxt<'tcx>, cgu: &CodegenUnit<'tcx>) -> CguR
         match compute_per_cgu_lto_type(
             &tcx.sess.lto(),
             &tcx.sess.opts,
-            &tcx.sess.crate_types(),
+            tcx.crate_types(),
             ModuleKind::Regular,
         ) {
             ComputedLtoType::No => CguReuse::PostLto,
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index be4c81638d6..f577f653ccd 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -150,6 +150,7 @@ impl From<&cstore::NativeLib> for NativeLib {
 #[derive(Debug, Encodable, Decodable)]
 pub struct CrateInfo {
     pub target_cpu: String,
+    pub crate_types: Vec<CrateType>,
     pub exported_symbols: FxHashMap<CrateType, Vec<String>>,
     pub linked_symbols: FxHashMap<CrateType, Vec<(String, SymbolExportKind)>>,
     pub local_crate_name: Symbol,
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index ec77569d4b8..7bbed0877f0 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -653,8 +653,6 @@ fn show_md_content_with_pager(content: &str, color: ColorConfig) {
 pub fn try_process_rlink(sess: &Session, compiler: &interface::Compiler) -> Compilation {
     if sess.opts.unstable_opts.link_only {
         if let Input::File(file) = &sess.io.input {
-            // FIXME: #![crate_type] and #![crate_name] support not implemented yet
-            sess.init_crate_types(collect_crate_types(sess, &[]));
             let outputs = compiler.build_output_filenames(sess, &[]);
             let rlink_data = fs::read(file).unwrap_or_else(|err| {
                 sess.emit_fatal(RlinkUnableToRead { err });
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 92a91766d91..6340f1dcca1 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1843,7 +1843,7 @@ impl Expr<'_> {
                 .iter()
                 .map(|field| field.expr)
                 .chain(init.into_iter())
-                .all(|e| e.can_have_side_effects()),
+                .any(|e| e.can_have_side_effects()),
 
             ExprKind::Array(args)
             | ExprKind::Tup(args)
@@ -1857,7 +1857,7 @@ impl Expr<'_> {
                     ..
                 },
                 args,
-            ) => args.iter().all(|arg| arg.can_have_side_effects()),
+            ) => args.iter().any(|arg| arg.can_have_side_effects()),
             ExprKind::If(..)
             | ExprKind::Match(..)
             | ExprKind::MethodCall(..)
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index a8c66ff9001..044fb405e32 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -1,7 +1,7 @@
 use super::potentially_plural_count;
 use crate::errors::LifetimesOrBoundsMismatchOnTrait;
 use hir::def_id::{DefId, LocalDefId};
-use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
 use rustc_errors::{
     pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed, MultiSpan,
 };
@@ -265,7 +265,6 @@ fn compare_method_predicate_entailment<'tcx>(
         infer::HigherRankedType,
         tcx.fn_sig(impl_m.def_id).instantiate_identity(),
     );
-    let unnormalized_impl_fty = Ty::new_fn_ptr(tcx, ty::Binder::dummy(unnormalized_impl_sig));
 
     let norm_cause = ObligationCause::misc(impl_m_span, impl_m_def_id);
     let impl_sig = ocx.normalize(&norm_cause, param_env, unnormalized_impl_sig);
@@ -309,16 +308,44 @@ fn compare_method_predicate_entailment<'tcx>(
     }
 
     if check_implied_wf == CheckImpliedWfMode::Check && !(impl_sig, trait_sig).references_error() {
-        // We need to check that the impl's args are well-formed given
-        // the hybrid param-env (impl + trait method where-clauses).
-        ocx.register_obligation(traits::Obligation::new(
-            infcx.tcx,
-            ObligationCause::dummy(),
-            param_env,
-            ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
-                unnormalized_impl_fty.into(),
-            ))),
-        ));
+        // See #108544. Annoying, we can end up in cases where, because of winnowing,
+        // we pick param env candidates over a more general impl, leading to more
+        // stricter lifetime requirements than we would otherwise need. This can
+        // trigger the lint. Instead, let's only consider type outlives and
+        // region outlives obligations.
+        //
+        // FIXME(-Ztrait-solver=next): Try removing this hack again once
+        // the new solver is stable.
+        let mut wf_args: smallvec::SmallVec<[_; 4]> =
+            unnormalized_impl_sig.inputs_and_output.iter().map(|ty| ty.into()).collect();
+        // Annoyingly, asking for the WF predicates of an array (with an unevaluated const (only?))
+        // will give back the well-formed predicate of the same array.
+        let mut wf_args_seen: FxHashSet<_> = wf_args.iter().copied().collect();
+        while let Some(arg) = wf_args.pop() {
+            let Some(obligations) = rustc_trait_selection::traits::wf::obligations(
+                infcx,
+                param_env,
+                impl_m_def_id,
+                0,
+                arg,
+                impl_m_span,
+            ) else {
+                continue;
+            };
+            for obligation in obligations {
+                match obligation.predicate.kind().skip_binder() {
+                    ty::PredicateKind::Clause(
+                        ty::ClauseKind::RegionOutlives(..) | ty::ClauseKind::TypeOutlives(..),
+                    ) => ocx.register_obligation(obligation),
+                    ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
+                        if wf_args_seen.insert(arg) {
+                            wf_args.push(arg)
+                        }
+                    }
+                    _ => {}
+                }
+            }
+        }
     }
 
     // Check that all obligations are satisfied by the implementation's
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index ba00954db91..dd79d1afc62 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -645,18 +645,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
             }
             hir::ExprKind::Call(ref inner_callee, _) => {
-                // If the call spans more than one line and the callee kind is
-                // itself another `ExprCall`, that's a clue that we might just be
-                // missing a semicolon (Issue #51055)
-                let call_is_multiline = self.tcx.sess.source_map().is_multiline(call_expr.span);
-                if call_is_multiline {
-                    err.span_suggestion(
-                        callee_expr.span.shrink_to_hi(),
-                        "consider using a semicolon here",
-                        ";",
-                        Applicability::MaybeIncorrect,
-                    );
-                }
                 if let hir::ExprKind::Path(ref inner_qpath) = inner_callee.kind {
                     inner_callee_path = Some(inner_qpath);
                     self.typeck_results.borrow().qpath_res(inner_qpath, inner_callee.hir_id)
@@ -668,6 +656,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         if !self.maybe_suggest_bad_array_definition(&mut err, call_expr, callee_expr) {
+            // If the call spans more than one line and the callee kind is
+            // itself another `ExprCall`, that's a clue that we might just be
+            // missing a semicolon (#51055, #106515).
+            let call_is_multiline = self
+                .tcx
+                .sess
+                .source_map()
+                .is_multiline(call_expr.span.with_lo(callee_expr.span.hi()))
+                && call_expr.span.ctxt() == callee_expr.span.ctxt();
+            if call_is_multiline {
+                err.span_suggestion(
+                    callee_expr.span.shrink_to_hi(),
+                    "consider using a semicolon here to finish the statement",
+                    ";",
+                    Applicability::MaybeIncorrect,
+                );
+            }
             if let Some((maybe_def, output_ty, _)) = self.extract_callable_info(callee_ty)
                 && !self.type_is_sized_modulo_regions(self.param_env, output_ty)
             {
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index d9b17a2e2b7..1cfdc5b9e7f 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -510,9 +510,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         success(adjustments, ty, obligations)
     }
 
-    // &[T; n] or &mut [T; n] -> &[T]
-    // or &mut [T; n] -> &mut [T]
-    // or &Concrete -> &Trait, etc.
+    /// Performs [unsized coercion] by emulating a fulfillment loop on a
+    /// `CoerceUnsized` goal until all `CoerceUnsized` and `Unsize` goals
+    /// are successfully selected.
+    ///
+    /// [unsized coercion](https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions)
     #[instrument(skip(self), level = "debug")]
     fn coerce_unsized(&self, mut source: Ty<'tcx>, mut target: Ty<'tcx>) -> CoerceResult<'tcx> {
         source = self.shallow_resolve(source);
@@ -1039,6 +1041,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Returns false if the coercion creates any obligations that result in
     /// errors.
     pub fn can_coerce(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> bool {
+        // FIXME(-Ztrait-solver=next): We need to structurally resolve both types here.
         let source = self.resolve_vars_with_obligations(expr_ty);
         debug!("coercion::can_with_predicates({:?} -> {:?})", source, target);
 
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 48383bd90fe..b05cef56ad2 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -260,7 +260,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         ));
         let expr = expr.peel_drop_temps();
         let cause = self.misc(expr.span);
-        let expr_ty = self.resolve_vars_with_obligations(checked_ty);
+        let expr_ty = self.resolve_vars_if_possible(checked_ty);
         let mut err = self.err_ctxt().report_mismatched_types(&cause, expected, expr_ty, e);
 
         let is_insufficiently_polymorphic =
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 8fad0a6c9e4..28fe2e062e5 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -85,16 +85,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// to get more type information.
     // FIXME(-Ztrait-solver=next): A lot of the calls to this method should
     // probably be `try_structurally_resolve_type` or `structurally_resolve_type` instead.
-    pub(in super::super) fn resolve_vars_with_obligations(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        self.resolve_vars_with_obligations_and_mutate_fulfillment(ty, |_| {})
-    }
-
-    #[instrument(skip(self, mutate_fulfillment_errors), level = "debug", ret)]
-    pub(in super::super) fn resolve_vars_with_obligations_and_mutate_fulfillment(
-        &self,
-        mut ty: Ty<'tcx>,
-        mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
-    ) -> Ty<'tcx> {
+    #[instrument(skip(self), level = "debug", ret)]
+    pub(in super::super) fn resolve_vars_with_obligations(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
         // No Infer()? Nothing needs doing.
         if !ty.has_non_region_infer() {
             debug!("no inference var, nothing needs doing");
@@ -112,7 +104,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // possible. This can help substantially when there are
         // indirect dependencies that don't seem worth tracking
         // precisely.
-        self.select_obligations_where_possible(mutate_fulfillment_errors);
+        self.select_obligations_where_possible(|_| {});
         self.resolve_vars_if_possible(ty)
     }
 
@@ -626,8 +618,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         match *self_ty.kind() {
             ty::Infer(ty::TyVar(found_vid)) => {
-                // FIXME: consider using `sub_root_var` here so we
-                // can see through subtyping.
                 let found_vid = self.root_var(found_vid);
                 debug!("self_type_matches_expected_vid - found_vid={:?}", found_vid);
                 expected_vid == found_vid
@@ -642,8 +632,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self_ty: ty::TyVid,
     ) -> impl DoubleEndedIterator<Item = traits::PredicateObligation<'tcx>> + Captures<'tcx> + 'b
     {
-        // FIXME: consider using `sub_root_var` here so we
-        // can see through subtyping.
         let ty_var_root = self.root_var(self_ty);
         trace!("pending_obligations = {:#?}", self.fulfillment_cx.borrow().pending_obligations());
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 89bbb4c2203..48358e338da 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -950,7 +950,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if !expected.is_unit() {
             return;
         }
-        let found = self.resolve_vars_with_obligations(found);
+        let found = self.resolve_vars_if_possible(found);
 
         let in_loop = self.is_loop(id)
             || self
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 2d64c5667a8..a0d31d3a22c 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -2994,7 +2994,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // This occurs for UFCS desugaring of `T::method`, where there is no
         // receiver expression for the method call, and thus no autoderef.
         if let SelfSource::QPath(_) = source {
-            return is_local(self.resolve_vars_with_obligations(rcvr_ty));
+            return is_local(rcvr_ty);
         }
 
         self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 07c559354c0..def9fdcd3c7 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -12,7 +12,7 @@ use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
 use rustc_errors::PResult;
 use rustc_expand::base::{ExtCtxt, LintStoreExpand};
 use rustc_fs_util::try_canonicalize;
-use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE};
 use rustc_lint::{unerased_lint_store, BufferedEarlyLint, EarlyCheckNode, LintStore};
 use rustc_metadata::creader::CStore;
 use rustc_middle::arena::Arena;
@@ -248,7 +248,7 @@ fn configure_and_expand(
         rustc_ast_passes::ast_validation::check_crate(sess, &krate, resolver.lint_buffer())
     });
 
-    let crate_types = sess.crate_types();
+    let crate_types = tcx.crate_types();
     let is_executable_crate = crate_types.contains(&CrateType::Executable);
     let is_proc_macro_crate = crate_types.contains(&CrateType::ProcMacro);
 
@@ -340,11 +340,12 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) {
 
 // Returns all the paths that correspond to generated files.
 fn generated_output_paths(
-    sess: &Session,
+    tcx: TyCtxt<'_>,
     outputs: &OutputFilenames,
     exact_name: bool,
     crate_name: Symbol,
 ) -> Vec<PathBuf> {
+    let sess = tcx.sess;
     let mut out_filenames = Vec::new();
     for output_type in sess.opts.output_types.keys() {
         let out_filename = outputs.path(*output_type);
@@ -353,7 +354,7 @@ fn generated_output_paths(
             // If the filename has been overridden using `-o`, it will not be modified
             // by appending `.rlib`, `.exe`, etc., so we can skip this transformation.
             OutputType::Exe if !exact_name => {
-                for crate_type in sess.crate_types().iter() {
+                for crate_type in tcx.crate_types().iter() {
                     let p = filename_for_input(sess, *crate_type, crate_name, outputs);
                     out_filenames.push(p.as_path().to_path_buf());
                 }
@@ -586,7 +587,7 @@ fn output_filenames(tcx: TyCtxt<'_>, (): ()) -> Arc<OutputFilenames> {
     let outputs = util::build_output_filenames(&krate.attrs, sess);
 
     let output_paths =
-        generated_output_paths(sess, &outputs, sess.io.output_file.is_some(), crate_name);
+        generated_output_paths(tcx, &outputs, sess.io.output_file.is_some(), crate_name);
 
     // Ensure the source file isn't accidentally overwritten during compilation.
     if let Some(ref input_path) = sess.io.input.opt_path() {
@@ -664,6 +665,8 @@ pub static DEFAULT_EXTERN_QUERY_PROVIDERS: LazyLock<ExternProviders> = LazyLock:
 
 pub fn create_global_ctxt<'tcx>(
     compiler: &'tcx Compiler,
+    crate_types: Vec<CrateType>,
+    stable_crate_id: StableCrateId,
     lint_store: Lrc<LintStore>,
     dep_graph: DepGraph,
     untracked: Untracked,
@@ -696,6 +699,8 @@ pub fn create_global_ctxt<'tcx>(
         gcx_cell.get_or_init(move || {
             TyCtxt::create_global_ctxt(
                 sess,
+                crate_types,
+                stable_crate_id,
                 lint_store,
                 arena,
                 hir_arena,
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index b805ff09ee4..7687e83da76 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -234,13 +234,13 @@ impl<'tcx> Queries<'tcx> {
             debug_assert_eq!(_id, CRATE_DEF_ID);
             let untracked = Untracked { cstore, source_span, definitions };
 
-            // FIXME: Move these fields from session to tcx and make them immutable.
-            sess.init_crate_types(crate_types);
-            sess.stable_crate_id.set(stable_crate_id).expect("not yet initialized");
+            // FIXME: Move features from session to tcx and make them immutable.
             sess.init_features(rustc_expand::config::features(sess, &pre_configured_attrs));
 
             let qcx = passes::create_global_ctxt(
                 self.compiler,
+                crate_types,
+                stable_crate_id,
                 lint_store,
                 self.dep_graph(dep_graph_future),
                 untracked,
@@ -320,7 +320,7 @@ impl<'tcx> Queries<'tcx> {
 
         let (crate_hash, prepare_outputs, dep_graph) = self.global_ctxt()?.enter(|tcx| {
             (
-                if tcx.sess.needs_crate_hash() { Some(tcx.crate_hash(LOCAL_CRATE)) } else { None },
+                if tcx.needs_crate_hash() { Some(tcx.crate_hash(LOCAL_CRATE)) } else { None },
                 tcx.output_filenames(()).clone(),
                 tcx.dep_graph.clone(),
             )
diff --git a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
index 80b6c0fb439..d61ec0b641c 100644
--- a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
@@ -103,12 +103,20 @@ fromRust(LLVMRustCounterExprKind Kind) {
 }
 
 extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer(
-    const char* const Filenames[],
+    const char *const Filenames[],
     size_t FilenamesLen,
+    const size_t *const Lengths,
+    size_t LengthsLen,
     RustStringRef BufferOut) {
+  if (FilenamesLen != LengthsLen) {
+    report_fatal_error(
+        "Mismatched lengths in LLVMRustCoverageWriteFilenamesSectionToBuffer");
+  }
+
   SmallVector<std::string,32> FilenameRefs;
+  FilenameRefs.reserve(FilenamesLen);
   for (size_t i = 0; i < FilenamesLen; i++) {
-    FilenameRefs.push_back(std::string(Filenames[i]));
+    FilenameRefs.emplace_back(Filenames[i], Lengths[i]);
   }
   auto FilenamesWriter =
       coverage::CoverageFilenamesSectionWriter(ArrayRef<std::string>(FilenameRefs));
@@ -153,8 +161,11 @@ extern "C" void LLVMRustCoverageWriteMappingToBuffer(
   CoverageMappingWriter.write(OS);
 }
 
-extern "C" LLVMValueRef LLVMRustCoverageCreatePGOFuncNameVar(LLVMValueRef F, const char *FuncName) {
-  StringRef FuncNameRef(FuncName);
+extern "C" LLVMValueRef LLVMRustCoverageCreatePGOFuncNameVar(
+    LLVMValueRef F,
+    const char *FuncName,
+    size_t FuncNameLen) {
+  StringRef FuncNameRef(FuncName, FuncNameLen);
   return wrap(createPGOFuncNameVar(*cast<Function>(unwrap(F)), FuncNameRef));
 }
 
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index 7c9aaeb5762..3c76f9a8e52 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -545,7 +545,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
                 name,
                 // The all loop is because `--crate-type=rlib --crate-type=rlib` is
                 // legal and produces both inside this type.
-                self.sess.crate_types().iter().all(|c| *c == CrateType::Rlib),
+                self.tcx.crate_types().iter().all(|c| *c == CrateType::Rlib),
                 hash,
                 extra_filename,
                 false, // is_host
@@ -689,7 +689,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
     fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
         // If we're only compiling an rlib, then there's no need to select a
         // panic runtime, so we just skip this section entirely.
-        let any_non_rlib = self.sess.crate_types().iter().any(|ct| *ct != CrateType::Rlib);
+        let any_non_rlib = self.tcx.crate_types().iter().any(|ct| *ct != CrateType::Rlib);
         if !any_non_rlib {
             info!("panic runtime injection skipped, only generating rlib");
             return;
@@ -818,7 +818,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
         // At this point we've determined that we need an allocator. Let's see
         // if our compilation session actually needs an allocator based on what
         // we're emitting.
-        let all_rlib = self.sess.crate_types().iter().all(|ct| matches!(*ct, CrateType::Rlib));
+        let all_rlib = self.tcx.crate_types().iter().all(|ct| matches!(*ct, CrateType::Rlib));
         if all_rlib {
             return;
         }
diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs
index 72b208a7132..783d35ac7e6 100644
--- a/compiler/rustc_metadata/src/dependency_format.rs
+++ b/compiler/rustc_metadata/src/dependency_format.rs
@@ -66,8 +66,7 @@ use rustc_session::cstore::CrateDepKind;
 use rustc_session::cstore::LinkagePreference::{self, RequireDynamic, RequireStatic};
 
 pub(crate) fn calculate(tcx: TyCtxt<'_>) -> Dependencies {
-    tcx.sess
-        .crate_types()
+    tcx.crate_types()
         .iter()
         .map(|&ty| {
             let linkage = calculate_type(tcx, ty);
diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs
index 69a77e82f98..2a9662b809a 100644
--- a/compiler/rustc_metadata/src/fs.rs
+++ b/compiler/rustc_metadata/src/fs.rs
@@ -56,7 +56,7 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) {
 
     // Always create a file at `metadata_filename`, even if we have nothing to write to it.
     // This simplifies the creation of the output `out_filename` when requested.
-    let metadata_kind = tcx.sess.metadata_kind();
+    let metadata_kind = tcx.metadata_kind();
     match metadata_kind {
         MetadataKind::None => {
             std::fs::File::create(&metadata_filename).unwrap_or_else(|err| {
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index ca5043cc263..098c411c8d6 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -52,10 +52,11 @@ fn find_bundled_library(
     verbatim: Option<bool>,
     kind: NativeLibKind,
     has_cfg: bool,
-    sess: &Session,
+    tcx: TyCtxt<'_>,
 ) -> Option<Symbol> {
+    let sess = tcx.sess;
     if let NativeLibKind::Static { bundle: Some(true) | None, whole_archive } = kind
-        && sess.crate_types().iter().any(|t| matches!(t, &CrateType::Rlib | CrateType::Staticlib))
+        && tcx.crate_types().iter().any(|t| matches!(t, &CrateType::Rlib | CrateType::Staticlib))
         && (sess.opts.unstable_opts.packed_bundled_libs || has_cfg || whole_archive == Some(true))
     {
         let verbatim = verbatim.unwrap_or(false);
@@ -364,7 +365,7 @@ impl<'tcx> Collector<'tcx> {
             };
 
             let kind = kind.unwrap_or(NativeLibKind::Unspecified);
-            let filename = find_bundled_library(name, verbatim, kind, cfg.is_some(), sess);
+            let filename = find_bundled_library(name, verbatim, kind, cfg.is_some(), self.tcx);
             self.libs.push(NativeLib {
                 name,
                 filename,
@@ -442,9 +443,13 @@ impl<'tcx> Collector<'tcx> {
                 // Add if not found
                 let new_name: Option<&str> = passed_lib.new_name.as_deref();
                 let name = Symbol::intern(new_name.unwrap_or(&passed_lib.name));
-                let sess = self.tcx.sess;
-                let filename =
-                    find_bundled_library(name, passed_lib.verbatim, passed_lib.kind, false, sess);
+                let filename = find_bundled_library(
+                    name,
+                    passed_lib.verbatim,
+                    passed_lib.kind,
+                    false,
+                    self.tcx,
+                );
                 self.libs.push(NativeLib {
                     name,
                     filename,
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index b34fead821f..be91ad4088a 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1741,7 +1741,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
     }
 
     fn encode_proc_macros(&mut self) -> Option<ProcMacroData> {
-        let is_proc_macro = self.tcx.sess.crate_types().contains(&CrateType::ProcMacro);
+        let is_proc_macro = self.tcx.crate_types().contains(&CrateType::ProcMacro);
         if is_proc_macro {
             let tcx = self.tcx;
             let hir = tcx.hir();
@@ -2204,7 +2204,7 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
         source_file_cache,
         interpret_allocs: Default::default(),
         required_source_files,
-        is_proc_macro: tcx.sess.crate_types().contains(&CrateType::ProcMacro),
+        is_proc_macro: tcx.crate_types().contains(&CrateType::ProcMacro),
         hygiene_ctxt: &hygiene_ctxt,
         symbol_table: Default::default(),
     };
diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs
index 4e242c684e3..06251bccc98 100644
--- a/compiler/rustc_middle/src/dep_graph/dep_node.rs
+++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs
@@ -60,7 +60,7 @@ use crate::mir::mono::MonoItem;
 use crate::ty::TyCtxt;
 
 use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use rustc_hir::definitions::DefPathHash;
 use rustc_hir::{HirId, ItemLocalId, OwnerId};
 use rustc_query_system::dep_graph::FingerprintStyle;
@@ -371,7 +371,7 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId {
     fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
         if tcx.fingerprint_style(dep_node.kind) == FingerprintStyle::HirId {
             let (local_hash, local_id) = Fingerprint::from(dep_node.hash).split();
-            let def_path_hash = DefPathHash::new(tcx.sess.local_stable_crate_id(), local_hash);
+            let def_path_hash = DefPathHash::new(tcx.stable_crate_id(LOCAL_CRATE), local_hash);
             let def_id = tcx
                 .def_path_hash_to_def_id(def_path_hash, &mut || {
                     panic!("Failed to extract HirId: {:?} {}", dep_node.kind, dep_node.hash)
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index fbc32263874..224f897492b 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -1210,7 +1210,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh {
             owner_spans.hash_stable(&mut hcx, &mut stable_hasher);
         }
         tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher);
-        tcx.sess.local_stable_crate_id().hash_stable(&mut hcx, &mut stable_hasher);
+        tcx.stable_crate_id(LOCAL_CRATE).hash_stable(&mut hcx, &mut stable_hasher);
         // Hash visibility information since it does not appear in HIR.
         resolutions.visibilities.hash_stable(&mut hcx, &mut stable_hasher);
         resolutions.has_pub_restricted.hash_stable(&mut hcx, &mut stable_hasher);
diff --git a/compiler/rustc_middle/src/middle/exported_symbols.rs b/compiler/rustc_middle/src/middle/exported_symbols.rs
index f19812619b2..e30b6b203d7 100644
--- a/compiler/rustc_middle/src/middle/exported_symbols.rs
+++ b/compiler/rustc_middle/src/middle/exported_symbols.rs
@@ -72,6 +72,6 @@ pub fn metadata_symbol_name(tcx: TyCtxt<'_>) -> String {
     format!(
         "rust_metadata_{}_{:08x}",
         tcx.crate_name(LOCAL_CRATE),
-        tcx.sess.local_stable_crate_id(),
+        tcx.stable_crate_id(LOCAL_CRATE),
     )
 }
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index ddb6cc15bc1..8fd980d5a9e 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -524,13 +524,13 @@ impl<'tcx> CodegenUnitNameBuilder<'tcx> {
             // local crate's ID. Otherwise there can be collisions between CGUs
             // instantiating stuff for upstream crates.
             let local_crate_id = if cnum != LOCAL_CRATE {
-                let local_stable_crate_id = tcx.sess.local_stable_crate_id();
+                let local_stable_crate_id = tcx.stable_crate_id(LOCAL_CRATE);
                 format!("-in-{}.{:08x}", tcx.crate_name(LOCAL_CRATE), local_stable_crate_id)
             } else {
                 String::new()
             };
 
-            let stable_crate_id = tcx.sess.local_stable_crate_id();
+            let stable_crate_id = tcx.stable_crate_id(LOCAL_CRATE);
             format!("{}.{:08x}{}", tcx.crate_name(cnum), stable_crate_id, local_crate_id)
         });
 
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 8ac1d02ce50..be839e03cff 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -59,8 +59,7 @@ use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
 use rustc_session::config::CrateType;
 use rustc_session::cstore::{CrateStoreDyn, Untracked};
 use rustc_session::lint::Lint;
-use rustc_session::Limit;
-use rustc_session::Session;
+use rustc_session::{Limit, MetadataKind, Session};
 use rustc_span::def_id::{DefPathHash, StableCrateId};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
@@ -527,6 +526,13 @@ pub struct GlobalCtxt<'tcx> {
     interners: CtxtInterners<'tcx>,
 
     pub sess: &'tcx Session,
+    crate_types: Vec<CrateType>,
+    /// The `stable_crate_id` is constructed out of the crate name and all the
+    /// `-C metadata` arguments passed to the compiler. Its value forms a unique
+    /// global identifier for the crate. It is used to allow multiple crates
+    /// with the same name to coexist. See the
+    /// `rustc_symbol_mangling` crate for more information.
+    stable_crate_id: StableCrateId,
 
     /// This only ever stores a `LintStore` but we don't want a dependency on that type here.
     ///
@@ -687,6 +693,8 @@ impl<'tcx> TyCtxt<'tcx> {
     /// has a valid reference to the context, to allow formatting values that need it.
     pub fn create_global_ctxt(
         s: &'tcx Session,
+        crate_types: Vec<CrateType>,
+        stable_crate_id: StableCrateId,
         lint_store: Lrc<dyn Any + sync::DynSend + sync::DynSync>,
         arena: &'tcx WorkerLocal<Arena<'tcx>>,
         hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
@@ -705,6 +713,8 @@ impl<'tcx> TyCtxt<'tcx> {
 
         GlobalCtxt {
             sess: s,
+            crate_types,
+            stable_crate_id,
             lint_store,
             arena,
             hir_arena,
@@ -801,9 +811,46 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     #[inline]
+    pub fn crate_types(self) -> &'tcx [CrateType] {
+        &self.crate_types
+    }
+
+    pub fn metadata_kind(self) -> MetadataKind {
+        self.crate_types()
+            .iter()
+            .map(|ty| match *ty {
+                CrateType::Executable | CrateType::Staticlib | CrateType::Cdylib => {
+                    MetadataKind::None
+                }
+                CrateType::Rlib => MetadataKind::Uncompressed,
+                CrateType::Dylib | CrateType::ProcMacro => MetadataKind::Compressed,
+            })
+            .max()
+            .unwrap_or(MetadataKind::None)
+    }
+
+    pub fn needs_metadata(self) -> bool {
+        self.metadata_kind() != MetadataKind::None
+    }
+
+    pub fn needs_crate_hash(self) -> bool {
+        // Why is the crate hash needed for these configurations?
+        // - debug_assertions: for the "fingerprint the result" check in
+        //   `rustc_query_system::query::plumbing::execute_job`.
+        // - incremental: for query lookups.
+        // - needs_metadata: for putting into crate metadata.
+        // - instrument_coverage: for putting into coverage data (see
+        //   `hash_mir_source`).
+        cfg!(debug_assertions)
+            || self.sess.opts.incremental.is_some()
+            || self.needs_metadata()
+            || self.sess.instrument_coverage()
+    }
+
+    #[inline]
     pub fn stable_crate_id(self, crate_num: CrateNum) -> StableCrateId {
         if crate_num == LOCAL_CRATE {
-            self.sess.local_stable_crate_id()
+            self.stable_crate_id
         } else {
             self.cstore_untracked().stable_crate_id(crate_num)
         }
@@ -813,7 +860,7 @@ impl<'tcx> TyCtxt<'tcx> {
     /// that the crate in question has already been loaded by the CrateStore.
     #[inline]
     pub fn stable_crate_id_to_crate_num(self, stable_crate_id: StableCrateId) -> CrateNum {
-        if stable_crate_id == self.sess.local_stable_crate_id() {
+        if stable_crate_id == self.stable_crate_id(LOCAL_CRATE) {
             LOCAL_CRATE
         } else {
             self.cstore_untracked().stable_crate_id_to_crate_num(stable_crate_id)
@@ -830,7 +877,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
         // If this is a DefPathHash from the local crate, we can look up the
         // DefId in the tcx's `Definitions`.
-        if stable_crate_id == self.sess.local_stable_crate_id() {
+        if stable_crate_id == self.stable_crate_id(LOCAL_CRATE) {
             self.untracked.definitions.read().local_def_path_hash_to_def_id(hash, err).to_def_id()
         } else {
             // If this is a DefPathHash from an upstream crate, let the CrateStore map
@@ -847,7 +894,7 @@ impl<'tcx> TyCtxt<'tcx> {
         // statements within the query system and we'd run into endless
         // recursion otherwise.
         let (crate_name, stable_crate_id) = if def_id.is_local() {
-            (self.crate_name(LOCAL_CRATE), self.sess.local_stable_crate_id())
+            (self.crate_name(LOCAL_CRATE), self.stable_crate_id(LOCAL_CRATE))
         } else {
             let cstore = &*self.cstore_untracked();
             (cstore.crate_name(def_id.krate), cstore.stable_crate_id(def_id.krate))
@@ -986,7 +1033,7 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn local_crate_exports_generics(self) -> bool {
         debug_assert!(self.sess.opts.share_generics());
 
-        self.sess.crate_types().iter().any(|crate_type| {
+        self.crate_types().iter().any(|crate_type| {
             match crate_type {
                 CrateType::Executable
                 | CrateType::Staticlib
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index ffd8f77b78b..6a29159e917 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -31,7 +31,7 @@ struct EntryContext<'tcx> {
 }
 
 fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> {
-    let any_exe = tcx.sess.crate_types().iter().any(|ty| *ty == CrateType::Executable);
+    let any_exe = tcx.crate_types().iter().any(|ty| *ty == CrateType::Executable);
     if !any_exe {
         // No need to find a main function.
         return None;
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index 7dec5b0acc8..f9d34ea71ba 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -364,10 +364,10 @@ fn has_custom_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
 fn reachable_set(tcx: TyCtxt<'_>, (): ()) -> LocalDefIdSet {
     let effective_visibilities = &tcx.effective_visibilities(());
 
-    let any_library =
-        tcx.sess.crate_types().iter().any(|ty| {
-            *ty == CrateType::Rlib || *ty == CrateType::Dylib || *ty == CrateType::ProcMacro
-        });
+    let any_library = tcx
+        .crate_types()
+        .iter()
+        .any(|ty| *ty == CrateType::Rlib || *ty == CrateType::Dylib || *ty == CrateType::ProcMacro);
     let mut reachable_context = ReachableContext {
         tcx,
         maybe_typeck_results: None,
diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs
index fc6372cf99e..75e071f1fcf 100644
--- a/compiler/rustc_passes/src/weak_lang_items.rs
+++ b/compiler/rustc_passes/src/weak_lang_items.rs
@@ -43,7 +43,7 @@ pub fn check_crate(tcx: TyCtxt<'_>, items: &mut lang_items::LanguageItems) {
 fn verify(tcx: TyCtxt<'_>, items: &lang_items::LanguageItems) {
     // We only need to check for the presence of weak lang items if we're
     // emitting something that's not an rlib.
-    let needs_check = tcx.sess.crate_types().iter().any(|kind| match *kind {
+    let needs_check = tcx.crate_types().iter().any(|kind| match *kind {
         CrateType::Dylib
         | CrateType::ProcMacro
         | CrateType::Cdylib
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 6007295b930..c87db96a5dd 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -4374,7 +4374,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                 if let Some(res) = res
                     && let Some(def_id) = res.opt_def_id()
                     && !def_id.is_local()
-                    && self.r.tcx.sess.crate_types().contains(&CrateType::ProcMacro)
+                    && self.r.tcx.crate_types().contains(&CrateType::ProcMacro)
                     && matches!(self.r.tcx.sess.opts.resolve_doc_links, ResolveDocLinks::ExportedMetadata) {
                     // Encoding foreign def ids in proc macro crate metadata will ICE.
                     return None;
@@ -4389,7 +4389,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         match self.r.tcx.sess.opts.resolve_doc_links {
             ResolveDocLinks::None => return,
             ResolveDocLinks::ExportedMetadata
-                if !self.r.tcx.sess.crate_types().iter().copied().any(CrateType::has_metadata)
+                if !self.r.tcx.crate_types().iter().copied().any(CrateType::has_metadata)
                     || !maybe_exported.eval(self.r) =>
             {
                 return;
@@ -4448,7 +4448,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                         .into_iter()
                         .filter_map(|tr| {
                             if !tr.def_id.is_local()
-                                && self.r.tcx.sess.crate_types().contains(&CrateType::ProcMacro)
+                                && self.r.tcx.crate_types().contains(&CrateType::ProcMacro)
                                 && matches!(
                                     self.r.tcx.sess.opts.resolve_doc_links,
                                     ResolveDocLinks::ExportedMetadata
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index b25a6299125..5d7572f65a5 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -152,14 +152,6 @@ pub struct Session {
     /// Input, input file path and output file path to this compilation process.
     pub io: CompilerIO,
 
-    crate_types: OnceCell<Vec<CrateType>>,
-    /// The `stable_crate_id` is constructed out of the crate name and all the
-    /// `-C metadata` arguments passed to the compiler. Its value forms a unique
-    /// global identifier for the crate. It is used to allow multiple crates
-    /// with the same name to coexist. See the
-    /// `rustc_symbol_mangling` crate for more information.
-    pub stable_crate_id: OnceCell<StableCrateId>,
-
     features: OnceCell<rustc_feature::Features>,
 
     incr_comp_session: OneThread<RefCell<IncrCompSession>>,
@@ -310,55 +302,11 @@ impl Session {
         self.parse_sess.span_diagnostic.emit_future_breakage_report(diags);
     }
 
-    pub fn local_stable_crate_id(&self) -> StableCrateId {
-        self.stable_crate_id.get().copied().unwrap()
-    }
-
-    pub fn crate_types(&self) -> &[CrateType] {
-        self.crate_types.get().unwrap().as_slice()
-    }
-
     /// Returns true if the crate is a testing one.
     pub fn is_test_crate(&self) -> bool {
         self.opts.test
     }
 
-    pub fn needs_crate_hash(&self) -> bool {
-        // Why is the crate hash needed for these configurations?
-        // - debug_assertions: for the "fingerprint the result" check in
-        //   `rustc_query_system::query::plumbing::execute_job`.
-        // - incremental: for query lookups.
-        // - needs_metadata: for putting into crate metadata.
-        // - instrument_coverage: for putting into coverage data (see
-        //   `hash_mir_source`).
-        cfg!(debug_assertions)
-            || self.opts.incremental.is_some()
-            || self.needs_metadata()
-            || self.instrument_coverage()
-    }
-
-    pub fn metadata_kind(&self) -> MetadataKind {
-        self.crate_types()
-            .iter()
-            .map(|ty| match *ty {
-                CrateType::Executable | CrateType::Staticlib | CrateType::Cdylib => {
-                    MetadataKind::None
-                }
-                CrateType::Rlib => MetadataKind::Uncompressed,
-                CrateType::Dylib | CrateType::ProcMacro => MetadataKind::Compressed,
-            })
-            .max()
-            .unwrap_or(MetadataKind::None)
-    }
-
-    pub fn needs_metadata(&self) -> bool {
-        self.metadata_kind() != MetadataKind::None
-    }
-
-    pub fn init_crate_types(&self, crate_types: Vec<CrateType>) {
-        self.crate_types.set(crate_types).expect("`crate_types` was initialized twice")
-    }
-
     #[rustc_lint_diagnostics]
     #[track_caller]
     pub fn struct_span_warn<S: Into<MultiSpan>>(
@@ -1516,8 +1464,6 @@ pub fn build_session(
         parse_sess,
         sysroot,
         io,
-        crate_types: OnceCell::new(),
-        stable_crate_id: OnceCell::new(),
         features: OnceCell::new(),
         incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)),
         cgu_reuse_tracker,
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index 0d9157940f8..078ff67446f 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -63,6 +63,10 @@ pub fn trait_def(did: DefId) -> stable_mir::ty::TraitDef {
     with_tables(|t| t.trait_def(did))
 }
 
+pub fn impl_def(did: DefId) -> stable_mir::ty::ImplDef {
+    with_tables(|t| t.impl_def(did))
+}
+
 impl<'tcx> Tables<'tcx> {
     pub fn item_def_id(&self, item: &stable_mir::CrateItem) -> DefId {
         self.def_ids[item.0]
@@ -72,6 +76,10 @@ impl<'tcx> Tables<'tcx> {
         self.def_ids[trait_def.0]
     }
 
+    pub fn impl_trait_def_id(&self, impl_def: &stable_mir::ty::ImplDef) -> DefId {
+        self.def_ids[impl_def.0]
+    }
+
     pub fn crate_item(&mut self, did: DefId) -> stable_mir::CrateItem {
         stable_mir::CrateItem(self.create_def_id(did))
     }
@@ -116,6 +124,10 @@ impl<'tcx> Tables<'tcx> {
         stable_mir::ty::ConstDef(self.create_def_id(did))
     }
 
+    pub fn impl_def(&mut self, did: DefId) -> stable_mir::ty::ImplDef {
+        stable_mir::ty::ImplDef(self.create_def_id(did))
+    }
+
     fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId {
         // FIXME: this becomes inefficient when we have too many ids
         for (i, &d) in self.def_ids.iter().enumerate() {
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index f782138f870..6ab473c3b54 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -59,6 +59,20 @@ impl<'tcx> Context for Tables<'tcx> {
         trait_def.stable(self)
     }
 
+    fn all_trait_impls(&mut self) -> stable_mir::ImplTraitDecls {
+        self.tcx
+            .trait_impls_in_crate(LOCAL_CRATE)
+            .iter()
+            .map(|impl_def_id| self.impl_def(*impl_def_id))
+            .collect()
+    }
+
+    fn trait_impl(&mut self, impl_def: &stable_mir::ty::ImplDef) -> stable_mir::ty::ImplTrait {
+        let def_id = self.impl_trait_def_id(impl_def);
+        let impl_trait = self.tcx.impl_trait_ref(def_id).unwrap();
+        impl_trait.stable(self)
+    }
+
     fn mir_body(&mut self, item: &stable_mir::CrateItem) -> stable_mir::mir::Body {
         let def_id = self.item_def_id(item);
         let mir = self.tcx.optimized_mir(def_id);
@@ -840,6 +854,19 @@ where
     }
 }
 
+impl<'tcx, S, V> Stable<'tcx> for ty::EarlyBinder<S>
+where
+    S: Stable<'tcx, T = V>,
+{
+    type T = stable_mir::ty::EarlyBinder<V>;
+
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        use stable_mir::ty::EarlyBinder;
+
+        EarlyBinder { value: self.as_ref().skip_binder().stable(tables) }
+    }
+}
+
 impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> {
     type T = stable_mir::ty::FnSig;
     fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
@@ -1154,3 +1181,12 @@ impl<'tcx> Stable<'tcx> for rustc_middle::mir::ConstantKind<'tcx> {
         }
     }
 }
+
+impl<'tcx> Stable<'tcx> for ty::TraitRef<'tcx> {
+    type T = stable_mir::ty::TraitRef;
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        use stable_mir::ty::TraitRef;
+
+        TraitRef { def_id: rustc_internal::trait_def(self.def_id), args: self.args.stable(tables) }
+    }
+}
diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs
index d93f25249b9..a74975cefc2 100644
--- a/compiler/rustc_smir/src/stable_mir/mod.rs
+++ b/compiler/rustc_smir/src/stable_mir/mod.rs
@@ -15,7 +15,7 @@ use std::cell::Cell;
 
 use crate::rustc_smir::Tables;
 
-use self::ty::{TraitDecl, TraitDef, Ty, TyKind};
+use self::ty::{ImplDef, ImplTrait, TraitDecl, TraitDef, Ty, TyKind};
 
 pub mod mir;
 pub mod ty;
@@ -32,9 +32,12 @@ pub type DefId = usize;
 /// A list of crate items.
 pub type CrateItems = Vec<CrateItem>;
 
-/// A list of crate items.
+/// A list of trait decls.
 pub type TraitDecls = Vec<TraitDef>;
 
+/// A list of impl trait decls.
+pub type ImplTraitDecls = Vec<ImplDef>;
+
 /// Holds information about a crate.
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct Crate {
@@ -89,6 +92,8 @@ pub trait Context {
     fn mir_body(&mut self, item: &CrateItem) -> mir::Body;
     fn all_trait_decls(&mut self) -> TraitDecls;
     fn trait_decl(&mut self, trait_def: &TraitDef) -> TraitDecl;
+    fn all_trait_impls(&mut self) -> ImplTraitDecls;
+    fn trait_impl(&mut self, trait_impl: &ImplDef) -> ImplTrait;
     /// Get information about the local crate.
     fn local_crate(&self) -> Crate;
     /// Retrieve a list of all external crates.
diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs
index e83ca88da1b..8a23af75749 100644
--- a/compiler/rustc_smir/src/stable_mir/ty.rs
+++ b/compiler/rustc_smir/src/stable_mir/ty.rs
@@ -119,6 +119,15 @@ impl TraitDef {
     }
 }
 
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct ImplDef(pub(crate) DefId);
+
+impl ImplDef {
+    pub fn trait_impl(&self) -> ImplTrait {
+        with(|cx| cx.trait_impl(self))
+    }
+}
+
 #[derive(Clone, Debug)]
 pub struct GenericArgs(pub Vec<GenericArgKind>);
 
@@ -197,6 +206,11 @@ pub struct Binder<T> {
 }
 
 #[derive(Clone, Debug)]
+pub struct EarlyBinder<T> {
+    pub value: T,
+}
+
+#[derive(Clone, Debug)]
 pub enum BoundVariableKind {
     Ty(BoundTyKind),
     Region(BoundRegionKind),
@@ -432,3 +446,10 @@ pub struct TraitDecl {
     pub implement_via_object: bool,
     pub deny_explicit_impl: bool,
 }
+
+pub type ImplTrait = EarlyBinder<TraitRef>;
+
+pub struct TraitRef {
+    pub def_id: TraitDef,
+    pub args: GenericArgs,
+}
diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs
index 22fd1f09f3a..74538e9f5a3 100644
--- a/compiler/rustc_symbol_mangling/src/lib.rs
+++ b/compiler/rustc_symbol_mangling/src/lib.rs
@@ -180,7 +180,7 @@ fn compute_symbol_name<'tcx>(
 
     if let Some(def_id) = def_id.as_local() {
         if tcx.proc_macro_decls_static(()) == Some(def_id) {
-            let stable_crate_id = tcx.sess.local_stable_crate_id();
+            let stable_crate_id = tcx.stable_crate_id(LOCAL_CRATE);
             return tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id);
         }
     }
diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
index 845b5791161..d345368d552 100644
--- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
@@ -824,11 +824,8 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
         }
 
         ty::Array(ty0, len) => {
-            let len = len
-                .try_to_scalar()
-                .unwrap()
-                .to_u64()
-                .unwrap_or_else(|_| panic!("failed to convert length to u64"));
+            let len = len.eval_target_usize(tcx, ty::ParamEnv::reveal_all());
+
             ty = Ty::new_array(tcx, transform_ty(tcx, *ty0, options), len);
         }
 
diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs b/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs
index 56f126e9157..be48447e27c 100644
--- a/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs
+++ b/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs
@@ -19,21 +19,25 @@ rustc_index::newtype_index! {
 
 #[derive(Debug, Clone)]
 pub(super) struct ProvisionalEntry<'tcx> {
-    // In case we have a coinductive cycle, this is the
-    // the currently least restrictive result of this goal.
-    pub(super) response: QueryResult<'tcx>,
-    // In case of a cycle, the position of deepest stack entry involved
-    // in that cycle. This is monotonically decreasing in the stack as all
-    // elements between the current stack element in the deepest stack entry
-    // involved have to also be involved in that cycle.
-    //
-    // We can only move entries to the global cache once we're complete done
-    // with the cycle. If this entry has not been involved in a cycle,
-    // this is just its own depth.
+    /// In case we have a coinductive cycle, this is the
+    /// the current provisional result of this goal.
+    ///
+    /// This starts out as `None` for all goals and gets to some
+    /// when the goal gets popped from the stack or we rerun evaluation
+    /// for this goal to reach a fixpoint.
+    pub(super) response: Option<QueryResult<'tcx>>,
+    /// In case of a cycle, the position of deepest stack entry involved
+    /// in that cycle. This is monotonically decreasing in the stack as all
+    /// elements between the current stack element in the deepest stack entry
+    /// involved have to also be involved in that cycle.
+    ///
+    /// We can only move entries to the global cache once we're complete done
+    /// with the cycle. If this entry has not been involved in a cycle,
+    /// this is just its own depth.
     pub(super) depth: StackDepth,
 
-    // The goal for this entry. Should always be equal to the corresponding goal
-    // in the lookup table.
+    /// The goal for this entry. Should always be equal to the corresponding goal
+    /// in the lookup table.
     pub(super) input: CanonicalInput<'tcx>,
 }
 
@@ -92,7 +96,7 @@ impl<'tcx> ProvisionalCache<'tcx> {
         self.entries[entry_index].depth
     }
 
-    pub(super) fn provisional_result(&self, entry_index: EntryIndex) -> QueryResult<'tcx> {
+    pub(super) fn provisional_result(&self, entry_index: EntryIndex) -> Option<QueryResult<'tcx>> {
         self.entries[entry_index].response
     }
 }
diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
index 21c8d476902..b860f374c0a 100644
--- a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
@@ -13,7 +13,7 @@ use rustc_middle::traits::solve::CacheData;
 use rustc_middle::traits::solve::{CanonicalInput, Certainty, EvaluationCache, QueryResult};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::Limit;
-use std::{collections::hash_map::Entry, mem};
+use std::collections::hash_map::Entry;
 
 rustc_index::newtype_index! {
     pub struct StackDepth {}
@@ -216,8 +216,8 @@ impl<'tcx> SearchGraph<'tcx> {
                     cycle_participants: Default::default(),
                 };
                 assert_eq!(self.stack.push(entry), depth);
-                let response = Self::response_no_constraints(tcx, input, Certainty::Yes);
-                let entry_index = cache.entries.push(ProvisionalEntry { response, depth, input });
+                let entry_index =
+                    cache.entries.push(ProvisionalEntry { response: None, depth, input });
                 v.insert(entry_index);
             }
             // We have a nested goal which relies on a goal `root` deeper in the stack.
@@ -243,23 +243,31 @@ impl<'tcx> SearchGraph<'tcx> {
                     root.cycle_participants.insert(e.input);
                 }
 
-                // NOTE: The goals on the stack aren't the only goals involved in this cycle.
-                // We can also depend on goals which aren't part of the stack but coinductively
-                // depend on the stack themselves. We already checked whether all the goals
-                // between these goals and their root on the stack. This means that as long as
-                // each goal in a cycle is checked for coinductivity by itself, simply checking
-                // the stack is enough.
-                if self.stack.raw[stack_depth.index()..]
-                    .iter()
-                    .all(|g| g.input.value.goal.predicate.is_coinductive(tcx))
-                {
-                    // If we're in a coinductive cycle, we have to retry proving the current goal
-                    // until we reach a fixpoint.
-                    self.stack[stack_depth].has_been_used = true;
-                    return cache.provisional_result(entry_index);
+                // If we're in a cycle, we have to retry proving the current goal
+                // until we reach a fixpoint.
+                self.stack[stack_depth].has_been_used = true;
+                return if let Some(result) = cache.provisional_result(entry_index) {
+                    result
                 } else {
-                    return Self::response_no_constraints(tcx, input, Certainty::OVERFLOW);
-                }
+                    // If we don't have a provisional result yet, the goal has to
+                    // still be on the stack.
+                    let mut goal_on_stack = false;
+                    let mut is_coinductive = true;
+                    for entry in self.stack.raw[stack_depth.index()..]
+                        .iter()
+                        .skip_while(|entry| entry.input != input)
+                    {
+                        goal_on_stack = true;
+                        is_coinductive &= entry.input.value.goal.predicate.is_coinductive(tcx);
+                    }
+                    debug_assert!(goal_on_stack);
+
+                    if is_coinductive {
+                        Self::response_no_constraints(tcx, input, Certainty::Yes)
+                    } else {
+                        Self::response_no_constraints(tcx, input, Certainty::OVERFLOW)
+                    }
+                };
             }
         }
 
@@ -288,15 +296,18 @@ impl<'tcx> SearchGraph<'tcx> {
                     let provisional_entry_index =
                         *cache.lookup_table.get(&stack_entry.input).unwrap();
                     let provisional_entry = &mut cache.entries[provisional_entry_index];
-                    let prev_response = mem::replace(&mut provisional_entry.response, response);
-                    if stack_entry.has_been_used && prev_response != response {
-                        // If so, remove all entries whose result depends on this goal
-                        // from the provisional cache...
+                    if stack_entry.has_been_used
+                        && provisional_entry.response.map_or(true, |r| r != response)
+                    {
+                        // If so, update the provisional result for this goal and remove
+                        // all entries whose result depends on this goal from the provisional
+                        // cache...
                         //
-                        // That's not completely correct, as a nested goal can also
+                        // That's not completely correct, as a nested goal can also only
                         // depend on a goal which is lower in the stack so it doesn't
                         // actually depend on the current goal. This should be fairly
                         // rare and is hopefully not relevant for performance.
+                        provisional_entry.response = Some(response);
                         #[allow(rustc::potential_query_instability)]
                         cache.lookup_table.retain(|_key, index| *index <= provisional_entry_index);
                         cache.entries.truncate(provisional_entry_index.index() + 1);
@@ -315,8 +326,8 @@ impl<'tcx> SearchGraph<'tcx> {
             });
 
         // We're now done with this goal. In case this goal is involved in a larger cycle
-        // do not remove it from the provisional cache and do not add it to the global
-        // cache.
+        // do not remove it from the provisional cache and update its provisional result.
+        // We only add the root of cycles to the global cache.
         //
         // It is not possible for any nested goal to depend on something deeper on the
         // stack, as this would have also updated the depth of the current goal.
@@ -348,6 +359,8 @@ impl<'tcx> SearchGraph<'tcx> {
                 dep_node,
                 result,
             )
+        } else {
+            provisional_entry.response = Some(result);
         }
 
         result
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index f1bd9f8b71a..4371b6c1239 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -2394,7 +2394,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
             Ok(args) => args,
             Err(()) => {
                 // FIXME: A rematch may fail when a candidate cache hit occurs
-                // on thefreshened form of the trait predicate, but the match
+                // on the freshened form of the trait predicate, but the match
                 // fails for some reason that is not captured in the freshened
                 // cache key. For example, equating an impl trait ref against
                 // the placeholder trait ref may fail due the Generalizer relation
diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs
index ec0dbffc22f..72bd50ace6d 100644
--- a/compiler/rustc_type_ir/src/sty.rs
+++ b/compiler/rustc_type_ir/src/sty.rs
@@ -200,7 +200,9 @@ pub enum TyKind<I: Interner> {
     /// A tuple type. For example, `(i32, bool)`.
     Tuple(I::ListTy),
 
-    /// A projection or opaque type. Both of these types
+    /// A projection, opaque type, weak type alias, or inherent associated type.
+    /// All of these types are represented as pairs of def-id and args, and can
+    /// be normalized, so they are grouped conceptually.
     Alias(AliasKind, I::AliasTy),
 
     /// A type parameter; for example, `T` in `fn f<T>(x: T) {}`.
diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs
index 052edf453f6..2c26f9e0312 100644
--- a/library/alloc/src/collections/linked_list.rs
+++ b/library/alloc/src/collections/linked_list.rs
@@ -18,7 +18,7 @@ use core::hash::{Hash, Hasher};
 use core::iter::FusedIterator;
 use core::marker::PhantomData;
 use core::mem;
-use core::ptr::{NonNull, Unique};
+use core::ptr::NonNull;
 
 use super::SpecExtend;
 use crate::alloc::{Allocator, Global};
@@ -168,15 +168,16 @@ impl<T, A: Allocator> LinkedList<T, A> {
     /// Adds the given node to the front of the list.
     ///
     /// # Safety
-    /// `node` must point to a valid node that was boxed using the list's allocator.
+    /// `node` must point to a valid node that was boxed and leaked using the list's allocator.
+    /// This method takes ownership of the node, so the pointer should not be used again.
     #[inline]
-    unsafe fn push_front_node(&mut self, node: Unique<Node<T>>) {
+    unsafe fn push_front_node(&mut self, node: NonNull<Node<T>>) {
         // This method takes care not to create mutable references to whole nodes,
         // to maintain validity of aliasing pointers into `element`.
         unsafe {
             (*node.as_ptr()).next = self.head;
             (*node.as_ptr()).prev = None;
-            let node = Some(NonNull::from(node));
+            let node = Some(node);
 
             match self.head {
                 None => self.tail = node,
@@ -212,15 +213,16 @@ impl<T, A: Allocator> LinkedList<T, A> {
     /// Adds the given node to the back of the list.
     ///
     /// # Safety
-    /// `node` must point to a valid node that was boxed using the list's allocator.
+    /// `node` must point to a valid node that was boxed and leaked using the list's allocator.
+    /// This method takes ownership of the node, so the pointer should not be used again.
     #[inline]
-    unsafe fn push_back_node(&mut self, node: Unique<Node<T>>) {
+    unsafe fn push_back_node(&mut self, node: NonNull<Node<T>>) {
         // This method takes care not to create mutable references to whole nodes,
         // to maintain validity of aliasing pointers into `element`.
         unsafe {
             (*node.as_ptr()).next = None;
             (*node.as_ptr()).prev = self.tail;
-            let node = Some(NonNull::from(node));
+            let node = Some(node);
 
             match self.tail {
                 None => self.head = node,
@@ -842,8 +844,8 @@ impl<T, A: Allocator> LinkedList<T, A> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn push_front(&mut self, elt: T) {
         let node = Box::new_in(Node::new(elt), &self.alloc);
-        let node_ptr = Unique::from(Box::leak(node));
-        // SAFETY: node_ptr is a unique pointer to a node we boxed with self.alloc
+        let node_ptr = NonNull::from(Box::leak(node));
+        // SAFETY: node_ptr is a unique pointer to a node we boxed with self.alloc and leaked
         unsafe {
             self.push_front_node(node_ptr);
         }
@@ -890,8 +892,8 @@ impl<T, A: Allocator> LinkedList<T, A> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn push_back(&mut self, elt: T) {
         let node = Box::new_in(Node::new(elt), &self.alloc);
-        let node_ptr = Unique::from(Box::leak(node));
-        // SAFETY: node_ptr is a unique pointer to a node we boxed with self.alloc
+        let node_ptr = NonNull::from(Box::leak(node));
+        // SAFETY: node_ptr is a unique pointer to a node we boxed with self.alloc and leaked
         unsafe {
             self.push_back_node(node_ptr);
         }
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 60b07485c3a..afed3fdf745 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -2491,9 +2491,9 @@ impl<T, A: Allocator> From<Vec<T, A>> for Rc<[T], A> {
     ///
     /// ```
     /// # use std::rc::Rc;
-    /// let original: Box<Vec<i32>> = Box::new(vec![1, 2, 3]);
-    /// let shared: Rc<Vec<i32>> = Rc::from(original);
-    /// assert_eq!(vec![1, 2, 3], *shared);
+    /// let unique: Vec<i32> = vec![1, 2, 3];
+    /// let shared: Rc<[i32]> = Rc::from(unique);
+    /// assert_eq!(&[1, 2, 3], &shared[..]);
     /// ```
     #[inline]
     fn from(v: Vec<T, A>) -> Rc<[T], A> {
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 74046a9c7c3..502f8a75863 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -1,7 +1,7 @@
 use super::*;
 use crate::cmp::Ordering::{self, Equal, Greater, Less};
 use crate::intrinsics::{self, const_eval_select};
-use crate::mem;
+use crate::mem::{self, SizedTypeProperties};
 use crate::slice::{self, SliceIndex};
 
 impl<T: ?Sized> *const T {
@@ -995,14 +995,23 @@ impl<T: ?Sized> *const T {
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+    // We could always go back to wrapping if unchecked becomes unacceptable
+    #[rustc_allow_const_fn_unstable(const_int_unchecked_arith)]
     #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn sub(self, count: usize) -> Self
     where
         T: Sized,
     {
-        // SAFETY: the caller must uphold the safety contract for `offset`.
-        unsafe { self.offset((count as isize).wrapping_neg()) }
+        if T::IS_ZST {
+            // Pointer arithmetic does nothing when the pointee is a ZST.
+            self
+        } else {
+            // SAFETY: the caller must uphold the safety contract for `offset`.
+            // Because the pointee is *not* a ZST, that means that `count` is
+            // at most `isize::MAX`, and thus the negation cannot overflow.
+            unsafe { self.offset(intrinsics::unchecked_sub(0, count as isize)) }
+        }
     }
 
     /// Calculates the offset from a pointer in bytes (convenience for
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index e3a3f69afd9..d129e1d645f 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -1,6 +1,7 @@
 use super::*;
 use crate::cmp::Ordering::{self, Equal, Greater, Less};
 use crate::intrinsics::{self, const_eval_select};
+use crate::mem::SizedTypeProperties;
 use crate::slice::{self, SliceIndex};
 
 impl<T: ?Sized> *mut T {
@@ -1095,14 +1096,23 @@ impl<T: ?Sized> *mut T {
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+    // We could always go back to wrapping if unchecked becomes unacceptable
+    #[rustc_allow_const_fn_unstable(const_int_unchecked_arith)]
     #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn sub(self, count: usize) -> Self
     where
         T: Sized,
     {
-        // SAFETY: the caller must uphold the safety contract for `offset`.
-        unsafe { self.offset((count as isize).wrapping_neg()) }
+        if T::IS_ZST {
+            // Pointer arithmetic does nothing when the pointee is a ZST.
+            self
+        } else {
+            // SAFETY: the caller must uphold the safety contract for `offset`.
+            // Because the pointee is *not* a ZST, that means that `count` is
+            // at most `isize::MAX`, and thus the negation cannot overflow.
+            unsafe { self.offset(intrinsics::unchecked_sub(0, count as isize)) }
+        }
     }
 
     /// Calculates the offset from a pointer in bytes (convenience for
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index b871be733b8..5b213555394 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -25,14 +25,12 @@ hashbrown = { version = "0.14", default-features = false, features = ['rustc-dep
 std_detect = { path = "../stdarch/crates/std_detect", default-features = false, features = ['rustc-dep-of-std'] }
 
 # Dependencies of the `backtrace` crate
-addr2line = { version = "0.20.0", optional = true, default-features = false }
 rustc-demangle = { version = "0.1.21", features = ['rustc-dep-of-std'] }
-miniz_oxide = { version = "0.7.0", optional = true, default-features = false, public = false }
-[dependencies.object]
-version = "0.31.1"
-optional = true
-default-features = false
-features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive']
+
+[target.'cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))'.dependencies]
+miniz_oxide = { version = "0.7.0", optional = true, default-features = false }
+addr2line = { version = "0.20.0", optional = true, default-features = false }
+object = { version = "0.31.1", default-features = false, optional = true, features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] }
 
 [dev-dependencies]
 rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 0f79e74f555..a7e65305386 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -791,6 +791,7 @@ impl Write for &File {
         self.inner.is_write_vectored()
     }
 
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         self.inner.flush()
     }
@@ -836,6 +837,7 @@ impl Write for File {
     fn is_write_vectored(&self) -> bool {
         (&&*self).is_write_vectored()
     }
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         (&*self).flush()
     }
@@ -881,6 +883,7 @@ impl Write for Arc<File> {
     fn is_write_vectored(&self) -> bool {
         (&**self).is_write_vectored()
     }
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         (&**self).flush()
     }
diff --git a/library/std/src/io/readbuf.rs b/library/std/src/io/readbuf.rs
index 1f3f80b9618..034ddd8df9a 100644
--- a/library/std/src/io/readbuf.rs
+++ b/library/std/src/io/readbuf.rs
@@ -310,6 +310,7 @@ impl<'a> Write for BorrowedCursor<'a> {
         Ok(buf.len())
     }
 
+    #[inline]
     fn flush(&mut self) -> Result<()> {
         Ok(())
     }
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index f08ffa75700..9038e8fa9d7 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -397,9 +397,15 @@ extern crate libc;
 #[allow(unused_extern_crates)]
 extern crate unwind;
 
+// FIXME: #94122 this extern crate definition only exist here to stop
+// miniz_oxide docs leaking into std docs. Find better way to do it.
+// Remove exclusion from tidy platform check when this removed.
 #[doc(masked)]
 #[allow(unused_extern_crates)]
-#[cfg(feature = "miniz_oxide")]
+#[cfg(all(
+    not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))),
+    feature = "miniz_oxide"
+))]
 extern crate miniz_oxide;
 
 // During testing, this crate is not actually the "real" std library, but rather
diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs
index 141a18a42dd..32fd54c8e75 100644
--- a/library/std/src/net/tcp.rs
+++ b/library/std/src/net/tcp.rs
@@ -647,6 +647,7 @@ impl Write for TcpStream {
         self.0.is_write_vectored()
     }
 
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
     }
@@ -685,6 +686,7 @@ impl Write for &TcpStream {
         self.0.is_write_vectored()
     }
 
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
     }
diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs
index e20170873bb..41290e0017a 100644
--- a/library/std/src/os/unix/net/stream.rs
+++ b/library/std/src/os/unix/net/stream.rs
@@ -712,6 +712,7 @@ impl<'a> io::Write for &'a UnixStream {
         self.0.is_write_vectored()
     }
 
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
     }
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index f1305dee146..f25ad2ece71 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -280,6 +280,7 @@ impl Write for ChildStdin {
         io::Write::is_write_vectored(&&*self)
     }
 
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         (&*self).flush()
     }
@@ -299,6 +300,7 @@ impl Write for &ChildStdin {
         self.inner.is_write_vectored()
     }
 
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
     }
diff --git a/library/std/src/sync/barrier.rs b/library/std/src/sync/barrier.rs
index e39254aa434..ed3c5512084 100644
--- a/library/std/src/sync/barrier.rs
+++ b/library/std/src/sync/barrier.rs
@@ -130,11 +130,8 @@ impl Barrier {
         let local_gen = lock.generation_id;
         lock.count += 1;
         if lock.count < self.num_threads {
-            // We need a while loop to guard against spurious wakeups.
-            // https://en.wikipedia.org/wiki/Spurious_wakeup
-            while local_gen == lock.generation_id {
-                lock = self.cvar.wait(lock).unwrap();
-            }
+            let _guard =
+                self.cvar.wait_while(lock, |state| local_gen == state.generation_id).unwrap();
             BarrierWaitResult(false)
         } else {
             lock.count = 0;
diff --git a/library/std/src/sys/hermit/fs.rs b/library/std/src/sys/hermit/fs.rs
index 4bb735668d2..6aa4ea7f5b4 100644
--- a/library/std/src/sys/hermit/fs.rs
+++ b/library/std/src/sys/hermit/fs.rs
@@ -335,6 +335,7 @@ impl File {
         false
     }
 
+    #[inline]
     pub fn flush(&self) -> io::Result<()> {
         Ok(())
     }
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index 7dc809a038b..a5604c92a80 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -1204,6 +1204,7 @@ impl File {
         self.0.write_vectored_at(bufs, offset)
     }
 
+    #[inline]
     pub fn flush(&self) -> io::Result<()> {
         Ok(())
     }
diff --git a/library/std/src/sys/unix/stdio.rs b/library/std/src/sys/unix/stdio.rs
index a26f20795a1..97e75f1b5b6 100644
--- a/library/std/src/sys/unix/stdio.rs
+++ b/library/std/src/sys/unix/stdio.rs
@@ -54,6 +54,7 @@ impl io::Write for Stdout {
         true
     }
 
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
     }
@@ -81,6 +82,7 @@ impl io::Write for Stderr {
         true
     }
 
+    #[inline]
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
     }
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 62c7b96b5be..cad370ad756 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -1129,7 +1129,7 @@ fn needs_codegen_config(run: &RunConfig<'_>) -> bool {
     needs_codegen_cfg
 }
 
-const CODEGEN_BACKEND_PREFIX: &str = "rustc_codegen_";
+pub(crate) const CODEGEN_BACKEND_PREFIX: &str = "rustc_codegen_";
 
 fn is_codegen_cfg_needed(path: &TaskPath, run: &RunConfig<'_>) -> bool {
     if path.path.to_str().unwrap().contains(&CODEGEN_BACKEND_PREFIX) {
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index cdb34f99164..830c1a3b846 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -20,6 +20,7 @@ use std::str::FromStr;
 use crate::cache::{Interned, INTERNER};
 use crate::cc_detect::{ndk_compiler, Language};
 use crate::channel::{self, GitInfo};
+use crate::compile::CODEGEN_BACKEND_PREFIX;
 pub use crate::flags::Subcommand;
 use crate::flags::{Color, Flags, Warnings};
 use crate::util::{exe, output, t};
@@ -1443,8 +1444,21 @@ impl Config {
                 .map(|v| v.parse().expect("failed to parse rust.llvm-libunwind"));
 
             if let Some(ref backends) = rust.codegen_backends {
-                config.rust_codegen_backends =
-                    backends.iter().map(|s| INTERNER.intern_str(s)).collect();
+                let available_backends = vec!["llvm", "cranelift", "gcc"];
+
+                config.rust_codegen_backends = backends.iter().map(|s| {
+                    if let Some(backend) = s.strip_prefix(CODEGEN_BACKEND_PREFIX) {
+                        if available_backends.contains(&backend) {
+                            panic!("Invalid value '{s}' for 'rust.codegen-backends'. Instead, please use '{backend}'.");
+                        } else {
+                            println!("help: '{s}' for 'rust.codegen-backends' might fail. \
+                                Codegen backends are mostly defined without the '{CODEGEN_BACKEND_PREFIX}' prefix. \
+                                In this case, it would be referred to as '{backend}'.");
+                        }
+                    }
+
+                    INTERNER.intern_str(s)
+                }).collect();
             }
 
             config.rust_codegen_units = rust.codegen_units.map(threads_from_config);
diff --git a/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md b/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md
index ce894ce6ac7..2dd1f6f8e1a 100644
--- a/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md
+++ b/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md
@@ -1,4 +1,4 @@
-# `profile-sample-use
+# `profile-sample-use`
 
 ---
 
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index 2655d93599e..71671273c57 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -4890,12 +4890,14 @@ Released 2018-09-13
 [`if_same_then_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_same_then_else
 [`if_then_some_else_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none
 [`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond
+[`ignored_unit_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#ignored_unit_patterns
 [`impl_trait_in_params`]: https://rust-lang.github.io/rust-clippy/master/index.html#impl_trait_in_params
 [`implicit_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_clone
 [`implicit_hasher`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_hasher
 [`implicit_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_return
 [`implicit_saturating_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_saturating_add
 [`implicit_saturating_sub`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_saturating_sub
+[`impossible_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#impossible_comparisons
 [`imprecise_flops`]: https://rust-lang.github.io/rust-clippy/master/index.html#imprecise_flops
 [`inconsistent_digit_grouping`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_digit_grouping
 [`inconsistent_struct_constructor`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_struct_constructor
@@ -5190,6 +5192,7 @@ Released 2018-09-13
 [`redundant_closure`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
 [`redundant_closure_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_call
 [`redundant_closure_for_method_calls`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_for_method_calls
+[`redundant_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_comparisons
 [`redundant_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_else
 [`redundant_feature_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_feature_names
 [`redundant_field_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names
diff --git a/src/tools/clippy/clippy_dev/src/main.rs b/src/tools/clippy/clippy_dev/src/main.rs
index 43eaccdf5a3..fca750fafc7 100644
--- a/src/tools/clippy/clippy_dev/src/main.rs
+++ b/src/tools/clippy/clippy_dev/src/main.rs
@@ -41,7 +41,7 @@ fn main() {
                 matches.get_one::<String>("type").map(String::as_str),
                 matches.get_flag("msrv"),
             ) {
-                Ok(_) => update_lints::update(update_lints::UpdateMode::Change),
+                Ok(()) => update_lints::update(update_lints::UpdateMode::Change),
                 Err(e) => eprintln!("Unable to create lint: {e}"),
             }
         },
diff --git a/src/tools/clippy/clippy_dev/src/setup/vscode.rs b/src/tools/clippy/clippy_dev/src/setup/vscode.rs
index dbcdc9b59e5..204f4af2cf1 100644
--- a/src/tools/clippy/clippy_dev/src/setup/vscode.rs
+++ b/src/tools/clippy/clippy_dev/src/setup/vscode.rs
@@ -47,7 +47,7 @@ fn check_install_precondition(force_override: bool) -> bool {
         }
     } else {
         match fs::create_dir(vs_dir_path) {
-            Ok(_) => {
+            Ok(()) => {
                 println!("info: created `{VSCODE_DIR}` directory for clippy");
             },
             Err(err) => {
diff --git a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs
index 15ffb00da88..181dbcf6e9a 100644
--- a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs
@@ -1,9 +1,7 @@
-use std::borrow::Cow;
-
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::msrvs::{self, Msrv};
+use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::sugg::Sugg;
-use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, Mutability, TyKind};
 use rustc_lint::LateContext;
@@ -16,33 +14,41 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) {
         return;
     }
 
-    if_chain! {
-        if let ExprKind::Cast(cast_expr, cast_to_hir_ty) = expr.kind;
-        let (cast_from, cast_to) = (cx.typeck_results().expr_ty(cast_expr), cx.typeck_results().expr_ty(expr));
-        if let ty::RawPtr(TypeAndMut { mutbl: from_mutbl, .. }) = cast_from.kind();
-        if let ty::RawPtr(TypeAndMut { ty: to_pointee_ty, mutbl: to_mutbl }) = cast_to.kind();
-        if matches!((from_mutbl, to_mutbl),
-            (Mutability::Not, Mutability::Not) | (Mutability::Mut, Mutability::Mut));
+    if let ExprKind::Cast(cast_expr, cast_to_hir_ty) = expr.kind
+        && let (cast_from, cast_to) = (cx.typeck_results().expr_ty(cast_expr), cx.typeck_results().expr_ty(expr))
+        && let ty::RawPtr(TypeAndMut { mutbl: from_mutbl, .. }) = cast_from.kind()
+        && let ty::RawPtr(TypeAndMut { ty: to_pointee_ty, mutbl: to_mutbl }) = cast_to.kind()
+        && matches!((from_mutbl, to_mutbl),
+            (Mutability::Not, Mutability::Not) | (Mutability::Mut, Mutability::Mut))
         // The `U` in `pointer::cast` have to be `Sized`
         // as explained here: https://github.com/rust-lang/rust/issues/60602.
-        if to_pointee_ty.is_sized(cx.tcx, cx.param_env);
-        then {
-            let mut applicability = Applicability::MachineApplicable;
-            let cast_expr_sugg = Sugg::hir_with_applicability(cx, cast_expr, "_", &mut applicability);
-            let turbofish = match &cast_to_hir_ty.kind {
-                    TyKind::Infer => Cow::Borrowed(""),
-                    TyKind::Ptr(mut_ty) if matches!(mut_ty.ty.kind, TyKind::Infer) => Cow::Borrowed(""),
-                    _ => Cow::Owned(format!("::<{to_pointee_ty}>")),
-                };
-            span_lint_and_sugg(
-                cx,
-                PTR_AS_PTR,
-                expr.span,
-                "`as` casting between raw pointers without changing its mutability",
-                "try `pointer::cast`, a safer alternative",
-                format!("{}.cast{turbofish}()", cast_expr_sugg.maybe_par()),
-                applicability,
-            );
-        }
+        && to_pointee_ty.is_sized(cx.tcx, cx.param_env)
+    {
+        let mut app = Applicability::MachineApplicable;
+        let cast_expr_sugg = Sugg::hir_with_applicability(cx, cast_expr, "_", &mut app);
+        let turbofish = match &cast_to_hir_ty.kind {
+            TyKind::Infer => String::new(),
+            TyKind::Ptr(mut_ty) => {
+                if matches!(mut_ty.ty.kind, TyKind::Infer) {
+                    String::new()
+                } else {
+                    format!(
+                        "::<{}>",
+                        snippet_with_applicability(cx, mut_ty.ty.span, "/* type */", &mut app)
+                    )
+                }
+            },
+            _ => return,
+        };
+
+        span_lint_and_sugg(
+            cx,
+            PTR_AS_PTR,
+            expr.span,
+            "`as` casting between raw pointers without changing its mutability",
+            "try `pointer::cast`, a safer alternative",
+            format!("{}.cast{turbofish}()", cast_expr_sugg.maybe_par()),
+            app,
+        );
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index d4e0d286334..db114abfc86 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -203,6 +203,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::if_let_mutex::IF_LET_MUTEX_INFO,
     crate::if_not_else::IF_NOT_ELSE_INFO,
     crate::if_then_some_else_none::IF_THEN_SOME_ELSE_NONE_INFO,
+    crate::ignored_unit_patterns::IGNORED_UNIT_PATTERNS_INFO,
     crate::implicit_hasher::IMPLICIT_HASHER_INFO,
     crate::implicit_return::IMPLICIT_RETURN_INFO,
     crate::implicit_saturating_add::IMPLICIT_SATURATING_ADD_INFO,
@@ -517,6 +518,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::operators::FLOAT_CMP_CONST_INFO,
     crate::operators::FLOAT_EQUALITY_WITHOUT_ABS_INFO,
     crate::operators::IDENTITY_OP_INFO,
+    crate::operators::IMPOSSIBLE_COMPARISONS_INFO,
     crate::operators::INEFFECTIVE_BIT_MASK_INFO,
     crate::operators::INTEGER_DIVISION_INFO,
     crate::operators::MISREFACTORED_ASSIGN_OP_INFO,
@@ -525,6 +527,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::operators::NEEDLESS_BITWISE_BOOL_INFO,
     crate::operators::OP_REF_INFO,
     crate::operators::PTR_EQ_INFO,
+    crate::operators::REDUNDANT_COMPARISONS_INFO,
     crate::operators::SELF_ASSIGNMENT_INFO,
     crate::operators::VERBOSE_BIT_MASK_INFO,
     crate::option_env_unwrap::OPTION_ENV_UNWRAP_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index 9900dbdee6b..d3311792cfa 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -1,6 +1,4 @@
-use clippy_utils::diagnostics::{
-    span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then,
-};
+use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::ty::{implements_trait, implements_trait_with_env, is_copy};
 use clippy_utils::{is_lint_allowed, match_def_path, paths};
 use if_chain::if_chain;
@@ -8,15 +6,14 @@ use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, Visitor};
 use rustc_hir::{
-    self as hir, BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, Impl, Item, ItemKind,
-    UnsafeSource, Unsafety,
+    self as hir, BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, Impl, Item, ItemKind, UnsafeSource, Unsafety,
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::traits::Reveal;
 use rustc_middle::ty::{
-    self, ClauseKind, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv,
-    ToPredicate, TraitPredicate, Ty, TyCtxt,
+    self, ClauseKind, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, ToPredicate, TraitPredicate, Ty,
+    TyCtxt,
 };
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::def_id::LocalDefId;
@@ -207,10 +204,13 @@ declare_lint_pass!(Derive => [
 
 impl<'tcx> LateLintPass<'tcx> for Derive {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        if let ItemKind::Impl(Impl { of_trait: Some(ref trait_ref), .. }) = item.kind {
+        if let ItemKind::Impl(Impl {
+            of_trait: Some(ref trait_ref),
+            ..
+        }) = item.kind
+        {
             let ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
-            let is_automatically_derived =
-                cx.tcx.has_attr(item.owner_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);
@@ -327,12 +327,7 @@ fn check_ord_partial_ord<'tcx>(
 }
 
 /// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint.
-fn check_copy_clone<'tcx>(
-    cx: &LateContext<'tcx>,
-    item: &Item<'_>,
-    trait_ref: &hir::TraitRef<'_>,
-    ty: Ty<'tcx>,
-) {
+fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &hir::TraitRef<'_>, ty: Ty<'tcx>) {
     let clone_id = match cx.tcx.lang_items().clone_trait() {
         Some(id) if trait_ref.trait_def_id() == Some(id) => id,
         _ => return,
@@ -350,9 +345,10 @@ fn check_copy_clone<'tcx>(
     if !is_copy(cx, ty) {
         if ty_subs.non_erasable_generics().next().is_some() {
             let has_copy_impl = cx.tcx.all_local_trait_impls(()).get(&copy_id).map_or(false, |impls| {
-                impls
-                    .iter()
-                    .any(|&id| matches!(cx.tcx.type_of(id).instantiate_identity().kind(), ty::Adt(adt, _) if ty_adt.did() == adt.did()))
+                impls.iter().any(|&id| {
+                    matches!(cx.tcx.type_of(id).instantiate_identity().kind(), ty::Adt(adt, _)
+                                        if ty_adt.did() == adt.did())
+                })
             });
             if !has_copy_impl {
                 return;
@@ -431,14 +427,7 @@ struct UnsafeVisitor<'a, 'tcx> {
 impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> {
     type NestedFilter = nested_filter::All;
 
-    fn visit_fn(
-        &mut self,
-        kind: FnKind<'tcx>,
-        decl: &'tcx FnDecl<'_>,
-        body_id: BodyId,
-        _: Span,
-        id: LocalDefId,
-    ) {
+    fn visit_fn(&mut self, kind: FnKind<'tcx>, decl: &'tcx FnDecl<'_>, body_id: BodyId, _: Span, id: LocalDefId) {
         if self.has_unsafe {
             return;
         }
@@ -474,12 +463,7 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> {
 }
 
 /// Implementation of the `DERIVE_PARTIAL_EQ_WITHOUT_EQ` lint.
-fn check_partial_eq_without_eq<'tcx>(
-    cx: &LateContext<'tcx>,
-    span: Span,
-    trait_ref: &hir::TraitRef<'_>,
-    ty: Ty<'tcx>,
-) {
+fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_ref: &hir::TraitRef<'_>, ty: Ty<'tcx>) {
     if_chain! {
         if let ty::Adt(adt, args) = ty.kind();
         if cx.tcx.visibility(adt.did()).is_public();
diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs
index 2c4d93e33ba..e29ab634c97 100644
--- a/src/tools/clippy/clippy_lints/src/doc.rs
+++ b/src/tools/clippy/clippy_lints/src/doc.rs
@@ -716,10 +716,7 @@ fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, span: Span) {
                 let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
                 let fallback_bundle =
                     rustc_errors::fallback_fluent_bundle(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), false);
-                let emitter = EmitterWriter::new(
-                    Box::new(io::sink()),
-                    fallback_bundle,
-                );
+                let emitter = EmitterWriter::new(Box::new(io::sink()), fallback_bundle);
                 let handler = Handler::with_emitter(Box::new(emitter)).disable_warnings();
                 let sess = ParseSess::with_span_handler(handler, sm);
 
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index ba7957b0dec..38066503c07 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -10,8 +10,8 @@ use rustc_hir::{BindingAnnotation, Expr, ExprKind, FnRetTy, Param, PatKind, QPat
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{
-    self, Binder, ClosureArgs, ClosureKind, EarlyBinder, FnSig, GenericArg, GenericArgKind,
-    GenericArgsRef, ImplPolarity, List, Region, RegionKind, Ty, TypeVisitableExt, TypeckResults,
+    self, Binder, ClosureArgs, ClosureKind, EarlyBinder, FnSig, GenericArg, GenericArgKind, GenericArgsRef,
+    ImplPolarity, List, Region, RegionKind, Ty, TypeVisitableExt, TypeckResults,
 };
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::symbol::sym;
diff --git a/src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs b/src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs
new file mode 100644
index 00000000000..c635120b882
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs
@@ -0,0 +1,52 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use hir::PatKind;
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for usage of `_` in patterns of type `()`.
+    ///
+    /// ### Why is this bad?
+    /// Matching with `()` explicitly instead of `_` outlines
+    /// the fact that the pattern contains no data. Also it
+    /// would detect a type change that `_` would ignore.
+    ///
+    /// ### Example
+    /// ```rust
+    /// match std::fs::create_dir("tmp-work-dir") {
+    ///    Ok(_) => println!("Working directory created"),
+    ///    Err(s) => eprintln!("Could not create directory: {s}"),
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// match std::fs::create_dir("tmp-work-dir") {
+    ///    Ok(()) => println!("Working directory created"),
+    ///    Err(s) => eprintln!("Could not create directory: {s}"),
+    /// }
+    /// ```
+    #[clippy::version = "1.73.0"]
+    pub IGNORED_UNIT_PATTERNS,
+    pedantic,
+    "suggest replacing `_` by `()` in patterns where appropriate"
+}
+declare_lint_pass!(IgnoredUnitPatterns => [IGNORED_UNIT_PATTERNS]);
+
+impl<'tcx> LateLintPass<'tcx> for IgnoredUnitPatterns {
+    fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx hir::Pat<'tcx>) {
+        if matches!(pat.kind, PatKind::Wild) && cx.typeck_results().pat_ty(pat).is_unit() {
+            span_lint_and_sugg(
+                cx,
+                IGNORED_UNIT_PATTERNS,
+                pat.span,
+                "matching over `()` is more explicit",
+                "use `()` instead of `_`",
+                String::from("()"),
+                Applicability::MachineApplicable,
+            );
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 9d6096ccb2a..358004cf460 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -147,6 +147,7 @@ mod future_not_send;
 mod if_let_mutex;
 mod if_not_else;
 mod if_then_some_else_none;
+mod ignored_unit_patterns;
 mod implicit_hasher;
 mod implicit_return;
 mod implicit_saturating_add;
@@ -1093,6 +1094,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         })
     });
     store.register_late_pass(|_| Box::new(redundant_locals::RedundantLocals));
+    store.register_late_pass(|_| Box::new(ignored_unit_patterns::IgnoredUnitPatterns));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
index dd77c69ef88..cc19ac55e5e 100644
--- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
@@ -162,7 +162,9 @@ fn never_loop_expr<'tcx>(
         ExprKind::Binary(_, e1, e2)
         | ExprKind::Assign(e1, e2, _)
         | ExprKind::AssignOp(_, e1, e2)
-        | ExprKind::Index(e1, e2, _) => never_loop_expr_all(cx, &mut [e1, e2].iter().copied(), ignore_ids, main_loop_id),
+        | ExprKind::Index(e1, e2, _) => {
+            never_loop_expr_all(cx, &mut [e1, e2].iter().copied(), ignore_ids, main_loop_id)
+        },
         ExprKind::Loop(b, _, _, _) => {
             // Break can come from the inner loop so remove them.
             absorb_break(never_loop_block(cx, b, ignore_ids, main_loop_id))
diff --git a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs
index f48a5d9d245..88db7ae6aec 100644
--- a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs
@@ -84,7 +84,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
         if !in_external_macro(cx.sess(), expr.span)
             && (
-                matches!(cx.tcx.constness(cx.tcx.hir().enclosing_body_owner(expr.hir_id)), Constness::NotConst) 
+                matches!(cx.tcx.constness(cx.tcx.hir().enclosing_body_owner(expr.hir_id)), Constness::NotConst)
                     || cx.tcx.features().active(sym!(const_float_classify))
             ) && let ExprKind::Binary(kind, lhs, rhs) = expr.kind
             && let ExprKind::Binary(lhs_kind, lhs_lhs, lhs_rhs) = lhs.kind
diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs
index 6383326aa38..29af4812351 100644
--- a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs
@@ -2,6 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::path_to_local;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::visitors::{for_each_expr, is_local_used};
+use rustc_ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{Arm, BinOpKind, Expr, ExprKind, Guard, MatchSource, Node, Pat, PatKind};
@@ -160,6 +161,11 @@ fn emit_redundant_guards<'tcx>(
 }
 
 /// Checks if the given `Expr` can also be represented as a `Pat`.
+///
+/// All literals generally also work as patterns, however float literals are special.
+/// They are currently (as of 2023/08/08) still allowed in patterns, but that will become
+/// an error in the future, and rustc already actively warns against this (see rust#41620),
+/// so we don't consider those as usable within patterns for linting purposes.
 fn expr_can_be_pat(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     for_each_expr(expr, |expr| {
         if match expr.kind {
@@ -177,8 +183,8 @@ fn expr_can_be_pat(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
             ExprKind::AddrOf(..)
             | ExprKind::Array(..)
             | ExprKind::Tup(..)
-            | ExprKind::Struct(..)
-            | ExprKind::Lit(..) => true,
+            | ExprKind::Struct(..) => true,
+            ExprKind::Lit(lit) if !matches!(lit.node, LitKind::Float(..)) => true,
             _ => false,
         } {
             return ControlFlow::Continue(());
diff --git a/src/tools/clippy/clippy_lints/src/methods/expect_used.rs b/src/tools/clippy/clippy_lints/src/methods/expect_used.rs
deleted file mode 100644
index 614610335a1..00000000000
--- a/src/tools/clippy/clippy_lints/src/methods/expect_used.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{is_in_cfg_test, is_in_test_function};
-use rustc_hir as hir;
-use rustc_lint::LateContext;
-use rustc_span::sym;
-
-use super::EXPECT_USED;
-
-/// lint use of `expect()` or `expect_err` for `Result` and `expect()` for `Option`.
-pub(super) fn check(
-    cx: &LateContext<'_>,
-    expr: &hir::Expr<'_>,
-    recv: &hir::Expr<'_>,
-    is_err: bool,
-    allow_expect_in_tests: bool,
-) {
-    let obj_ty = cx.typeck_results().expr_ty(recv).peel_refs();
-
-    let mess = if is_type_diagnostic_item(cx, obj_ty, sym::Option) && !is_err {
-        Some((EXPECT_USED, "an `Option`", "None", ""))
-    } else if is_type_diagnostic_item(cx, obj_ty, sym::Result) {
-        Some((EXPECT_USED, "a `Result`", if is_err { "Ok" } else { "Err" }, "an "))
-    } else {
-        None
-    };
-
-    let method = if is_err { "expect_err" } else { "expect" };
-
-    if allow_expect_in_tests && (is_in_test_function(cx.tcx, expr.hir_id) || is_in_cfg_test(cx.tcx, expr.hir_id)) {
-        return;
-    }
-
-    if let Some((lint, kind, none_value, none_prefix)) = mess {
-        span_lint_and_help(
-            cx,
-            lint,
-            expr.span,
-            &format!("used `{method}()` on {kind} value"),
-            None,
-            &format!("if this value is {none_prefix}`{none_value}`, it will panic"),
-        );
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs
index 4aee22a4afc..fafc9709770 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs
@@ -1,3 +1,4 @@
+use super::FILTER_MAP_BOOL_THEN;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::paths::BOOL_THEN;
 use clippy_utils::source::snippet_opt;
@@ -7,10 +8,9 @@ use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::lint::in_external_macro;
+use rustc_middle::ty::Binder;
 use rustc_span::{sym, Span};
 
-use super::FILTER_MAP_BOOL_THEN;
-
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: &Expr<'_>, call_span: Span) {
     if !in_external_macro(cx.sess(), expr.span)
         && is_trait_method(cx, expr, sym::Iterator)
@@ -21,7 +21,15 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: &
         // `inputs` and `params` here as we need both the type and the span
         && let param_ty = closure.fn_decl.inputs[0]
         && let param = body.params[0]
-        && is_copy(cx, cx.typeck_results().node_type(param_ty.hir_id).peel_refs())
+        // Issue #11309
+        && let param_ty = cx.tcx.liberate_late_bound_regions(
+            closure.def_id.to_def_id(),
+            Binder::bind_with_vars(
+                cx.typeck_results().node_type(param_ty.hir_id),
+                cx.tcx.late_bound_vars(cx.tcx.hir().local_def_id_to_hir_id(closure.def_id)),
+            ),
+        )
+        && is_copy(cx, param_ty)
         && let ExprKind::MethodCall(_, recv, [then_arg], _) = value.kind
         && let ExprKind::Closure(then_closure) = then_arg.kind
         && let then_body = peel_blocks(cx.tcx.hir().body(then_closure.body).value)
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index dd694ce7393..42756b27d01 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -17,7 +17,6 @@ mod collapsible_str_replace;
 mod drain_collect;
 mod err_expect;
 mod expect_fun_call;
-mod expect_used;
 mod extend_with_drain;
 mod filetype_is_file;
 mod filter_map;
@@ -105,7 +104,7 @@ mod unnecessary_lazy_eval;
 mod unnecessary_literal_unwrap;
 mod unnecessary_sort_by;
 mod unnecessary_to_owned;
-mod unwrap_used;
+mod unwrap_expect_used;
 mod useless_asref;
 mod utils;
 mod vec_resize_to_zero;
@@ -3881,6 +3880,13 @@ impl Methods {
                         unnecessary_lazy_eval::check(cx, expr, recv, arg, "and");
                     }
                 },
+                ("any", [arg]) if let ExprKind::Closure(arg) = arg.kind
+                    && let body = cx.tcx.hir().body(arg.body)
+                    && let [param] = body.params
+                    && let Some(("chars", recv, _, _, _)) = method_call(recv) =>
+                {
+                    string_lit_chars_any::check(cx, expr, recv, param, peel_blocks(body.value), &self.msrv);
+                }
                 ("arg", [arg]) => {
                     suspicious_command_arg_space::check(cx, recv, arg, span);
                 }
@@ -3941,13 +3947,27 @@ impl Methods {
                     match method_call(recv) {
                         Some(("ok", recv, [], _, _)) => ok_expect::check(cx, expr, recv),
                         Some(("err", recv, [], err_span, _)) => err_expect::check(cx, expr, recv, span, err_span, &self.msrv),
-                        _ => expect_used::check(cx, expr, recv, false, self.allow_expect_in_tests),
+                        _ => unwrap_expect_used::check(
+                            cx,
+                            expr,
+                            recv,
+                            false,
+                            self.allow_expect_in_tests,
+                            unwrap_expect_used::Variant::Expect,
+                        ),
                     }
                     unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
                 },
                 ("expect_err", [_]) => {
                     unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
-                    expect_used::check(cx, expr, recv, true, self.allow_expect_in_tests);
+                    unwrap_expect_used::check(
+                        cx,
+                        expr,
+                        recv,
+                        true,
+                        self.allow_expect_in_tests,
+                        unwrap_expect_used::Variant::Expect,
+                    );
                 },
                 ("extend", [arg]) => {
                     string_extend_chars::check(cx, expr, recv, arg);
@@ -3999,20 +4019,9 @@ impl Methods {
                         unnecessary_join::check(cx, expr, recv, join_arg, span);
                     }
                 },
-                ("skip", [arg]) => {
-                    iter_skip_zero::check(cx, expr, arg);
-
-                    if let Some((name2, recv2, args2, _span2, _)) = method_call(recv) {
-                        if let ("cloned", []) = (name2, args2) {
-                            iter_overeager_cloned::check(cx, expr, recv, recv2, false, false);
-                        }
-                    }
-                }
                 ("last", []) => {
-                    if let Some((name2, recv2, args2, _span2, _)) = method_call(recv) {
-                        if let ("cloned", []) = (name2, args2) {
-                            iter_overeager_cloned::check(cx, expr, recv, recv2, false, false);
-                        }
+                    if let Some(("cloned", recv2, [], _span2, _)) = method_call(recv) {
+                        iter_overeager_cloned::check(cx, expr, recv, recv2, false, false);
                     }
                 },
                 ("lock", []) => {
@@ -4060,13 +4069,6 @@ impl Methods {
                         }
                     }
                 },
-                ("any", [arg]) if let ExprKind::Closure(arg) = arg.kind
-                    && let body = cx.tcx.hir().body(arg.body)
-                    && let [param] = body.params
-                    && let Some(("chars", recv, _, _, _)) = method_call(recv) =>
-                {
-                    string_lit_chars_any::check(cx, expr, recv, param, peel_blocks(body.value), &self.msrv);
-                }
                 ("nth", [n_arg]) => match method_call(recv) {
                     Some(("bytes", recv2, [], _, _)) => bytes_nth::check(cx, expr, recv2, n_arg),
                     Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, false),
@@ -4120,6 +4122,13 @@ impl Methods {
                         seek_to_start_instead_of_rewind::check(cx, expr, recv, arg, span);
                     }
                 },
+                ("skip", [arg]) => {
+                    iter_skip_zero::check(cx, expr, arg);
+
+                    if let Some(("cloned", recv2, [], _span2, _)) = method_call(recv) {
+                        iter_overeager_cloned::check(cx, expr, recv, recv2, false, false);
+                    }
+                }
                 ("sort", []) => {
                     stable_sort_primitive::check(cx, expr, recv);
                 },
@@ -4142,10 +4151,8 @@ impl Methods {
                 },
                 ("step_by", [arg]) => iterator_step_by_zero::check(cx, expr, arg),
                 ("take", [_arg]) => {
-                    if let Some((name2, recv2, args2, _span2, _)) = method_call(recv) {
-                        if let ("cloned", []) = (name2, args2) {
-                            iter_overeager_cloned::check(cx, expr, recv, recv2, false, false);
-                        }
+                    if let Some(("cloned", recv2, [], _span2, _)) = method_call(recv) {
+                        iter_overeager_cloned::check(cx, expr, recv, recv2, false, false);
                     }
                 },
                 ("take", []) => needless_option_take::check(cx, expr, recv),
@@ -4180,11 +4187,25 @@ impl Methods {
                         _ => {},
                     }
                     unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
-                    unwrap_used::check(cx, expr, recv, false, self.allow_unwrap_in_tests);
+                    unwrap_expect_used::check(
+                        cx,
+                        expr,
+                        recv,
+                        false,
+                        self.allow_unwrap_in_tests,
+                        unwrap_expect_used::Variant::Unwrap,
+                    );
                 },
                 ("unwrap_err", []) => {
                     unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
-                    unwrap_used::check(cx, expr, recv, true, self.allow_unwrap_in_tests);
+                    unwrap_expect_used::check(
+                        cx,
+                        expr,
+                        recv,
+                        true,
+                        self.allow_unwrap_in_tests,
+                        unwrap_expect_used::Variant::Unwrap,
+                    );
                 },
                 ("unwrap_or", [u_arg]) => {
                     match method_call(recv) {
@@ -4214,6 +4235,9 @@ impl Methods {
                     }
                     unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
                 },
+                ("write", []) => {
+                    readonly_write_lock::check(cx, expr, recv);
+                }
                 ("zip", [arg]) => {
                     if let ExprKind::MethodCall(name, iter_recv, [], _) = recv.kind
                         && name.ident.name == sym::iter
@@ -4221,9 +4245,6 @@ impl Methods {
                         range_zip_with_len::check(cx, expr, iter_recv, arg);
                     }
                 },
-                ("write", []) => {
-                    readonly_write_lock::check(cx, expr, recv);
-                }
                 _ => {},
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/methods/unwrap_expect_used.rs b/src/tools/clippy/clippy_lints/src/methods/unwrap_expect_used.rs
new file mode 100644
index 00000000000..7bd16b473ce
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/unwrap_expect_used.rs
@@ -0,0 +1,83 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::ty::{is_never_like, is_type_diagnostic_item};
+use clippy_utils::{is_in_cfg_test, is_in_test_function, is_lint_allowed};
+use rustc_hir::Expr;
+use rustc_lint::{LateContext, Lint};
+use rustc_middle::ty;
+use rustc_span::sym;
+
+use super::{EXPECT_USED, UNWRAP_USED};
+
+#[derive(Clone, Copy, Eq, PartialEq)]
+pub(super) enum Variant {
+    Unwrap,
+    Expect,
+}
+
+impl Variant {
+    fn method_name(self, is_err: bool) -> &'static str {
+        match (self, is_err) {
+            (Variant::Unwrap, true) => "unwrap_err",
+            (Variant::Unwrap, false) => "unwrap",
+            (Variant::Expect, true) => "expect_err",
+            (Variant::Expect, false) => "expect",
+        }
+    }
+
+    fn lint(self) -> &'static Lint {
+        match self {
+            Variant::Unwrap => UNWRAP_USED,
+            Variant::Expect => EXPECT_USED,
+        }
+    }
+}
+
+/// Lint usage of `unwrap` or `unwrap_err` for `Result` and `unwrap()` for `Option` (and their
+/// `expect` counterparts).
+pub(super) fn check(
+    cx: &LateContext<'_>,
+    expr: &Expr<'_>,
+    recv: &Expr<'_>,
+    is_err: bool,
+    allow_unwrap_in_tests: bool,
+    variant: Variant,
+) {
+    let ty = cx.typeck_results().expr_ty(recv).peel_refs();
+
+    let (kind, none_value, none_prefix) = if is_type_diagnostic_item(cx, ty, sym::Option) && !is_err {
+        ("an `Option`", "None", "")
+    } else if is_type_diagnostic_item(cx, ty, sym::Result)
+        && let ty::Adt(_, substs) = ty.kind()
+        && let Some(t_or_e_ty) = substs[usize::from(!is_err)].as_type()
+    {
+        if is_never_like(t_or_e_ty) {
+            return;
+        }
+
+        ("a `Result`", if is_err { "Ok" } else { "Err" }, "an ")
+    } else {
+        return;
+    };
+
+    let method_suffix = if is_err { "_err" } else { "" };
+
+    if allow_unwrap_in_tests && (is_in_test_function(cx.tcx, expr.hir_id) || is_in_cfg_test(cx.tcx, expr.hir_id)) {
+        return;
+    }
+
+    span_lint_and_then(
+        cx,
+        variant.lint(),
+        expr.span,
+        &format!("used `{}()` on {kind} value", variant.method_name(is_err)),
+        |diag| {
+            diag.note(format!("if this value is {none_prefix}`{none_value}`, it will panic"));
+
+            if variant == Variant::Unwrap && is_lint_allowed(cx, EXPECT_USED, expr.hir_id) {
+                diag.help(format!(
+                    "consider using `expect{method_suffix}()` to provide a better panic message"
+                ));
+            }
+        },
+    );
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs b/src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs
deleted file mode 100644
index 5e4c3daee64..00000000000
--- a/src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs
+++ /dev/null
@@ -1,53 +0,0 @@
-use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{is_in_cfg_test, is_in_test_function, is_lint_allowed};
-use rustc_hir as hir;
-use rustc_lint::LateContext;
-use rustc_span::sym;
-
-use super::{EXPECT_USED, UNWRAP_USED};
-
-/// lint use of `unwrap()` or `unwrap_err` for `Result` and `unwrap()` for `Option`.
-pub(super) fn check(
-    cx: &LateContext<'_>,
-    expr: &hir::Expr<'_>,
-    recv: &hir::Expr<'_>,
-    is_err: bool,
-    allow_unwrap_in_tests: bool,
-) {
-    let obj_ty = cx.typeck_results().expr_ty(recv).peel_refs();
-
-    let mess = if is_type_diagnostic_item(cx, obj_ty, sym::Option) && !is_err {
-        Some((UNWRAP_USED, "an `Option`", "None", ""))
-    } else if is_type_diagnostic_item(cx, obj_ty, sym::Result) {
-        Some((UNWRAP_USED, "a `Result`", if is_err { "Ok" } else { "Err" }, "an "))
-    } else {
-        None
-    };
-
-    let method_suffix = if is_err { "_err" } else { "" };
-
-    if allow_unwrap_in_tests && (is_in_test_function(cx.tcx, expr.hir_id) || is_in_cfg_test(cx.tcx, expr.hir_id)) {
-        return;
-    }
-
-    if let Some((lint, kind, none_value, none_prefix)) = mess {
-        let help = if is_lint_allowed(cx, EXPECT_USED, expr.hir_id) {
-            format!(
-                "if you don't want to handle the `{none_value}` case gracefully, consider \
-                using `expect{method_suffix}()` to provide a better panic message"
-            )
-        } else {
-            format!("if this value is {none_prefix}`{none_value}`, it will panic")
-        };
-
-        span_lint_and_help(
-            cx,
-            lint,
-            expr.span,
-            &format!("used `unwrap{method_suffix}()` on {kind} value"),
-            None,
-            &help,
-        );
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs
index a41d5a9ce8d..93f6025c71d 100644
--- a/src/tools/clippy/clippy_lints/src/missing_inline.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs
@@ -74,7 +74,6 @@ fn is_executable_or_proc_macro(cx: &LateContext<'_>) -> bool {
     use rustc_session::config::CrateType;
 
     cx.tcx
-        .sess
         .crate_types()
         .iter()
         .any(|t: &CrateType| matches!(t, CrateType::Executable | CrateType::ProcMacro))
diff --git a/src/tools/clippy/clippy_lints/src/mut_reference.rs b/src/tools/clippy/clippy_lints/src/mut_reference.rs
index 4b20aecad4a..e53e146ec5d 100644
--- a/src/tools/clippy/clippy_lints/src/mut_reference.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_reference.rs
@@ -37,6 +37,11 @@ declare_lint_pass!(UnnecessaryMutPassed => [UNNECESSARY_MUT_PASSED]);
 
 impl<'tcx> LateLintPass<'tcx> for UnnecessaryMutPassed {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
+        if e.span.from_expansion() {
+            // Issue #11268
+            return;
+        }
+
         match e.kind {
             ExprKind::Call(fn_expr, arguments) => {
                 if let ExprKind::Path(ref path) = fn_expr.kind {
diff --git a/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs b/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs
new file mode 100644
index 00000000000..abe8df19543
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs
@@ -0,0 +1,207 @@
+#![allow(clippy::match_same_arms)]
+
+use std::cmp::Ordering;
+
+use clippy_utils::consts::{constant, Constant};
+use if_chain::if_chain;
+use rustc_hir::{BinOpKind, Expr, ExprKind};
+use rustc_lint::LateContext;
+use rustc_middle::ty::layout::HasTyCtxt;
+use rustc_middle::ty::{Ty, TypeckResults};
+use rustc_span::source_map::{Span, Spanned};
+
+use clippy_utils::diagnostics::span_lint_and_note;
+use clippy_utils::source::snippet;
+use clippy_utils::SpanlessEq;
+
+use super::{IMPOSSIBLE_COMPARISONS, REDUNDANT_COMPARISONS};
+
+// Extract a comparison between a const and non-const
+// Flip yoda conditionals, turnings expressions like `42 < x` into `x > 42`
+fn comparison_to_const<'tcx>(
+    cx: &LateContext<'tcx>,
+    typeck: &TypeckResults<'tcx>,
+    expr: &'tcx Expr<'tcx>,
+) -> Option<(CmpOp, &'tcx Expr<'tcx>, &'tcx Expr<'tcx>, Constant<'tcx>, Ty<'tcx>)> {
+    if_chain! {
+        if let ExprKind::Binary(operator, left, right) = expr.kind;
+        if let Ok(cmp_op) = CmpOp::try_from(operator.node);
+        then {
+            match (constant(cx, typeck, left), constant(cx, typeck, right)) {
+                (Some(_), Some(_)) => None,
+                (_, Some(con)) => Some((cmp_op, left, right, con, typeck.expr_ty(right))),
+                (Some(con), _) => Some((cmp_op.reverse(), right, left, con, typeck.expr_ty(left))),
+                _ => None,
+            }
+        } else {
+            None
+        }
+    }
+}
+
+pub(super) fn check<'tcx>(
+    cx: &LateContext<'tcx>,
+    and_op: Spanned<BinOpKind>,
+    left_cond: &'tcx Expr<'tcx>,
+    right_cond: &'tcx Expr<'tcx>,
+    span: Span,
+) {
+    if_chain! {
+        // Ensure that the binary operator is &&
+        if and_op.node == BinOpKind::And;
+
+        // Check that both operands to '&&' are themselves a binary operation
+        // The `comparison_to_const` step also checks this, so this step is just an optimization
+        if let ExprKind::Binary(_, _, _) = left_cond.kind;
+        if let ExprKind::Binary(_, _, _) = right_cond.kind;
+
+        let typeck = cx.typeck_results();
+
+        // Check that both operands to '&&' compare a non-literal to a literal
+        if let Some((left_cmp_op, left_expr, left_const_expr, left_const, left_type)) =
+            comparison_to_const(cx, typeck, left_cond);
+        if let Some((right_cmp_op, right_expr, right_const_expr, right_const, right_type)) =
+            comparison_to_const(cx, typeck, right_cond);
+
+        if left_type == right_type;
+
+        // Check that the same expression is compared in both comparisons
+        if SpanlessEq::new(cx).eq_expr(left_expr, right_expr);
+
+        if !left_expr.can_have_side_effects();
+
+        // Compare the two constant expressions
+        if let Some(ordering) = Constant::partial_cmp(cx.tcx(), left_type, &left_const, &right_const);
+
+        // Rule out the `x >= 42 && x <= 42` corner case immediately
+        // Mostly to simplify the implementation, but it is also covered by `clippy::double_comparisons`
+        if !matches!(
+            (&left_cmp_op, &right_cmp_op, ordering),
+            (CmpOp::Le | CmpOp::Ge, CmpOp::Le | CmpOp::Ge, Ordering::Equal)
+        );
+
+        then {
+            if left_cmp_op.direction() == right_cmp_op.direction() {
+                let lhs_str = snippet(cx, left_cond.span, "<lhs>");
+                let rhs_str = snippet(cx, right_cond.span, "<rhs>");
+                // We already know that either side of `&&` has no effect,
+                // but emit a different error message depending on which side it is
+                if left_side_is_useless(left_cmp_op, ordering) {
+                    span_lint_and_note(
+                        cx,
+                        REDUNDANT_COMPARISONS,
+                        span,
+                        "left-hand side of `&&` operator has no effect",
+                        Some(left_cond.span.until(right_cond.span)),
+                        &format!("`if `{rhs_str}` evaluates to true, {lhs_str}` will always evaluate to true as well"),
+                    );
+                } else {
+                    span_lint_and_note(
+                        cx,
+                        REDUNDANT_COMPARISONS,
+                        span,
+                        "right-hand side of `&&` operator has no effect",
+                        Some(and_op.span.to(right_cond.span)),
+                        &format!("`if `{lhs_str}` evaluates to true, {rhs_str}` will always evaluate to true as well"),
+                    );
+                }
+                // We could autofix this error but choose not to,
+                // because code triggering this lint probably not behaving correctly in the first place
+            }
+            else if !comparison_is_possible(left_cmp_op.direction(), ordering) {
+                let expr_str = snippet(cx, left_expr.span, "..");
+                let lhs_str = snippet(cx, left_const_expr.span, "<lhs>");
+                let rhs_str = snippet(cx, right_const_expr.span, "<rhs>");
+                let note = match ordering {
+                    Ordering::Less => format!("since `{lhs_str}` < `{rhs_str}`, the expression evaluates to false for any value of `{expr_str}`"),
+                    Ordering::Equal => format!("`{expr_str}` cannot simultaneously be greater than and less than `{lhs_str}`"),
+                    Ordering::Greater => format!("since `{lhs_str}` > `{rhs_str}`, the expression evaluates to false for any value of `{expr_str}`"),
+                };
+                span_lint_and_note(
+                    cx,
+                    IMPOSSIBLE_COMPARISONS,
+                    span,
+                    "boolean expression will never evaluate to 'true'",
+                    None,
+                    &note,
+                );
+            };
+        }
+    }
+}
+
+fn left_side_is_useless(left_cmp_op: CmpOp, ordering: Ordering) -> bool {
+    // Special-case for equal constants with an inclusive comparison
+    if ordering == Ordering::Equal {
+        match left_cmp_op {
+            CmpOp::Lt | CmpOp::Gt => false,
+            CmpOp::Le | CmpOp::Ge => true,
+        }
+    } else {
+        match (left_cmp_op.direction(), ordering) {
+            (CmpOpDirection::Lesser, Ordering::Less) => false,
+            (CmpOpDirection::Lesser, Ordering::Equal) => false,
+            (CmpOpDirection::Lesser, Ordering::Greater) => true,
+            (CmpOpDirection::Greater, Ordering::Less) => true,
+            (CmpOpDirection::Greater, Ordering::Equal) => false,
+            (CmpOpDirection::Greater, Ordering::Greater) => false,
+        }
+    }
+}
+
+fn comparison_is_possible(left_cmp_direction: CmpOpDirection, ordering: Ordering) -> bool {
+    match (left_cmp_direction, ordering) {
+        (CmpOpDirection::Lesser, Ordering::Less | Ordering::Equal) => false,
+        (CmpOpDirection::Lesser, Ordering::Greater) => true,
+        (CmpOpDirection::Greater, Ordering::Greater | Ordering::Equal) => false,
+        (CmpOpDirection::Greater, Ordering::Less) => true,
+    }
+}
+
+#[derive(PartialEq, Eq, Clone, Copy)]
+enum CmpOpDirection {
+    Lesser,
+    Greater,
+}
+
+#[derive(Clone, Copy)]
+enum CmpOp {
+    Lt,
+    Le,
+    Ge,
+    Gt,
+}
+
+impl CmpOp {
+    fn reverse(self) -> Self {
+        match self {
+            CmpOp::Lt => CmpOp::Gt,
+            CmpOp::Le => CmpOp::Ge,
+            CmpOp::Ge => CmpOp::Le,
+            CmpOp::Gt => CmpOp::Lt,
+        }
+    }
+
+    fn direction(self) -> CmpOpDirection {
+        match self {
+            CmpOp::Lt => CmpOpDirection::Lesser,
+            CmpOp::Le => CmpOpDirection::Lesser,
+            CmpOp::Ge => CmpOpDirection::Greater,
+            CmpOp::Gt => CmpOpDirection::Greater,
+        }
+    }
+}
+
+impl TryFrom<BinOpKind> for CmpOp {
+    type Error = ();
+
+    fn try_from(bin_op: BinOpKind) -> Result<Self, Self::Error> {
+        match bin_op {
+            BinOpKind::Lt => Ok(CmpOp::Lt),
+            BinOpKind::Le => Ok(CmpOp::Le),
+            BinOpKind::Ge => Ok(CmpOp::Ge),
+            BinOpKind::Gt => Ok(CmpOp::Gt),
+            _ => Err(()),
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/operators/mod.rs b/src/tools/clippy/clippy_lints/src/operators/mod.rs
index 2cf15adda01..4635e1164cd 100644
--- a/src/tools/clippy/clippy_lints/src/operators/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/mod.rs
@@ -2,6 +2,7 @@ mod absurd_extreme_comparisons;
 mod assign_op_pattern;
 mod bit_mask;
 mod cmp_owned;
+mod const_comparisons;
 mod double_comparison;
 mod duration_subsec;
 mod eq_op;
@@ -300,6 +301,45 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
+    /// Checks for double comparisons that can never succeed
+    ///
+    /// ### Why is this bad?
+    /// The whole expression can be replaced by `false`,
+    /// which is probably not the programmer's intention
+    ///
+    /// ### Example
+    /// ```rust
+    /// # let status_code = 200;
+    /// if status_code <= 400 && status_code > 500 {}
+    /// ```
+    #[clippy::version = "1.71.0"]
+    pub IMPOSSIBLE_COMPARISONS,
+    correctness,
+    "double comparisons that will never evaluate to `true`"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for ineffective double comparisons against constants.
+    ///
+    /// ### Why is this bad?
+    /// Only one of the comparisons has any effect on the result, the programmer
+    /// probably intended to flip one of the comparison operators, or compare a
+    /// different value entirely.
+    ///
+    /// ### Example
+    /// ```rust
+    /// # let status_code = 200;
+    /// if status_code <= 400 && status_code < 500 {}
+    /// ```
+    #[clippy::version = "1.71.0"]
+    pub REDUNDANT_COMPARISONS,
+    correctness,
+    "double comparisons where one of them can be removed"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
     /// Checks for calculation of subsecond microseconds or milliseconds
     /// from other `Duration` methods.
     ///
@@ -742,6 +782,8 @@ impl_lint_pass!(Operators => [
     INEFFECTIVE_BIT_MASK,
     VERBOSE_BIT_MASK,
     DOUBLE_COMPARISONS,
+    IMPOSSIBLE_COMPARISONS,
+    REDUNDANT_COMPARISONS,
     DURATION_SUBSEC,
     EQ_OP,
     OP_REF,
@@ -786,6 +828,7 @@ impl<'tcx> LateLintPass<'tcx> for Operators {
                 bit_mask::check(cx, e, op.node, lhs, rhs);
                 verbose_bit_mask::check(cx, e, op.node, lhs, rhs, self.verbose_bit_mask_threshold);
                 double_comparison::check(cx, op.node, lhs, rhs, e.span);
+                const_comparisons::check(cx, op, lhs, rhs, e.span);
                 duration_subsec::check(cx, e, op.node, lhs, rhs);
                 float_equality_without_abs::check(cx, e, op.node, lhs, rhs);
                 integer_division::check(cx, e, op.node, lhs, rhs);
diff --git a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
index 40da002f4ff..a7a7f4fd8fa 100644
--- a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
+++ b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
@@ -155,7 +155,7 @@ fn try_get_option_occurrence<'tcx>(
                 });
                 if let ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(local_id), .. })) = e.kind {
                     match some_captures.get(local_id)
-                        .or_else(|| (method_sugg == "map_or_else").then_some(()).and_then(|_| none_captures.get(local_id)))
+                        .or_else(|| (method_sugg == "map_or_else").then_some(()).and_then(|()| none_captures.get(local_id)))
                     {
                         Some(CaptureKind::Value | CaptureKind::Ref(Mutability::Mut)) => return None,
                         Some(CaptureKind::Ref(Mutability::Not)) if as_mut => return None,
diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs
index f5502cffb66..734ca2914f5 100644
--- a/src/tools/clippy/clippy_lints/src/question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/question_mark.rs
@@ -1,11 +1,13 @@
 use crate::manual_let_else::{MatchLintBehaviour, MANUAL_LET_ELSE};
+use crate::question_mark_used::QUESTION_MARK_USED;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::msrvs::Msrv;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{
-    eq_expr_value, get_parent_node, higher, in_constant, is_else_clause, is_path_lang_item, is_res_lang_ctor,
-    pat_and_expr_can_be_question_mark, path_to_local, path_to_local_id, peel_blocks, peel_blocks_with_stmt,
+    eq_expr_value, get_parent_node, higher, in_constant, is_else_clause, is_lint_allowed, is_path_lang_item,
+    is_res_lang_ctor, pat_and_expr_can_be_question_mark, path_to_local, path_to_local_id, peel_blocks,
+    peel_blocks_with_stmt,
 };
 use if_chain::if_chain;
 use rustc_errors::Applicability;
@@ -299,13 +301,17 @@ fn is_try_block(cx: &LateContext<'_>, bl: &rustc_hir::Block<'_>) -> bool {
 
 impl<'tcx> LateLintPass<'tcx> for QuestionMark {
     fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
+        if !is_lint_allowed(cx, QUESTION_MARK_USED, stmt.hir_id) {
+            return;
+        }
+
         if !in_constant(cx, stmt.hir_id) {
             check_let_some_else_return_none(cx, stmt);
         }
         self.check_manual_let_else(cx, stmt);
     }
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if !in_constant(cx, expr.hir_id) {
+        if !in_constant(cx, expr.hir_id) && is_lint_allowed(cx, QUESTION_MARK_USED, expr.hir_id) {
             self.check_is_none_or_err_and_early_return(cx, expr);
             self.check_if_let_some_or_err_and_early_return(cx, expr);
         }
diff --git a/src/tools/clippy/clippy_lints/src/redundant_locals.rs b/src/tools/clippy/clippy_lints/src/redundant_locals.rs
index 896bd79b20b..0c89c7ee47d 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_locals.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_locals.rs
@@ -1,6 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::is_from_proc_macro;
 use clippy_utils::ty::needs_ordered_drop;
+use rustc_ast::Mutability;
 use rustc_hir::def::Res;
 use rustc_hir::{
     BindingAnnotation, ByRef, Expr, ExprKind, HirId, Local, Node, Pat, PatKind, QPath,
@@ -9,6 +10,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::{in_external_macro, is_from_async_await};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::symbol::Ident;
+use rustc_span::DesugaringKind;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -47,6 +49,7 @@ declare_lint_pass!(RedundantLocals => [REDUNDANT_LOCALS]);
 impl<'tcx> LateLintPass<'tcx> for RedundantLocals {
     fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) {
         if_chain! {
+            if !local.span.is_desugaring(DesugaringKind::Async);
             // the pattern is a single by-value binding
             if let PatKind::Binding(BindingAnnotation(ByRef::No, mutability), _, ident, None) = local.pat.kind;
             // the binding is not type-ascribed
@@ -62,6 +65,8 @@ impl<'tcx> LateLintPass<'tcx> for RedundantLocals {
             if let Node::Pat(binding_pat) = cx.tcx.hir().get(binding_id);
             // the previous binding has the same mutability
             if find_binding(binding_pat, ident).unwrap().1 == mutability;
+            // the local does not change the effect of assignments to the binding. see #11290
+            if !affects_assignments(cx, mutability, binding_id, local.hir_id);
             // the local does not affect the code's drop behavior
             if !affects_drop_behavior(cx, binding_id, local.hir_id, expr);
             // the local is user-controlled
@@ -97,6 +102,14 @@ fn find_binding(pat: &Pat<'_>, name: Ident) -> Option<BindingAnnotation> {
     ret
 }
 
+/// Check if a rebinding of a local changes the effect of assignments to the binding.
+fn affects_assignments(cx: &LateContext<'_>, mutability: Mutability, bind: HirId, rebind: HirId) -> bool {
+    let hir = cx.tcx.hir();
+
+    // the binding is mutable and the rebinding is in a different scope than the original binding
+    mutability == Mutability::Mut && hir.get_enclosing_scope(bind) != hir.get_enclosing_scope(rebind)
+}
+
 /// Check if a rebinding of a local affects the code's drop behavior.
 fn affects_drop_behavior<'tcx>(
     cx: &LateContext<'tcx>,
diff --git a/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs b/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs
index 8e9234bba3c..3e963d79892 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs
@@ -1,6 +1,8 @@
 use clippy_utils::diagnostics::span_lint;
+use clippy_utils::is_lint_allowed;
 use rustc_ast::LitKind;
 use rustc_hir as hir;
+use rustc_hir::def::DefKind;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::Ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -45,8 +47,8 @@ fn is_same_type<'tcx>(cx: &LateContext<'tcx>, ty_resolved_path: hir::def::Res, f
         return primty.name() == func_return_type_sym;
     }
 
-    // type annotation is any other non generic type
-    if let hir::def::Res::Def(_, defid) = ty_resolved_path
+    // type annotation is a non generic type
+    if let hir::def::Res::Def(DefKind::Struct | DefKind::Union | DefKind::Enum, defid) = ty_resolved_path
         && let Some(annotation_ty) = cx.tcx.type_of(defid).no_bound_vars()
     {
         return annotation_ty == func_return_type;
@@ -130,8 +132,9 @@ fn extract_primty(ty_kind: &hir::TyKind<'_>) -> Option<hir::PrimTy> {
 
 impl LateLintPass<'_> for RedundantTypeAnnotations {
     fn check_local<'tcx>(&mut self, cx: &LateContext<'tcx>, local: &'tcx rustc_hir::Local<'tcx>) {
-        // type annotation part
-        if !local.span.from_expansion()
+        if !is_lint_allowed(cx, REDUNDANT_TYPE_ANNOTATIONS, local.hir_id)
+            // type annotation part
+            && !local.span.from_expansion()
             && let Some(ty) = &local.ty
 
             // initialization part
diff --git a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
index 54a33eb2986..c9ab622ad25 100644
--- a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
+++ b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
@@ -20,18 +20,27 @@ declare_clippy_lint! {
     /// These structures are non-idiomatic and less efficient than simply using
     /// `vec![0; len]`.
     ///
+    /// Specifically, for `vec![0; len]`, the compiler can use a specialized type of allocation
+    /// that also zero-initializes the allocated memory in the same call
+    /// (see: [alloc_zeroed](https://doc.rust-lang.org/stable/std/alloc/trait.GlobalAlloc.html#method.alloc_zeroed)).
+    ///
+    /// Writing `Vec::new()` followed by `vec.resize(len, 0)` is suboptimal because,
+    /// while it does do the same number of allocations,
+    /// it involves two operations for allocating and initializing.
+    /// The `resize` call first allocates memory (since `Vec::new()` did not), and only *then* zero-initializes it.
+    ///
     /// ### Example
     /// ```rust
     /// # use core::iter::repeat;
     /// # let len = 4;
-    /// let mut vec1 = Vec::with_capacity(len);
+    /// let mut vec1 = Vec::new();
     /// vec1.resize(len, 0);
     ///
-    /// let mut vec1 = Vec::with_capacity(len);
-    /// vec1.resize(vec1.capacity(), 0);
-    ///
     /// let mut vec2 = Vec::with_capacity(len);
-    /// vec2.extend(repeat(0).take(len));
+    /// vec2.resize(len, 0);
+    ///
+    /// let mut vec3 = Vec::with_capacity(len);
+    /// vec3.extend(repeat(0).take(len));
     /// ```
     ///
     /// Use instead:
@@ -39,6 +48,7 @@ declare_clippy_lint! {
     /// # let len = 4;
     /// let mut vec1 = vec![0; len];
     /// let mut vec2 = vec![0; len];
+    /// let mut vec3 = vec![0; len];
     /// ```
     #[clippy::version = "1.32.0"]
     pub SLOW_VECTOR_INITIALIZATION,
diff --git a/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs b/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs
index 6fa49afe0ec..8e156b8829b 100644
--- a/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs
+++ b/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs
@@ -1,5 +1,7 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::numeric_literal::NumericLiteral;
-use clippy_utils::source::snippet_with_context;
+use clippy_utils::source::snippet;
+use rustc_ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -28,27 +30,29 @@ declare_lint_pass!(ConfusingXorAndPow => [SUSPICIOUS_XOR_USED_AS_POW]);
 
 impl LateLintPass<'_> for ConfusingXorAndPow {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
-        if !in_external_macro(cx.sess(), expr.span) &&
-        	let ExprKind::Binary(op, left, right) = &expr.kind &&
-            op.node == BinOpKind::BitXor &&
-            left.span.ctxt() == right.span.ctxt() &&
-            let ExprKind::Lit(lit_left) = &left.kind &&
-            let ExprKind::Lit(lit_right) = &right.kind &&
-            let snip_left = snippet_with_context(cx, lit_left.span, lit_left.span.ctxt(), "..", &mut Applicability::MaybeIncorrect) &&
-            let snip_right = snippet_with_context(cx, lit_right.span, lit_right.span.ctxt(), "..", &mut Applicability::MaybeIncorrect) &&
-            let Some(left_val) = NumericLiteral::from_lit_kind(&snip_left.0, &lit_left.node) &&
-            let Some(right_val) = NumericLiteral::from_lit_kind(&snip_right.0, &lit_right.node) &&
-			left_val.is_decimal() &&
-			right_val.is_decimal() {
-					clippy_utils::diagnostics::span_lint_and_sugg(
-					        cx,
-					        SUSPICIOUS_XOR_USED_AS_POW,
-					        expr.span,
-					        "`^` is not the exponentiation operator",
-					        "did you mean to write",
-					        format!("{}.pow({})", left_val.format(), right_val.format()),
-					        Applicability::MaybeIncorrect,
-					    );
+        if !in_external_macro(cx.sess(), expr.span)
+            && let ExprKind::Binary(op, left, right) = &expr.kind
+            && op.node == BinOpKind::BitXor
+            && left.span.ctxt() == right.span.ctxt()
+            && let ExprKind::Lit(lit_left) = &left.kind
+            && let ExprKind::Lit(lit_right) = &right.kind
+            && matches!(lit_right.node, LitKind::Int(..) | LitKind::Float(..))
+            && matches!(lit_left.node, LitKind::Int(..) | LitKind::Float(..))
+            && NumericLiteral::from_lit_kind(&snippet(cx, lit_right.span, ".."), &lit_right.node).is_some_and(|x| x.is_decimal())
+            {
+                span_lint_and_sugg(
+                    cx,
+                    SUSPICIOUS_XOR_USED_AS_POW,
+                    expr.span,
+                    "`^` is not the exponentiation operator",
+                    "did you mean to write",
+                    format!(
+                        "{}.pow({})",
+                        lit_left.node,
+                        lit_right.node
+                    ),
+                    Applicability::MaybeIncorrect,
+                );
 		}
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
index e4906944c8d..4ed985f54d0 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
@@ -34,7 +34,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidPaths {
         let mod_name = &cx.tcx.item_name(local_def_id.to_def_id());
         if_chain! {
             if mod_name.as_str() == "paths";
-            if let hir::ItemKind::Const(ty, body_id) = item.kind;
+            if let hir::ItemKind::Const(ty, _, body_id) = item.kind;
             let ty = hir_ty_to_ty(cx.tcx, ty);
             if let ty::Array(el_ty, _) = &ty.kind();
             if let ty::Ref(_, el_ty, _) = &el_ty.kind();
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs
index 2d0d6f559ad..140cfa2194f 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs
@@ -178,7 +178,9 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
         (Yield(l), Yield(r)) | (Ret(l), Ret(r)) => eq_expr_opt(l, r),
         (Break(ll, le), Break(rl, re)) => eq_label(ll, rl) && eq_expr_opt(le, re),
         (Continue(ll), Continue(rl)) => eq_label(ll, rl),
-        (Assign(l1, l2, _), Assign(r1, r2, _)) | (Index(l1, l2, _), Index(r1, r2, _)) => eq_expr(l1, r1) && eq_expr(l2, r2),
+        (Assign(l1, l2, _), Assign(r1, r2, _)) | (Index(l1, l2, _), Index(r1, r2, _)) => {
+            eq_expr(l1, r1) && eq_expr(l2, r2)
+        },
         (AssignOp(lo, lp, lv), AssignOp(ro, rp, rv)) => lo.node == ro.node && eq_expr(lp, rp) && eq_expr(lv, rv),
         (Field(lp, lf), Field(rp, rf)) => eq_id(*lf, *rf) && eq_expr(lp, rp),
         (Match(ls, la), Match(rs, ra)) => eq_expr(ls, rs) && over(la, ra, eq_arm),
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index d38e3f1ae76..adeb673b6b9 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -329,7 +329,7 @@ pub struct ConstEvalLateContext<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
-    fn new(lcx: &'a LateContext<'tcx>, typeck_results: &'a ty::TypeckResults<'tcx>) -> Self {
+    pub fn new(lcx: &'a LateContext<'tcx>, typeck_results: &'a ty::TypeckResults<'tcx>) -> Self {
         Self {
             lcx,
             typeck_results,
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index f0a777c5b89..4c695cb9b6e 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -14,7 +14,7 @@ use rustc_middle::mir::{
     Body, CastKind, NonDivergingIntrinsic, NullOp, Operand, Place, ProjectionElem, Rvalue, Statement, StatementKind,
     Terminator, TerminatorKind,
 };
-use rustc_middle::traits::{ImplSource, ObligationCause, BuiltinImplSource};
+use rustc_middle::traits::{BuiltinImplSource, ImplSource, ObligationCause};
 use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::{self, GenericArgKind, TraitRef, Ty, TyCtxt};
 use rustc_semver::RustcVersion;
@@ -425,5 +425,5 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx>
         ocx.select_all_or_error().is_empty()
     }
 
-    !ty.needs_drop(tcx, ConstCx::new(tcx, body).param_env)    
+    !ty.needs_drop(tcx, ConstCx::new(tcx, body).param_env)
 }
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index a43a81bc63a..ee5a49a2073 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -1010,7 +1010,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
                             projections_handled = true;
                         },
                         // note: unable to trigger `Subslice` kind in tests
-                        ProjectionKind::Subslice => (),
+                        ProjectionKind::Subslice |
                         // Doesn't have surface syntax. Only occurs in patterns.
                         ProjectionKind::OpaqueCast => (),
                         ProjectionKind::Deref => {
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 71766480535..a05f682aa8c 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -1093,6 +1093,11 @@ fn assert_generic_args_match<'tcx>(tcx: TyCtxt<'tcx>, did: DefId, args: &[Generi
     }
 }
 
+/// Returns whether `ty` is never-like; i.e., `!` (never) or an enum with zero variants.
+pub fn is_never_like(ty: Ty<'_>) -> bool {
+    ty.is_never() || (ty.is_enum() && ty.ty_adt_def().is_some_and(|def| def.variants().is_empty()))
+}
+
 /// Makes the projection type for the named associated type in the given impl or trait impl.
 ///
 /// This function is for associated types which are "known" to exist, and as such, will only return
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index 833608faff0..8b3f819f0cd 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2023-07-28"
+channel = "nightly-2023-08-10"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
diff --git a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
index 31df0ebd9fd..d8b158816c9 100644
--- a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
+++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
@@ -1,4 +1,5 @@
-thread '<unnamed>' panicked at 'Would you like some help with that?', clippy_lints/src/utils/internal_lints/produce_ice.rs
+thread '<unnamed>' panicked at clippy_lints/src/utils/internal_lints/produce_ice.rs:
+Would you like some help with that?
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 
 error: the compiler unexpectedly panicked. this is a bug.
diff --git a/src/tools/clippy/tests/ui-toml/expect_used/expect_used.stderr b/src/tools/clippy/tests/ui-toml/expect_used/expect_used.stderr
index 9eef0e1bfaa..815d009350f 100644
--- a/src/tools/clippy/tests/ui-toml/expect_used/expect_used.stderr
+++ b/src/tools/clippy/tests/ui-toml/expect_used/expect_used.stderr
@@ -4,7 +4,7 @@ error: used `expect()` on an `Option` value
 LL |     let _ = opt.expect("");
    |             ^^^^^^^^^^^^^^
    |
-   = help: if this value is `None`, it will panic
+   = note: if this value is `None`, it will panic
    = note: `-D clippy::expect-used` implied by `-D warnings`
 
 error: used `expect()` on a `Result` value
@@ -13,7 +13,7 @@ error: used `expect()` on a `Result` value
 LL |     let _ = res.expect("");
    |             ^^^^^^^^^^^^^^
    |
-   = help: if this value is an `Err`, it will panic
+   = note: if this value is an `Err`, it will panic
 
 error: aborting due to 2 previous errors
 
diff --git a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr
index 4c9bdfa9dba..10219beaf97 100644
--- a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr
+++ b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr
@@ -12,7 +12,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = boxed_slice.get(1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
    = note: `-D clippy::unwrap-used` implied by `-D warnings`
 
 error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
@@ -27,7 +28,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_slice.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
   --> $DIR/unwrap_used.rs:40:17
@@ -41,7 +43,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_vec.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
   --> $DIR/unwrap_used.rs:41:17
@@ -55,7 +58,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_vecdeque.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise
   --> $DIR/unwrap_used.rs:42:17
@@ -69,7 +73,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_hashmap.get(&1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise
   --> $DIR/unwrap_used.rs:43:17
@@ -83,7 +88,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_btreemap.get(&1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
   --> $DIR/unwrap_used.rs:47:21
@@ -97,7 +103,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _: u8 = *boxed_slice.get(1).unwrap();
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
   --> $DIR/unwrap_used.rs:52:9
@@ -111,7 +118,8 @@ error: used `unwrap()` on an `Option` value
 LL |         *boxed_slice.get_mut(0).unwrap() = 1;
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
   --> $DIR/unwrap_used.rs:53:9
@@ -125,7 +133,8 @@ error: used `unwrap()` on an `Option` value
 LL |         *some_slice.get_mut(0).unwrap() = 1;
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
   --> $DIR/unwrap_used.rs:54:9
@@ -139,7 +148,8 @@ error: used `unwrap()` on an `Option` value
 LL |         *some_vec.get_mut(0).unwrap() = 1;
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
   --> $DIR/unwrap_used.rs:55:9
@@ -153,7 +163,8 @@ error: used `unwrap()` on an `Option` value
 LL |         *some_vecdeque.get_mut(0).unwrap() = 1;
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
   --> $DIR/unwrap_used.rs:67:17
@@ -167,7 +178,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_vec.get(0..1).unwrap().to_vec();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
   --> $DIR/unwrap_used.rs:68:17
@@ -181,7 +193,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_vec.get_mut(0..1).unwrap().to_vec();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
   --> $DIR/unwrap_used.rs:75:13
diff --git a/src/tools/clippy/tests/ui/const_comparisons.rs b/src/tools/clippy/tests/ui/const_comparisons.rs
new file mode 100644
index 00000000000..8e265c9141c
--- /dev/null
+++ b/src/tools/clippy/tests/ui/const_comparisons.rs
@@ -0,0 +1,93 @@
+#![allow(unused)]
+#![warn(clippy::impossible_comparisons)]
+#![warn(clippy::redundant_comparisons)]
+#![allow(clippy::no_effect)]
+#![allow(clippy::short_circuit_statement)]
+#![allow(clippy::manual_range_contains)]
+
+const STATUS_BAD_REQUEST: u16 = 400;
+const STATUS_SERVER_ERROR: u16 = 500;
+
+struct Status {
+    code: u16,
+}
+
+impl PartialEq<u16> for Status {
+    fn eq(&self, other: &u16) -> bool {
+        self.code == *other
+    }
+}
+
+impl PartialOrd<u16> for Status {
+    fn partial_cmp(&self, other: &u16) -> Option<std::cmp::Ordering> {
+        self.code.partial_cmp(other)
+    }
+}
+
+impl PartialEq<Status> for u16 {
+    fn eq(&self, other: &Status) -> bool {
+        *self == other.code
+    }
+}
+
+impl PartialOrd<Status> for u16 {
+    fn partial_cmp(&self, other: &Status) -> Option<std::cmp::Ordering> {
+        self.partial_cmp(&other.code)
+    }
+}
+
+fn main() {
+    let status_code = 500; // Value doesn't matter for the lint
+    let status = Status { code: status_code };
+
+    status_code >= 400 && status_code < 500; // Correct
+    status_code <= 400 && status_code > 500;
+    status_code > 500 && status_code < 400;
+    status_code < 500 && status_code > 500;
+
+    // More complex expressions
+    status_code < { 400 } && status_code > { 500 };
+    status_code < STATUS_BAD_REQUEST && status_code > STATUS_SERVER_ERROR;
+    status_code <= u16::MIN + 1 && status_code > STATUS_SERVER_ERROR;
+    status_code < STATUS_SERVER_ERROR && status_code > STATUS_SERVER_ERROR;
+
+    // Comparing two different types, via the `impl PartialOrd<u16> for Status`
+    status < { 400 } && status > { 500 };
+    status < STATUS_BAD_REQUEST && status > STATUS_SERVER_ERROR;
+    status <= u16::MIN + 1 && status > STATUS_SERVER_ERROR;
+    status < STATUS_SERVER_ERROR && status > STATUS_SERVER_ERROR;
+
+    // Yoda conditions
+    500 <= status_code && 600 > status_code; // Correct
+    500 <= status_code && status_code <= 600; // Correct
+    500 >= status_code && 600 < status_code; // Incorrect
+    500 >= status_code && status_code > 600; // Incorrect
+
+    // Yoda conditions, comparing two different types
+    500 <= status && 600 > status; // Correct
+    500 <= status && status <= 600; // Correct
+    500 >= status && 600 < status; // Incorrect
+    500 >= status && status > 600; // Incorrect
+
+    // Expressions where one of the sides has no effect
+    status_code < 200 && status_code <= 299;
+    status_code > 200 && status_code >= 299;
+
+    status_code >= 500 && status_code > 500; // Useless left
+    status_code > 500 && status_code >= 500; // Useless right
+    status_code <= 500 && status_code < 500; // Useless left
+    status_code < 500 && status_code <= 500; // Useless right
+
+    // Other types
+    let name = "Steve";
+    name < "Jennifer" && name > "Shannon";
+
+    let numbers = [1, 2];
+    numbers < [3, 4] && numbers > [5, 6];
+
+    let letter = 'a';
+    letter < 'b' && letter > 'c';
+
+    let area = 42.0;
+    area < std::f32::consts::E && area > std::f32::consts::PI;
+}
diff --git a/src/tools/clippy/tests/ui/const_comparisons.stderr b/src/tools/clippy/tests/ui/const_comparisons.stderr
new file mode 100644
index 00000000000..90e6db64762
--- /dev/null
+++ b/src/tools/clippy/tests/ui/const_comparisons.stderr
@@ -0,0 +1,228 @@
+error: boolean expression will never evaluate to 'true'
+  --> $DIR/const_comparisons.rs:44:5
+   |
+LL |     status_code <= 400 && status_code > 500;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: since `400` < `500`, the expression evaluates to false for any value of `status_code`
+   = note: `-D clippy::impossible-comparisons` implied by `-D warnings`
+
+error: boolean expression will never evaluate to 'true'
+  --> $DIR/const_comparisons.rs:45:5
+   |
+LL |     status_code > 500 && status_code < 400;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: since `500` > `400`, the expression evaluates to false for any value of `status_code`
+
+error: boolean expression will never evaluate to 'true'
+  --> $DIR/const_comparisons.rs:46:5
+   |
+LL |     status_code < 500 && status_code > 500;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `status_code` cannot simultaneously be greater than and less than `500`
+
+error: boolean expression will never evaluate to 'true'
+  --> $DIR/const_comparisons.rs:49:5
+   |
+LL |     status_code < { 400 } && status_code > { 500 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: since `{ 400 }` < `{ 500 }`, the expression evaluates to false for any value of `status_code`
+
+error: boolean expression will never evaluate to 'true'
+  --> $DIR/const_comparisons.rs:50:5
+   |
+LL |     status_code < STATUS_BAD_REQUEST && status_code > STATUS_SERVER_ERROR;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: since `STATUS_BAD_REQUEST` < `STATUS_SERVER_ERROR`, the expression evaluates to false for any value of `status_code`
+
+error: boolean expression will never evaluate to 'true'
+  --> $DIR/const_comparisons.rs:51:5
+   |
+LL |     status_code <= u16::MIN + 1 && status_code > STATUS_SERVER_ERROR;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: since `u16::MIN + 1` < `STATUS_SERVER_ERROR`, the expression evaluates to false for any value of `status_code`
+
+error: boolean expression will never evaluate to 'true'
+  --> $DIR/const_comparisons.rs:52:5
+   |
+LL |     status_code < STATUS_SERVER_ERROR && status_code > STATUS_SERVER_ERROR;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `status_code` cannot simultaneously be greater than and less than `STATUS_SERVER_ERROR`
+
+error: boolean expression will never evaluate to 'true'
+  --> $DIR/const_comparisons.rs:55:5
+   |
+LL |     status < { 400 } && status > { 500 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: since `{ 400 }` < `{ 500 }`, the expression evaluates to false for any value of `status`
+
+error: boolean expression will never evaluate to 'true'
+  --> $DIR/const_comparisons.rs:56:5
+   |
+LL |     status < STATUS_BAD_REQUEST && status > STATUS_SERVER_ERROR;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: since `STATUS_BAD_REQUEST` < `STATUS_SERVER_ERROR`, the expression evaluates to false for any value of `status`
+
+error: boolean expression will never evaluate to 'true'
+  --> $DIR/const_comparisons.rs:57:5
+   |
+LL |     status <= u16::MIN + 1 && status > STATUS_SERVER_ERROR;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: since `u16::MIN + 1` < `STATUS_SERVER_ERROR`, the expression evaluates to false for any value of `status`
+
+error: boolean expression will never evaluate to 'true'
+  --> $DIR/const_comparisons.rs:58:5
+   |
+LL |     status < STATUS_SERVER_ERROR && status > STATUS_SERVER_ERROR;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `status` cannot simultaneously be greater than and less than `STATUS_SERVER_ERROR`
+
+error: boolean expression will never evaluate to 'true'
+  --> $DIR/const_comparisons.rs:63:5
+   |
+LL |     500 >= status_code && 600 < status_code; // Incorrect
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: since `500` < `600`, the expression evaluates to false for any value of `status_code`
+
+error: boolean expression will never evaluate to 'true'
+  --> $DIR/const_comparisons.rs:64:5
+   |
+LL |     500 >= status_code && status_code > 600; // Incorrect
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: since `500` < `600`, the expression evaluates to false for any value of `status_code`
+
+error: boolean expression will never evaluate to 'true'
+  --> $DIR/const_comparisons.rs:69:5
+   |
+LL |     500 >= status && 600 < status; // Incorrect
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: since `500` < `600`, the expression evaluates to false for any value of `status`
+
+error: boolean expression will never evaluate to 'true'
+  --> $DIR/const_comparisons.rs:70:5
+   |
+LL |     500 >= status && status > 600; // Incorrect
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: since `500` < `600`, the expression evaluates to false for any value of `status`
+
+error: right-hand side of `&&` operator has no effect
+  --> $DIR/const_comparisons.rs:73:5
+   |
+LL |     status_code < 200 && status_code <= 299;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: `if `status_code < 200` evaluates to true, status_code <= 299` will always evaluate to true as well
+  --> $DIR/const_comparisons.rs:73:23
+   |
+LL |     status_code < 200 && status_code <= 299;
+   |                       ^^^^^^^^^^^^^^^^^^^^^
+   = note: `-D clippy::redundant-comparisons` implied by `-D warnings`
+
+error: left-hand side of `&&` operator has no effect
+  --> $DIR/const_comparisons.rs:74:5
+   |
+LL |     status_code > 200 && status_code >= 299;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: `if `status_code >= 299` evaluates to true, status_code > 200` will always evaluate to true as well
+  --> $DIR/const_comparisons.rs:74:5
+   |
+LL |     status_code > 200 && status_code >= 299;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error: left-hand side of `&&` operator has no effect
+  --> $DIR/const_comparisons.rs:76:5
+   |
+LL |     status_code >= 500 && status_code > 500; // Useless left
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: `if `status_code > 500` evaluates to true, status_code >= 500` will always evaluate to true as well
+  --> $DIR/const_comparisons.rs:76:5
+   |
+LL |     status_code >= 500 && status_code > 500; // Useless left
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: right-hand side of `&&` operator has no effect
+  --> $DIR/const_comparisons.rs:77:5
+   |
+LL |     status_code > 500 && status_code >= 500; // Useless right
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: `if `status_code > 500` evaluates to true, status_code >= 500` will always evaluate to true as well
+  --> $DIR/const_comparisons.rs:77:23
+   |
+LL |     status_code > 500 && status_code >= 500; // Useless right
+   |                       ^^^^^^^^^^^^^^^^^^^^^
+
+error: left-hand side of `&&` operator has no effect
+  --> $DIR/const_comparisons.rs:78:5
+   |
+LL |     status_code <= 500 && status_code < 500; // Useless left
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: `if `status_code < 500` evaluates to true, status_code <= 500` will always evaluate to true as well
+  --> $DIR/const_comparisons.rs:78:5
+   |
+LL |     status_code <= 500 && status_code < 500; // Useless left
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: right-hand side of `&&` operator has no effect
+  --> $DIR/const_comparisons.rs:79:5
+   |
+LL |     status_code < 500 && status_code <= 500; // Useless right
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: `if `status_code < 500` evaluates to true, status_code <= 500` will always evaluate to true as well
+  --> $DIR/const_comparisons.rs:79:23
+   |
+LL |     status_code < 500 && status_code <= 500; // Useless right
+   |                       ^^^^^^^^^^^^^^^^^^^^^
+
+error: boolean expression will never evaluate to 'true'
+  --> $DIR/const_comparisons.rs:83:5
+   |
+LL |     name < "Jennifer" && name > "Shannon";
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: since `"Jennifer"` < `"Shannon"`, the expression evaluates to false for any value of `name`
+
+error: boolean expression will never evaluate to 'true'
+  --> $DIR/const_comparisons.rs:86:5
+   |
+LL |     numbers < [3, 4] && numbers > [5, 6];
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: since `[3, 4]` < `[5, 6]`, the expression evaluates to false for any value of `numbers`
+
+error: boolean expression will never evaluate to 'true'
+  --> $DIR/const_comparisons.rs:89:5
+   |
+LL |     letter < 'b' && letter > 'c';
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: since `'b'` < `'c'`, the expression evaluates to false for any value of `letter`
+
+error: boolean expression will never evaluate to 'true'
+  --> $DIR/const_comparisons.rs:92:5
+   |
+LL |     area < std::f32::consts::E && area > std::f32::consts::PI;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: since `std::f32::consts::E` < `std::f32::consts::PI`, the expression evaluates to false for any value of `area`
+
+error: aborting due to 25 previous errors
+
diff --git a/src/tools/clippy/tests/ui/expect.stderr b/src/tools/clippy/tests/ui/expect.stderr
index be340340d47..f787fa973a3 100644
--- a/src/tools/clippy/tests/ui/expect.stderr
+++ b/src/tools/clippy/tests/ui/expect.stderr
@@ -4,7 +4,7 @@ error: used `expect()` on an `Option` value
 LL |     let _ = opt.expect("");
    |             ^^^^^^^^^^^^^^
    |
-   = help: if this value is `None`, it will panic
+   = note: if this value is `None`, it will panic
    = note: `-D clippy::expect-used` implied by `-D warnings`
 
 error: used `expect()` on a `Result` value
@@ -13,7 +13,7 @@ error: used `expect()` on a `Result` value
 LL |     let _ = res.expect("");
    |             ^^^^^^^^^^^^^^
    |
-   = help: if this value is an `Err`, it will panic
+   = note: if this value is an `Err`, it will panic
 
 error: used `expect_err()` on a `Result` value
   --> $DIR/expect.rs:12:13
@@ -21,7 +21,7 @@ error: used `expect_err()` on a `Result` value
 LL |     let _ = res.expect_err("");
    |             ^^^^^^^^^^^^^^^^^^
    |
-   = help: if this value is an `Ok`, it will panic
+   = note: if this value is an `Ok`, it will panic
 
 error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui/filter_map_bool_then.fixed b/src/tools/clippy/tests/ui/filter_map_bool_then.fixed
index 3e72fee4b07..e5c9f783f6b 100644
--- a/src/tools/clippy/tests/ui/filter_map_bool_then.fixed
+++ b/src/tools/clippy/tests/ui/filter_map_bool_then.fixed
@@ -4,6 +4,7 @@
     clippy::clone_on_copy,
     clippy::map_identity,
     clippy::unnecessary_lazy_evaluations,
+    clippy::unnecessary_filter_map,
     unused
 )]
 #![warn(clippy::filter_map_bool_then)]
@@ -29,9 +30,18 @@ fn main() {
         .copied()
         .filter(|&i| i != 1000)
         .filter(|&i| (i.clone() % 2 == 0)).map(|i| i + 1);
+    // Despite this is non-copy, `is_copy` still returns true (at least now) because it's `&NonCopy`,
+    // and any `&` is `Copy`. So since we can dereference it in `filter` (since it's then `&&NonCopy`),
+    // we can lint this and still get the same input type.
+    // See: <https://doc.rust-lang.org/std/primitive.reference.html#trait-implementations-1>
+    let v = vec![NonCopy, NonCopy];
+    v.clone().iter().filter(|&i| (i == &NonCopy)).map(|i| i);
     // Do not lint
     let v = vec![NonCopy, NonCopy];
-    v.clone().iter().filter_map(|i| (i == &NonCopy).then(|| i));
+    v.clone().into_iter().filter_map(|i| (i == NonCopy).then(|| i));
+    // `&mut` is `!Copy`.
+    let v = vec![NonCopy, NonCopy];
+    v.clone().iter_mut().filter_map(|i| (i == &mut NonCopy).then(|| i));
     external! {
         let v = vec![1, 2, 3, 4, 5, 6];
         v.clone().into_iter().filter_map(|i| (i % 2 == 0).then(|| i + 1));
@@ -42,3 +52,7 @@ fn main() {
         v.clone().into_iter().filter_map(|i| (i % 2 == 0).then(|| i + 1));
     }
 }
+
+fn issue11309<'a>(iter: impl Iterator<Item = (&'a str, &'a str)>) -> Vec<&'a str> {
+    iter.filter_map(|(_, s): (&str, _)| Some(s)).collect()
+}
diff --git a/src/tools/clippy/tests/ui/filter_map_bool_then.rs b/src/tools/clippy/tests/ui/filter_map_bool_then.rs
index 38a04e57de4..7c9b99df78c 100644
--- a/src/tools/clippy/tests/ui/filter_map_bool_then.rs
+++ b/src/tools/clippy/tests/ui/filter_map_bool_then.rs
@@ -4,6 +4,7 @@
     clippy::clone_on_copy,
     clippy::map_identity,
     clippy::unnecessary_lazy_evaluations,
+    clippy::unnecessary_filter_map,
     unused
 )]
 #![warn(clippy::filter_map_bool_then)]
@@ -29,9 +30,18 @@ fn main() {
         .copied()
         .filter(|&i| i != 1000)
         .filter_map(|i| (i.clone() % 2 == 0).then(|| i + 1));
-    // Do not lint
+    // Despite this is non-copy, `is_copy` still returns true (at least now) because it's `&NonCopy`,
+    // and any `&` is `Copy`. So since we can dereference it in `filter` (since it's then `&&NonCopy`),
+    // we can lint this and still get the same input type.
+    // See: <https://doc.rust-lang.org/std/primitive.reference.html#trait-implementations-1>
     let v = vec![NonCopy, NonCopy];
     v.clone().iter().filter_map(|i| (i == &NonCopy).then(|| i));
+    // Do not lint
+    let v = vec![NonCopy, NonCopy];
+    v.clone().into_iter().filter_map(|i| (i == NonCopy).then(|| i));
+    // `&mut` is `!Copy`.
+    let v = vec![NonCopy, NonCopy];
+    v.clone().iter_mut().filter_map(|i| (i == &mut NonCopy).then(|| i));
     external! {
         let v = vec![1, 2, 3, 4, 5, 6];
         v.clone().into_iter().filter_map(|i| (i % 2 == 0).then(|| i + 1));
@@ -42,3 +52,7 @@ fn main() {
         v.clone().into_iter().filter_map(|i| (i % 2 == 0).then(|| i + 1));
     }
 }
+
+fn issue11309<'a>(iter: impl Iterator<Item = (&'a str, &'a str)>) -> Vec<&'a str> {
+    iter.filter_map(|(_, s): (&str, _)| Some(s)).collect()
+}
diff --git a/src/tools/clippy/tests/ui/filter_map_bool_then.stderr b/src/tools/clippy/tests/ui/filter_map_bool_then.stderr
index b411cd83dfd..fffa5252e5f 100644
--- a/src/tools/clippy/tests/ui/filter_map_bool_then.stderr
+++ b/src/tools/clippy/tests/ui/filter_map_bool_then.stderr
@@ -1,5 +1,5 @@
 error: usage of `bool::then` in `filter_map`
-  --> $DIR/filter_map_bool_then.rs:19:22
+  --> $DIR/filter_map_bool_then.rs:20:22
    |
 LL |     v.clone().iter().filter_map(|i| (i % 2 == 0).then(|| i + 1));
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `filter` then `map` instead: `filter(|&i| (i % 2 == 0)).map(|i| i + 1)`
@@ -7,28 +7,34 @@ LL |     v.clone().iter().filter_map(|i| (i % 2 == 0).then(|| i + 1));
    = note: `-D clippy::filter-map-bool-then` implied by `-D warnings`
 
 error: usage of `bool::then` in `filter_map`
-  --> $DIR/filter_map_bool_then.rs:20:27
+  --> $DIR/filter_map_bool_then.rs:21:27
    |
 LL |     v.clone().into_iter().filter_map(|i| (i % 2 == 0).then(|| i + 1));
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `filter` then `map` instead: `filter(|&i| (i % 2 == 0)).map(|i| i + 1)`
 
 error: usage of `bool::then` in `filter_map`
-  --> $DIR/filter_map_bool_then.rs:23:10
+  --> $DIR/filter_map_bool_then.rs:24:10
    |
 LL |         .filter_map(|i| -> Option<_> { (i % 2 == 0).then(|| i + 1) });
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `filter` then `map` instead: `filter(|&i| (i % 2 == 0)).map(|i| i + 1)`
 
 error: usage of `bool::then` in `filter_map`
-  --> $DIR/filter_map_bool_then.rs:27:10
+  --> $DIR/filter_map_bool_then.rs:28:10
    |
 LL |         .filter_map(|i| (i % 2 == 0).then(|| i + 1));
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `filter` then `map` instead: `filter(|&i| (i % 2 == 0)).map(|i| i + 1)`
 
 error: usage of `bool::then` in `filter_map`
-  --> $DIR/filter_map_bool_then.rs:31:10
+  --> $DIR/filter_map_bool_then.rs:32:10
    |
 LL |         .filter_map(|i| (i.clone() % 2 == 0).then(|| i + 1));
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `filter` then `map` instead: `filter(|&i| (i.clone() % 2 == 0)).map(|i| i + 1)`
 
-error: aborting due to 5 previous errors
+error: usage of `bool::then` in `filter_map`
+  --> $DIR/filter_map_bool_then.rs:38:22
+   |
+LL |     v.clone().iter().filter_map(|i| (i == &NonCopy).then(|| i));
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `filter` then `map` instead: `filter(|&i| (i == &NonCopy)).map(|i| i)`
+
+error: aborting due to 6 previous errors
 
diff --git a/src/tools/clippy/tests/ui/get_unwrap.stderr b/src/tools/clippy/tests/ui/get_unwrap.stderr
index c567ed319b5..19dc9071fe7 100644
--- a/src/tools/clippy/tests/ui/get_unwrap.stderr
+++ b/src/tools/clippy/tests/ui/get_unwrap.stderr
@@ -16,7 +16,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = boxed_slice.get(1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
    = note: `-D clippy::unwrap-used` implied by `-D warnings`
 
 error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
@@ -31,7 +32,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_slice.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
   --> $DIR/get_unwrap.rs:40:17
@@ -45,7 +47,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_vec.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
   --> $DIR/get_unwrap.rs:41:17
@@ -59,7 +62,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_vecdeque.get(0).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise
   --> $DIR/get_unwrap.rs:42:17
@@ -73,7 +77,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_hashmap.get(&1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise
   --> $DIR/get_unwrap.rs:43:17
@@ -87,7 +92,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_btreemap.get(&1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
   --> $DIR/get_unwrap.rs:47:21
@@ -101,7 +107,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _: u8 = *boxed_slice.get(1).unwrap();
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
   --> $DIR/get_unwrap.rs:52:9
@@ -115,7 +122,8 @@ error: used `unwrap()` on an `Option` value
 LL |         *boxed_slice.get_mut(0).unwrap() = 1;
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
   --> $DIR/get_unwrap.rs:53:9
@@ -129,7 +137,8 @@ error: used `unwrap()` on an `Option` value
 LL |         *some_slice.get_mut(0).unwrap() = 1;
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
   --> $DIR/get_unwrap.rs:54:9
@@ -143,7 +152,8 @@ error: used `unwrap()` on an `Option` value
 LL |         *some_vec.get_mut(0).unwrap() = 1;
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
   --> $DIR/get_unwrap.rs:55:9
@@ -157,7 +167,8 @@ error: used `unwrap()` on an `Option` value
 LL |         *some_vecdeque.get_mut(0).unwrap() = 1;
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
   --> $DIR/get_unwrap.rs:67:17
@@ -171,7 +182,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_vec.get(0..1).unwrap().to_vec();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
   --> $DIR/get_unwrap.rs:68:17
@@ -185,7 +197,8 @@ error: used `unwrap()` on an `Option` value
 LL |         let _ = some_vec.get_mut(0..1).unwrap().to_vec();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
   --> $DIR/get_unwrap.rs:78:24
diff --git a/src/tools/clippy/tests/ui/ignored_unit_patterns.fixed b/src/tools/clippy/tests/ui/ignored_unit_patterns.fixed
new file mode 100644
index 00000000000..492219fe447
--- /dev/null
+++ b/src/tools/clippy/tests/ui/ignored_unit_patterns.fixed
@@ -0,0 +1,17 @@
+//@run-rustfix
+
+#![warn(clippy::ignored_unit_patterns)]
+#![allow(clippy::redundant_pattern_matching, clippy::single_match)]
+
+fn foo() -> Result<(), ()> {
+    unimplemented!()
+}
+
+fn main() {
+    match foo() {
+        Ok(()) => {},
+        Err(()) => {},
+    }
+    if let Ok(()) = foo() {}
+    let _ = foo().map_err(|()| todo!());
+}
diff --git a/src/tools/clippy/tests/ui/ignored_unit_patterns.rs b/src/tools/clippy/tests/ui/ignored_unit_patterns.rs
new file mode 100644
index 00000000000..90af36f8e5e
--- /dev/null
+++ b/src/tools/clippy/tests/ui/ignored_unit_patterns.rs
@@ -0,0 +1,17 @@
+//@run-rustfix
+
+#![warn(clippy::ignored_unit_patterns)]
+#![allow(clippy::redundant_pattern_matching, clippy::single_match)]
+
+fn foo() -> Result<(), ()> {
+    unimplemented!()
+}
+
+fn main() {
+    match foo() {
+        Ok(_) => {},
+        Err(_) => {},
+    }
+    if let Ok(_) = foo() {}
+    let _ = foo().map_err(|_| todo!());
+}
diff --git a/src/tools/clippy/tests/ui/ignored_unit_patterns.stderr b/src/tools/clippy/tests/ui/ignored_unit_patterns.stderr
new file mode 100644
index 00000000000..8feea3cc2a8
--- /dev/null
+++ b/src/tools/clippy/tests/ui/ignored_unit_patterns.stderr
@@ -0,0 +1,28 @@
+error: matching over `()` is more explicit
+  --> $DIR/ignored_unit_patterns.rs:12:12
+   |
+LL |         Ok(_) => {},
+   |            ^ help: use `()` instead of `_`: `()`
+   |
+   = note: `-D clippy::ignored-unit-patterns` implied by `-D warnings`
+
+error: matching over `()` is more explicit
+  --> $DIR/ignored_unit_patterns.rs:13:13
+   |
+LL |         Err(_) => {},
+   |             ^ help: use `()` instead of `_`: `()`
+
+error: matching over `()` is more explicit
+  --> $DIR/ignored_unit_patterns.rs:15:15
+   |
+LL |     if let Ok(_) = foo() {}
+   |               ^ help: use `()` instead of `_`: `()`
+
+error: matching over `()` is more explicit
+  --> $DIR/ignored_unit_patterns.rs:16:28
+   |
+LL |     let _ = foo().map_err(|_| todo!());
+   |                            ^ help: use `()` instead of `_`: `()`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/mut_reference.rs b/src/tools/clippy/tests/ui/mut_reference.rs
index 73906121c40..00661c51a78 100644
--- a/src/tools/clippy/tests/ui/mut_reference.rs
+++ b/src/tools/clippy/tests/ui/mut_reference.rs
@@ -1,8 +1,21 @@
-#![allow(unused_variables)]
+#![allow(unused_variables, dead_code)]
 
 fn takes_an_immutable_reference(a: &i32) {}
 fn takes_a_mutable_reference(a: &mut i32) {}
 
+mod issue11268 {
+    macro_rules! x {
+        ($f:expr) => {
+            $f(&mut 1);
+        };
+    }
+
+    fn f() {
+        x!(super::takes_an_immutable_reference);
+        x!(super::takes_a_mutable_reference);
+    }
+}
+
 struct MyStruct;
 
 impl MyStruct {
diff --git a/src/tools/clippy/tests/ui/mut_reference.stderr b/src/tools/clippy/tests/ui/mut_reference.stderr
index 1fdfbf9227e..d8a71d26461 100644
--- a/src/tools/clippy/tests/ui/mut_reference.stderr
+++ b/src/tools/clippy/tests/ui/mut_reference.stderr
@@ -1,5 +1,5 @@
 error: the function `takes_an_immutable_reference` doesn't need a mutable reference
-  --> $DIR/mut_reference.rs:17:34
+  --> $DIR/mut_reference.rs:30:34
    |
 LL |     takes_an_immutable_reference(&mut 42);
    |                                  ^^^^^^^
@@ -7,19 +7,19 @@ LL |     takes_an_immutable_reference(&mut 42);
    = note: `-D clippy::unnecessary-mut-passed` implied by `-D warnings`
 
 error: the function `as_ptr` doesn't need a mutable reference
-  --> $DIR/mut_reference.rs:19:12
+  --> $DIR/mut_reference.rs:32:12
    |
 LL |     as_ptr(&mut 42);
    |            ^^^^^^^
 
 error: the method `takes_an_immutable_reference` doesn't need a mutable reference
-  --> $DIR/mut_reference.rs:23:44
+  --> $DIR/mut_reference.rs:36:44
    |
 LL |     my_struct.takes_an_immutable_reference(&mut 42);
    |                                            ^^^^^^^
 
 error: this argument is a mutable reference, but not used mutably
-  --> $DIR/mut_reference.rs:11:44
+  --> $DIR/mut_reference.rs:24:44
    |
 LL |     fn takes_a_mutable_reference(&self, a: &mut i32) {}
    |                                            ^^^^^^^^ help: consider changing to: `&i32`
diff --git a/src/tools/clippy/tests/ui/ptr_as_ptr.fixed b/src/tools/clippy/tests/ui/ptr_as_ptr.fixed
index 26a64c861cf..84babb97416 100644
--- a/src/tools/clippy/tests/ui/ptr_as_ptr.fixed
+++ b/src/tools/clippy/tests/ui/ptr_as_ptr.fixed
@@ -3,8 +3,22 @@
 
 #![warn(clippy::ptr_as_ptr)]
 
+#[macro_use]
 extern crate proc_macros;
-use proc_macros::{external, inline_macros};
+
+mod issue_11278_a {
+    #[derive(Debug)]
+    pub struct T<D: std::fmt::Debug + ?Sized> {
+        pub p: D,
+    }
+}
+
+mod issue_11278_b {
+    pub fn f(o: &mut super::issue_11278_a::T<dyn std::fmt::Debug>) -> super::issue_11278_a::T<String> {
+        // Retain `super`
+        *unsafe { Box::from_raw(Box::into_raw(Box::new(o)).cast::<super::issue_11278_a::T<String>>()) }
+    }
+}
 
 #[inline_macros]
 fn main() {
diff --git a/src/tools/clippy/tests/ui/ptr_as_ptr.rs b/src/tools/clippy/tests/ui/ptr_as_ptr.rs
index ea40d494733..34fd76428b2 100644
--- a/src/tools/clippy/tests/ui/ptr_as_ptr.rs
+++ b/src/tools/clippy/tests/ui/ptr_as_ptr.rs
@@ -3,8 +3,22 @@
 
 #![warn(clippy::ptr_as_ptr)]
 
+#[macro_use]
 extern crate proc_macros;
-use proc_macros::{external, inline_macros};
+
+mod issue_11278_a {
+    #[derive(Debug)]
+    pub struct T<D: std::fmt::Debug + ?Sized> {
+        pub p: D,
+    }
+}
+
+mod issue_11278_b {
+    pub fn f(o: &mut super::issue_11278_a::T<dyn std::fmt::Debug>) -> super::issue_11278_a::T<String> {
+        // Retain `super`
+        *unsafe { Box::from_raw(Box::into_raw(Box::new(o)) as *mut super::issue_11278_a::T<String>) }
+    }
+}
 
 #[inline_macros]
 fn main() {
diff --git a/src/tools/clippy/tests/ui/ptr_as_ptr.stderr b/src/tools/clippy/tests/ui/ptr_as_ptr.stderr
index 78d733994ac..e64f3351505 100644
--- a/src/tools/clippy/tests/ui/ptr_as_ptr.stderr
+++ b/src/tools/clippy/tests/ui/ptr_as_ptr.stderr
@@ -1,37 +1,43 @@
 error: `as` casting between raw pointers without changing its mutability
-  --> $DIR/ptr_as_ptr.rs:14:13
+  --> $DIR/ptr_as_ptr.rs:19:33
    |
-LL |     let _ = ptr as *const i32;
-   |             ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()`
+LL |         *unsafe { Box::from_raw(Box::into_raw(Box::new(o)) as *mut super::issue_11278_a::T<String>) }
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `Box::into_raw(Box::new(o)).cast::<super::issue_11278_a::T<String>>()`
    |
    = note: `-D clippy::ptr-as-ptr` implied by `-D warnings`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> $DIR/ptr_as_ptr.rs:15:13
+  --> $DIR/ptr_as_ptr.rs:28:13
+   |
+LL |     let _ = ptr as *const i32;
+   |             ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()`
+
+error: `as` casting between raw pointers without changing its mutability
+  --> $DIR/ptr_as_ptr.rs:29:13
    |
 LL |     let _ = mut_ptr as *mut i32;
    |             ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> $DIR/ptr_as_ptr.rs:20:17
+  --> $DIR/ptr_as_ptr.rs:34:17
    |
 LL |         let _ = *ptr_ptr as *const i32;
    |                 ^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `(*ptr_ptr).cast::<i32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> $DIR/ptr_as_ptr.rs:33:25
+  --> $DIR/ptr_as_ptr.rs:47:25
    |
 LL |     let _: *const i32 = ptr as *const _;
    |                         ^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> $DIR/ptr_as_ptr.rs:34:23
+  --> $DIR/ptr_as_ptr.rs:48:23
    |
 LL |     let _: *mut i32 = mut_ptr as _;
    |                       ^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> $DIR/ptr_as_ptr.rs:37:21
+  --> $DIR/ptr_as_ptr.rs:51:21
    |
 LL |     let _ = inline!($ptr as *const i32);
    |                     ^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `$ptr.cast::<i32>()`
@@ -39,16 +45,16 @@ LL |     let _ = inline!($ptr as *const i32);
    = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: `as` casting between raw pointers without changing its mutability
-  --> $DIR/ptr_as_ptr.rs:58:13
+  --> $DIR/ptr_as_ptr.rs:72:13
    |
 LL |     let _ = ptr as *const i32;
    |             ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> $DIR/ptr_as_ptr.rs:59:13
+  --> $DIR/ptr_as_ptr.rs:73:13
    |
 LL |     let _ = mut_ptr as *mut i32;
    |             ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()`
 
-error: aborting due to 8 previous errors
+error: aborting due to 9 previous errors
 
diff --git a/src/tools/clippy/tests/ui/question_mark.fixed b/src/tools/clippy/tests/ui/question_mark.fixed
index 2d8920ccc42..20b9e42a7aa 100644
--- a/src/tools/clippy/tests/ui/question_mark.fixed
+++ b/src/tools/clippy/tests/ui/question_mark.fixed
@@ -138,6 +138,23 @@ fn result_func(x: Result<i32, i32>) -> Result<i32, i32> {
     // no warning
     let _ = if let Err(e) = x { Err(e) } else { Ok(0) };
 
+    // issue #11283
+    // no warning
+    #[warn(clippy::question_mark_used)]
+    {
+        if let Err(err) = Ok(()) {
+            return Err(err);
+        }
+
+        if Err::<i32, _>(0).is_err() {
+            return Err(0);
+        } else {
+            return Ok(0);
+        }
+
+        unreachable!()
+    }
+
     Ok(y)
 }
 
diff --git a/src/tools/clippy/tests/ui/question_mark.rs b/src/tools/clippy/tests/ui/question_mark.rs
index 69451c17ee7..8bdafd46e8f 100644
--- a/src/tools/clippy/tests/ui/question_mark.rs
+++ b/src/tools/clippy/tests/ui/question_mark.rs
@@ -170,6 +170,23 @@ fn result_func(x: Result<i32, i32>) -> Result<i32, i32> {
     // no warning
     let _ = if let Err(e) = x { Err(e) } else { Ok(0) };
 
+    // issue #11283
+    // no warning
+    #[warn(clippy::question_mark_used)]
+    {
+        if let Err(err) = Ok(()) {
+            return Err(err);
+        }
+
+        if Err::<i32, _>(0).is_err() {
+            return Err(0);
+        } else {
+            return Ok(0);
+        }
+
+        unreachable!()
+    }
+
     Ok(y)
 }
 
diff --git a/src/tools/clippy/tests/ui/question_mark.stderr b/src/tools/clippy/tests/ui/question_mark.stderr
index 2cfd7586308..62489c8c8c4 100644
--- a/src/tools/clippy/tests/ui/question_mark.stderr
+++ b/src/tools/clippy/tests/ui/question_mark.stderr
@@ -115,7 +115,7 @@ LL | |     }
    | |_____^ help: replace it with: `x?;`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:197:5
+  --> $DIR/question_mark.rs:214:5
    |
 LL | /     if let Err(err) = func_returning_result() {
 LL | |         return Err(err);
@@ -123,7 +123,7 @@ LL | |     }
    | |_____^ help: replace it with: `func_returning_result()?;`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:204:5
+  --> $DIR/question_mark.rs:221:5
    |
 LL | /     if let Err(err) = func_returning_result() {
 LL | |         return Err(err);
@@ -131,7 +131,7 @@ LL | |     }
    | |_____^ help: replace it with: `func_returning_result()?;`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:281:13
+  --> $DIR/question_mark.rs:298:13
    |
 LL | /             if a.is_none() {
 LL | |                 return None;
diff --git a/src/tools/clippy/tests/ui/range_contains.fixed b/src/tools/clippy/tests/ui/range_contains.fixed
index 0a92ee7c8dd..47c5248118e 100644
--- a/src/tools/clippy/tests/ui/range_contains.fixed
+++ b/src/tools/clippy/tests/ui/range_contains.fixed
@@ -5,6 +5,8 @@
 #![allow(clippy::no_effect)]
 #![allow(clippy::short_circuit_statement)]
 #![allow(clippy::unnecessary_operation)]
+#![allow(clippy::impossible_comparisons)]
+#![allow(clippy::redundant_comparisons)]
 
 fn main() {
     let x = 9_i32;
diff --git a/src/tools/clippy/tests/ui/range_contains.rs b/src/tools/clippy/tests/ui/range_contains.rs
index 7a83be60957..a35315a649d 100644
--- a/src/tools/clippy/tests/ui/range_contains.rs
+++ b/src/tools/clippy/tests/ui/range_contains.rs
@@ -5,6 +5,8 @@
 #![allow(clippy::no_effect)]
 #![allow(clippy::short_circuit_statement)]
 #![allow(clippy::unnecessary_operation)]
+#![allow(clippy::impossible_comparisons)]
+#![allow(clippy::redundant_comparisons)]
 
 fn main() {
     let x = 9_i32;
diff --git a/src/tools/clippy/tests/ui/range_contains.stderr b/src/tools/clippy/tests/ui/range_contains.stderr
index ea34023a466..1265db695bf 100644
--- a/src/tools/clippy/tests/ui/range_contains.stderr
+++ b/src/tools/clippy/tests/ui/range_contains.stderr
@@ -1,5 +1,5 @@
 error: manual `Range::contains` implementation
-  --> $DIR/range_contains.rs:13:5
+  --> $DIR/range_contains.rs:15:5
    |
 LL |     x >= 8 && x < 12;
    |     ^^^^^^^^^^^^^^^^ help: use: `(8..12).contains(&x)`
@@ -7,121 +7,121 @@ LL |     x >= 8 && x < 12;
    = note: `-D clippy::manual-range-contains` implied by `-D warnings`
 
 error: manual `Range::contains` implementation
-  --> $DIR/range_contains.rs:14:5
+  --> $DIR/range_contains.rs:16:5
    |
 LL |     x < 42 && x >= 21;
    |     ^^^^^^^^^^^^^^^^^ help: use: `(21..42).contains(&x)`
 
 error: manual `Range::contains` implementation
-  --> $DIR/range_contains.rs:15:5
+  --> $DIR/range_contains.rs:17:5
    |
 LL |     100 > x && 1 <= x;
    |     ^^^^^^^^^^^^^^^^^ help: use: `(1..100).contains(&x)`
 
 error: manual `RangeInclusive::contains` implementation
-  --> $DIR/range_contains.rs:18:5
+  --> $DIR/range_contains.rs:20:5
    |
 LL |     x >= 9 && x <= 99;
    |     ^^^^^^^^^^^^^^^^^ help: use: `(9..=99).contains(&x)`
 
 error: manual `RangeInclusive::contains` implementation
-  --> $DIR/range_contains.rs:19:5
+  --> $DIR/range_contains.rs:21:5
    |
 LL |     x <= 33 && x >= 1;
    |     ^^^^^^^^^^^^^^^^^ help: use: `(1..=33).contains(&x)`
 
 error: manual `RangeInclusive::contains` implementation
-  --> $DIR/range_contains.rs:20:5
+  --> $DIR/range_contains.rs:22:5
    |
 LL |     999 >= x && 1 <= x;
    |     ^^^^^^^^^^^^^^^^^^ help: use: `(1..=999).contains(&x)`
 
 error: manual `!Range::contains` implementation
-  --> $DIR/range_contains.rs:23:5
+  --> $DIR/range_contains.rs:25:5
    |
 LL |     x < 8 || x >= 12;
    |     ^^^^^^^^^^^^^^^^ help: use: `!(8..12).contains(&x)`
 
 error: manual `!Range::contains` implementation
-  --> $DIR/range_contains.rs:24:5
+  --> $DIR/range_contains.rs:26:5
    |
 LL |     x >= 42 || x < 21;
    |     ^^^^^^^^^^^^^^^^^ help: use: `!(21..42).contains(&x)`
 
 error: manual `!Range::contains` implementation
-  --> $DIR/range_contains.rs:25:5
+  --> $DIR/range_contains.rs:27:5
    |
 LL |     100 <= x || 1 > x;
    |     ^^^^^^^^^^^^^^^^^ help: use: `!(1..100).contains(&x)`
 
 error: manual `!RangeInclusive::contains` implementation
-  --> $DIR/range_contains.rs:28:5
+  --> $DIR/range_contains.rs:30:5
    |
 LL |     x < 9 || x > 99;
    |     ^^^^^^^^^^^^^^^ help: use: `!(9..=99).contains(&x)`
 
 error: manual `!RangeInclusive::contains` implementation
-  --> $DIR/range_contains.rs:29:5
+  --> $DIR/range_contains.rs:31:5
    |
 LL |     x > 33 || x < 1;
    |     ^^^^^^^^^^^^^^^ help: use: `!(1..=33).contains(&x)`
 
 error: manual `!RangeInclusive::contains` implementation
-  --> $DIR/range_contains.rs:30:5
+  --> $DIR/range_contains.rs:32:5
    |
 LL |     999 < x || 1 > x;
    |     ^^^^^^^^^^^^^^^^ help: use: `!(1..=999).contains(&x)`
 
 error: manual `Range::contains` implementation
-  --> $DIR/range_contains.rs:45:5
+  --> $DIR/range_contains.rs:47:5
    |
 LL |     y >= 0. && y < 1.;
    |     ^^^^^^^^^^^^^^^^^ help: use: `(0. ..1.).contains(&y)`
 
 error: manual `!RangeInclusive::contains` implementation
-  --> $DIR/range_contains.rs:46:5
+  --> $DIR/range_contains.rs:48:5
    |
 LL |     y < 0. || y > 1.;
    |     ^^^^^^^^^^^^^^^^ help: use: `!(0. ..=1.).contains(&y)`
 
 error: manual `RangeInclusive::contains` implementation
-  --> $DIR/range_contains.rs:49:5
+  --> $DIR/range_contains.rs:51:5
    |
 LL |     x >= -10 && x <= 10;
    |     ^^^^^^^^^^^^^^^^^^^ help: use: `(-10..=10).contains(&x)`
 
 error: manual `RangeInclusive::contains` implementation
-  --> $DIR/range_contains.rs:51:5
+  --> $DIR/range_contains.rs:53:5
    |
 LL |     y >= -3. && y <= 3.;
    |     ^^^^^^^^^^^^^^^^^^^ help: use: `(-3. ..=3.).contains(&y)`
 
 error: manual `RangeInclusive::contains` implementation
-  --> $DIR/range_contains.rs:56:30
+  --> $DIR/range_contains.rs:58:30
    |
 LL |     (x >= 0) && (x <= 10) && (z >= 0) && (z <= 10);
    |                              ^^^^^^^^^^^^^^^^^^^^^ help: use: `(0..=10).contains(&z)`
 
 error: manual `RangeInclusive::contains` implementation
-  --> $DIR/range_contains.rs:56:5
+  --> $DIR/range_contains.rs:58:5
    |
 LL |     (x >= 0) && (x <= 10) && (z >= 0) && (z <= 10);
    |     ^^^^^^^^^^^^^^^^^^^^^ help: use: `(0..=10).contains(&x)`
 
 error: manual `!Range::contains` implementation
-  --> $DIR/range_contains.rs:57:29
+  --> $DIR/range_contains.rs:59:29
    |
 LL |     (x < 0) || (x >= 10) || (z < 0) || (z >= 10);
    |                             ^^^^^^^^^^^^^^^^^^^^ help: use: `!(0..10).contains(&z)`
 
 error: manual `!Range::contains` implementation
-  --> $DIR/range_contains.rs:57:5
+  --> $DIR/range_contains.rs:59:5
    |
 LL |     (x < 0) || (x >= 10) || (z < 0) || (z >= 10);
    |     ^^^^^^^^^^^^^^^^^^^^ help: use: `!(0..10).contains(&x)`
 
 error: manual `Range::contains` implementation
-  --> $DIR/range_contains.rs:76:5
+  --> $DIR/range_contains.rs:78:5
    |
 LL |     x >= 8 && x < 35;
    |     ^^^^^^^^^^^^^^^^ help: use: `(8..35).contains(&x)`
diff --git a/src/tools/clippy/tests/ui/redundant_guards.fixed b/src/tools/clippy/tests/ui/redundant_guards.fixed
index 77ac7666864..49d7336ee37 100644
--- a/src/tools/clippy/tests/ui/redundant_guards.fixed
+++ b/src/tools/clippy/tests/ui/redundant_guards.fixed
@@ -15,6 +15,19 @@ struct B {
 
 struct C(u32, u32);
 
+#[derive(PartialEq)]
+struct FloatWrapper(f32);
+fn issue11304() {
+    match 0.1 {
+        x if x == 0.0 => todo!(),
+        _ => todo!(),
+    }
+    match FloatWrapper(0.1) {
+        x if x == FloatWrapper(0.0) => todo!(),
+        _ => todo!(),
+    }
+}
+
 fn main() {
     let c = C(1, 2);
     match c {
diff --git a/src/tools/clippy/tests/ui/redundant_guards.rs b/src/tools/clippy/tests/ui/redundant_guards.rs
index b072e4ea14d..87761010de2 100644
--- a/src/tools/clippy/tests/ui/redundant_guards.rs
+++ b/src/tools/clippy/tests/ui/redundant_guards.rs
@@ -15,6 +15,19 @@ struct B {
 
 struct C(u32, u32);
 
+#[derive(PartialEq)]
+struct FloatWrapper(f32);
+fn issue11304() {
+    match 0.1 {
+        x if x == 0.0 => todo!(),
+        _ => todo!(),
+    }
+    match FloatWrapper(0.1) {
+        x if x == FloatWrapper(0.0) => todo!(),
+        _ => todo!(),
+    }
+}
+
 fn main() {
     let c = C(1, 2);
     match c {
diff --git a/src/tools/clippy/tests/ui/redundant_guards.stderr b/src/tools/clippy/tests/ui/redundant_guards.stderr
index c2a92071d1d..5bdf43d23c5 100644
--- a/src/tools/clippy/tests/ui/redundant_guards.stderr
+++ b/src/tools/clippy/tests/ui/redundant_guards.stderr
@@ -1,5 +1,5 @@
 error: redundant guard
-  --> $DIR/redundant_guards.rs:21:20
+  --> $DIR/redundant_guards.rs:34:20
    |
 LL |         C(x, y) if let 1 = y => ..,
    |                    ^^^^^^^^^
@@ -12,7 +12,7 @@ LL +         C(x, 1) => ..,
    |
 
 error: redundant guard
-  --> $DIR/redundant_guards.rs:27:20
+  --> $DIR/redundant_guards.rs:40:20
    |
 LL |         Some(x) if matches!(x, Some(1) if true) => ..,
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -23,7 +23,7 @@ LL |         Some(Some(1)) if true => ..,
    |              ~~~~~~~  ~~~~~~~
 
 error: redundant guard
-  --> $DIR/redundant_guards.rs:28:20
+  --> $DIR/redundant_guards.rs:41:20
    |
 LL |         Some(x) if matches!(x, Some(1)) => {
    |                    ^^^^^^^^^^^^^^^^^^^^
@@ -35,7 +35,7 @@ LL +         Some(Some(1)) => {
    |
 
 error: redundant guard
-  --> $DIR/redundant_guards.rs:32:20
+  --> $DIR/redundant_guards.rs:45:20
    |
 LL |         Some(x) if let Some(1) = x => ..,
    |                    ^^^^^^^^^^^^^^^
@@ -47,7 +47,7 @@ LL +         Some(Some(1)) => ..,
    |
 
 error: redundant guard
-  --> $DIR/redundant_guards.rs:33:20
+  --> $DIR/redundant_guards.rs:46:20
    |
 LL |         Some(x) if x == Some(2) => ..,
    |                    ^^^^^^^^^^^^
@@ -59,7 +59,7 @@ LL +         Some(Some(2)) => ..,
    |
 
 error: redundant guard
-  --> $DIR/redundant_guards.rs:56:20
+  --> $DIR/redundant_guards.rs:69:20
    |
 LL |         B { e } if matches!(e, Some(A(2))) => ..,
    |                    ^^^^^^^^^^^^^^^^^^^^^^^
@@ -71,7 +71,7 @@ LL +         B { e: Some(A(2)) } => ..,
    |
 
 error: redundant guard
-  --> $DIR/redundant_guards.rs:93:20
+  --> $DIR/redundant_guards.rs:106:20
    |
 LL |         E::A(y) if y == "not from an or pattern" => {},
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -83,7 +83,7 @@ LL +         E::A("not from an or pattern") => {},
    |
 
 error: redundant guard
-  --> $DIR/redundant_guards.rs:100:14
+  --> $DIR/redundant_guards.rs:113:14
    |
 LL |         x if matches!(x, Some(0)) => ..,
    |              ^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/redundant_locals.rs b/src/tools/clippy/tests/ui/redundant_locals.rs
index e74c78a50b6..80af38f47b8 100644
--- a/src/tools/clippy/tests/ui/redundant_locals.rs
+++ b/src/tools/clippy/tests/ui/redundant_locals.rs
@@ -27,6 +27,15 @@ fn downgraded_mutability() {
     let x = x;
 }
 
+// see #11290
+fn shadow_mutation() {
+    let mut x = 1;
+    {
+        let mut x = x;
+        x = 2;
+    }
+}
+
 fn coercion(par: &mut i32) {
     let par: &i32 = par;
 
diff --git a/src/tools/clippy/tests/ui/redundant_locals.stderr b/src/tools/clippy/tests/ui/redundant_locals.stderr
index df07dd2f453..587de057524 100644
--- a/src/tools/clippy/tests/ui/redundant_locals.stderr
+++ b/src/tools/clippy/tests/ui/redundant_locals.stderr
@@ -20,7 +20,7 @@ LL |     let mut x = x;
    = help: remove the redefinition of `x`
 
 error: redundant redefinition of a binding
-  --> $DIR/redundant_locals.rs:37:14
+  --> $DIR/redundant_locals.rs:46:14
    |
 LL | fn parameter(x: i32) {
    |              ^
@@ -30,7 +30,7 @@ LL |     let x = x;
    = help: remove the redefinition of `x`
 
 error: redundant redefinition of a binding
-  --> $DIR/redundant_locals.rs:42:9
+  --> $DIR/redundant_locals.rs:51:9
    |
 LL |     let x = 1;
    |         ^
@@ -40,7 +40,7 @@ LL |     let x = x;
    = help: remove the redefinition of `x`
 
 error: redundant redefinition of a binding
-  --> $DIR/redundant_locals.rs:43:9
+  --> $DIR/redundant_locals.rs:52:9
    |
 LL |     let x = x;
    |         ^
@@ -50,7 +50,7 @@ LL |     let x = x;
    = help: remove the redefinition of `x`
 
 error: redundant redefinition of a binding
-  --> $DIR/redundant_locals.rs:44:9
+  --> $DIR/redundant_locals.rs:53:9
    |
 LL |     let x = x;
    |         ^
@@ -60,7 +60,7 @@ LL |     let x = x;
    = help: remove the redefinition of `x`
 
 error: redundant redefinition of a binding
-  --> $DIR/redundant_locals.rs:45:9
+  --> $DIR/redundant_locals.rs:54:9
    |
 LL |     let x = x;
    |         ^
@@ -70,7 +70,7 @@ LL |     let x = x;
    = help: remove the redefinition of `x`
 
 error: redundant redefinition of a binding
-  --> $DIR/redundant_locals.rs:50:9
+  --> $DIR/redundant_locals.rs:59:9
    |
 LL |     let a = 1;
    |         ^
@@ -81,7 +81,7 @@ LL |     let a = a;
    = help: remove the redefinition of `a`
 
 error: redundant redefinition of a binding
-  --> $DIR/redundant_locals.rs:51:9
+  --> $DIR/redundant_locals.rs:60:9
    |
 LL |     let b = 2;
    |         ^
@@ -92,7 +92,7 @@ LL |     let b = b;
    = help: remove the redefinition of `b`
 
 error: redundant redefinition of a binding
-  --> $DIR/redundant_locals.rs:58:13
+  --> $DIR/redundant_locals.rs:67:13
    |
 LL |         let x = 1;
    |             ^
@@ -102,7 +102,7 @@ LL |         let x = x;
    = help: remove the redefinition of `x`
 
 error: redundant redefinition of a binding
-  --> $DIR/redundant_locals.rs:65:13
+  --> $DIR/redundant_locals.rs:74:13
    |
 LL |         let x = 1;
    |             ^
@@ -112,7 +112,7 @@ LL |         let x = x;
    = help: remove the redefinition of `x`
 
 error: redundant redefinition of a binding
-  --> $DIR/redundant_locals.rs:68:6
+  --> $DIR/redundant_locals.rs:77:6
    |
 LL |     |x: i32| {
    |      ^
@@ -122,7 +122,7 @@ LL |         let x = x;
    = help: remove the redefinition of `x`
 
 error: redundant redefinition of a binding
-  --> $DIR/redundant_locals.rs:85:9
+  --> $DIR/redundant_locals.rs:94:9
    |
 LL |     let x = 1;
    |         ^
diff --git a/src/tools/clippy/tests/ui/redundant_type_annotations.rs b/src/tools/clippy/tests/ui/redundant_type_annotations.rs
index cc507b8d658..09dbd3c9b39 100644
--- a/src/tools/clippy/tests/ui/redundant_type_annotations.rs
+++ b/src/tools/clippy/tests/ui/redundant_type_annotations.rs
@@ -6,8 +6,8 @@ struct Cake<T> {
     _data: T,
 }
 
-fn make_something<T: Default>() -> T {
-    T::default()
+fn make_something<T>() -> T {
+    unimplemented!()
 }
 
 fn make_cake<T: Default>() -> Cake<T> {
@@ -117,7 +117,15 @@ fn test_non_locals() {
     let _closure_arg = |x: u32| x;
 }
 
-fn test_complex_types() {
+trait Trait {
+    type AssocTy;
+}
+
+impl Trait for () {
+    type AssocTy = String;
+}
+
+fn test_complex_types<T>() {
     // Shouldn't be lint, since the literal will be i32 otherwise
     let _u8: u8 = 128;
 
@@ -135,6 +143,10 @@ fn test_complex_types() {
 
     // Shouldn't be lint
     let _array: [u32; 2] = [8, 9];
+
+    let ty_param: T = make_something();
+
+    let assoc_ty: <() as Trait>::AssocTy = String::new();
 }
 
 fn test_functions() {
@@ -173,4 +185,6 @@ fn test_simple_types() {
     let _var: bool = false;
 }
 
+fn issue11190() {}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/redundant_type_annotations.stderr b/src/tools/clippy/tests/ui/redundant_type_annotations.stderr
index e8b2fe5c384..988ebe63722 100644
--- a/src/tools/clippy/tests/ui/redundant_type_annotations.stderr
+++ b/src/tools/clippy/tests/ui/redundant_type_annotations.stderr
@@ -19,85 +19,85 @@ LL |         let v: &Slice = self.return_a_ref_to_struct();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: redundant type annotation
-  --> $DIR/redundant_type_annotations.rs:143:5
+  --> $DIR/redundant_type_annotations.rs:155:5
    |
 LL |     let _return: String = return_a_string();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: redundant type annotation
-  --> $DIR/redundant_type_annotations.rs:145:5
+  --> $DIR/redundant_type_annotations.rs:157:5
    |
 LL |     let _return: Pie = return_a_struct();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: redundant type annotation
-  --> $DIR/redundant_type_annotations.rs:147:5
+  --> $DIR/redundant_type_annotations.rs:159:5
    |
 LL |     let _return: Pizza = return_an_enum();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: redundant type annotation
-  --> $DIR/redundant_type_annotations.rs:149:5
+  --> $DIR/redundant_type_annotations.rs:161:5
    |
 LL |     let _return: u32 = return_an_int();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: redundant type annotation
-  --> $DIR/redundant_type_annotations.rs:151:5
+  --> $DIR/redundant_type_annotations.rs:163:5
    |
 LL |     let _return: String = String::new();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: redundant type annotation
-  --> $DIR/redundant_type_annotations.rs:153:5
+  --> $DIR/redundant_type_annotations.rs:165:5
    |
 LL |     let new_pie: Pie = Pie::new();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: redundant type annotation
-  --> $DIR/redundant_type_annotations.rs:155:5
+  --> $DIR/redundant_type_annotations.rs:167:5
    |
 LL |     let _return: u32 = new_pie.return_an_int();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: redundant type annotation
-  --> $DIR/redundant_type_annotations.rs:157:5
+  --> $DIR/redundant_type_annotations.rs:169:5
    |
 LL |     let _return: u32 = Pie::associated_return_an_int();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: redundant type annotation
-  --> $DIR/redundant_type_annotations.rs:159:5
+  --> $DIR/redundant_type_annotations.rs:171:5
    |
 LL |     let _return: String = Pie::associated_return_a_string();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: redundant type annotation
-  --> $DIR/redundant_type_annotations.rs:165:5
+  --> $DIR/redundant_type_annotations.rs:177:5
    |
 LL |     let _var: u32 = u32::MAX;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: redundant type annotation
-  --> $DIR/redundant_type_annotations.rs:167:5
+  --> $DIR/redundant_type_annotations.rs:179:5
    |
 LL |     let _var: u32 = 5_u32;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: redundant type annotation
-  --> $DIR/redundant_type_annotations.rs:169:5
+  --> $DIR/redundant_type_annotations.rs:181:5
    |
 LL |     let _var: &str = "test";
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: redundant type annotation
-  --> $DIR/redundant_type_annotations.rs:171:5
+  --> $DIR/redundant_type_annotations.rs:183:5
    |
 LL |     let _var: &[u8] = b"test";
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: redundant type annotation
-  --> $DIR/redundant_type_annotations.rs:173:5
+  --> $DIR/redundant_type_annotations.rs:185:5
    |
 LL |     let _var: bool = false;
    |     ^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed
index 8257bf2947a..e78b9e5c9c1 100644
--- a/src/tools/clippy/tests/ui/rename.fixed
+++ b/src/tools/clippy/tests/ui/rename.fixed
@@ -29,9 +29,9 @@
 #![allow(clippy::recursive_format_impl)]
 #![allow(clippy::unwrap_or_default)]
 #![allow(clippy::invisible_characters)]
+#![allow(invalid_reference_casting)]
 #![allow(suspicious_double_ref_op)]
 #![allow(invalid_nan_comparisons)]
-#![allow(invalid_reference_casting)]
 #![allow(drop_bounds)]
 #![allow(dropping_copy_types)]
 #![allow(dropping_references)]
diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs
index 6569dad18d4..2e6ef60cb79 100644
--- a/src/tools/clippy/tests/ui/rename.rs
+++ b/src/tools/clippy/tests/ui/rename.rs
@@ -29,9 +29,9 @@
 #![allow(clippy::recursive_format_impl)]
 #![allow(clippy::unwrap_or_default)]
 #![allow(clippy::invisible_characters)]
+#![allow(invalid_reference_casting)]
 #![allow(suspicious_double_ref_op)]
 #![allow(invalid_nan_comparisons)]
-#![allow(invalid_reference_casting)]
 #![allow(drop_bounds)]
 #![allow(dropping_copy_types)]
 #![allow(dropping_references)]
diff --git a/src/tools/clippy/tests/ui/suspicious_xor_used_as_pow.stderr b/src/tools/clippy/tests/ui/suspicious_xor_used_as_pow.stderr
index 8bb3c8fbeeb..d93a55ba906 100644
--- a/src/tools/clippy/tests/ui/suspicious_xor_used_as_pow.stderr
+++ b/src/tools/clippy/tests/ui/suspicious_xor_used_as_pow.stderr
@@ -10,31 +10,31 @@ error: `^` is not the exponentiation operator
   --> $DIR/suspicious_xor_used_as_pow.rs:20:13
    |
 LL |     let _ = 2i32 ^ 9i32;
-   |             ^^^^^^^^^^^ help: did you mean to write: `2_i32.pow(9_i32)`
+   |             ^^^^^^^^^^^ help: did you mean to write: `2i32.pow(9i32)`
 
 error: `^` is not the exponentiation operator
   --> $DIR/suspicious_xor_used_as_pow.rs:21:13
    |
 LL |     let _ = 2i32 ^ 2i32;
-   |             ^^^^^^^^^^^ help: did you mean to write: `2_i32.pow(2_i32)`
+   |             ^^^^^^^^^^^ help: did you mean to write: `2i32.pow(2i32)`
 
 error: `^` is not the exponentiation operator
   --> $DIR/suspicious_xor_used_as_pow.rs:22:13
    |
 LL |     let _ = 50i32 ^ 3i32;
-   |             ^^^^^^^^^^^^ help: did you mean to write: `50_i32.pow(3_i32)`
+   |             ^^^^^^^^^^^^ help: did you mean to write: `50i32.pow(3i32)`
 
 error: `^` is not the exponentiation operator
   --> $DIR/suspicious_xor_used_as_pow.rs:23:13
    |
 LL |     let _ = 5i32 ^ 8i32;
-   |             ^^^^^^^^^^^ help: did you mean to write: `5_i32.pow(8_i32)`
+   |             ^^^^^^^^^^^ help: did you mean to write: `5i32.pow(8i32)`
 
 error: `^` is not the exponentiation operator
   --> $DIR/suspicious_xor_used_as_pow.rs:24:13
    |
 LL |     let _ = 2i32 ^ 32i32;
-   |             ^^^^^^^^^^^^ help: did you mean to write: `2_i32.pow(32_i32)`
+   |             ^^^^^^^^^^^^ help: did you mean to write: `2i32.pow(32i32)`
 
 error: `^` is not the exponentiation operator
   --> $DIR/suspicious_xor_used_as_pow.rs:13:9
diff --git a/src/tools/clippy/tests/ui/unwrap.stderr b/src/tools/clippy/tests/ui/unwrap.stderr
index 3796d942ff9..41db819f6fb 100644
--- a/src/tools/clippy/tests/ui/unwrap.stderr
+++ b/src/tools/clippy/tests/ui/unwrap.stderr
@@ -4,7 +4,8 @@ error: used `unwrap()` on an `Option` value
 LL |     let _ = opt.unwrap();
    |             ^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is `None`, it will panic
+   = help: consider using `expect()` to provide a better panic message
    = note: `-D clippy::unwrap-used` implied by `-D warnings`
 
 error: used `unwrap()` on a `Result` value
@@ -13,7 +14,8 @@ error: used `unwrap()` on a `Result` value
 LL |     let _ = res.unwrap();
    |             ^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `Err` case gracefully, consider using `expect()` to provide a better panic message
+   = note: if this value is an `Err`, it will panic
+   = help: consider using `expect()` to provide a better panic message
 
 error: used `unwrap_err()` on a `Result` value
   --> $DIR/unwrap.rs:12:13
@@ -21,7 +23,8 @@ error: used `unwrap_err()` on a `Result` value
 LL |     let _ = res.unwrap_err();
    |             ^^^^^^^^^^^^^^^^
    |
-   = help: if you don't want to handle the `Ok` case gracefully, consider using `expect_err()` to provide a better panic message
+   = note: if this value is an `Ok`, it will panic
+   = help: consider using `expect_err()` to provide a better panic message
 
 error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unwrap_expect_used.rs b/src/tools/clippy/tests/ui/unwrap_expect_used.rs
index 7f57efc53c9..26f92ccdefa 100644
--- a/src/tools/clippy/tests/ui/unwrap_expect_used.rs
+++ b/src/tools/clippy/tests/ui/unwrap_expect_used.rs
@@ -1,5 +1,8 @@
 #![warn(clippy::unwrap_used, clippy::expect_used)]
 #![allow(clippy::unnecessary_literal_unwrap)]
+#![feature(never_type)]
+
+use std::convert::Infallible;
 
 trait OptionExt {
     type Item;
@@ -28,6 +31,14 @@ fn main() {
     Some(3).unwrap_err();
     Some(3).expect_err("Hellow none!");
 
+    // Issue #11245: The `Err` variant can never be constructed so do not lint this.
+    let x: Result<(), !> = Ok(());
+    x.unwrap();
+    x.expect("is `!` (never)");
+    let x: Result<(), Infallible> = Ok(());
+    x.unwrap();
+    x.expect("is never-like (0 variants)");
+
     let a: Result<i32, i32> = Ok(3);
     a.unwrap();
     a.expect("Hello world!");
diff --git a/src/tools/clippy/tests/ui/unwrap_expect_used.stderr b/src/tools/clippy/tests/ui/unwrap_expect_used.stderr
index 1a551ab5ab8..f66e47612ad 100644
--- a/src/tools/clippy/tests/ui/unwrap_expect_used.stderr
+++ b/src/tools/clippy/tests/ui/unwrap_expect_used.stderr
@@ -1,52 +1,52 @@
 error: used `unwrap()` on an `Option` value
-  --> $DIR/unwrap_expect_used.rs:24:5
+  --> $DIR/unwrap_expect_used.rs:27:5
    |
 LL |     Some(3).unwrap();
    |     ^^^^^^^^^^^^^^^^
    |
-   = help: if this value is `None`, it will panic
+   = note: if this value is `None`, it will panic
    = note: `-D clippy::unwrap-used` implied by `-D warnings`
 
 error: used `expect()` on an `Option` value
-  --> $DIR/unwrap_expect_used.rs:25:5
+  --> $DIR/unwrap_expect_used.rs:28:5
    |
 LL |     Some(3).expect("Hello world!");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if this value is `None`, it will panic
+   = note: if this value is `None`, it will panic
    = note: `-D clippy::expect-used` implied by `-D warnings`
 
 error: used `unwrap()` on a `Result` value
-  --> $DIR/unwrap_expect_used.rs:32:5
+  --> $DIR/unwrap_expect_used.rs:43:5
    |
 LL |     a.unwrap();
    |     ^^^^^^^^^^
    |
-   = help: if this value is an `Err`, it will panic
+   = note: if this value is an `Err`, it will panic
 
 error: used `expect()` on a `Result` value
-  --> $DIR/unwrap_expect_used.rs:33:5
+  --> $DIR/unwrap_expect_used.rs:44:5
    |
 LL |     a.expect("Hello world!");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if this value is an `Err`, it will panic
+   = note: if this value is an `Err`, it will panic
 
 error: used `unwrap_err()` on a `Result` value
-  --> $DIR/unwrap_expect_used.rs:34:5
+  --> $DIR/unwrap_expect_used.rs:45:5
    |
 LL |     a.unwrap_err();
    |     ^^^^^^^^^^^^^^
    |
-   = help: if this value is an `Ok`, it will panic
+   = note: if this value is an `Ok`, it will panic
 
 error: used `expect_err()` on a `Result` value
-  --> $DIR/unwrap_expect_used.rs:35:5
+  --> $DIR/unwrap_expect_used.rs:46:5
    |
 LL |     a.expect_err("Hello error!");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if this value is an `Ok`, it will panic
+   = note: if this value is an `Ok`, it will panic
 
 error: aborting due to 6 previous errors
 
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index 1ec4cbc4de7..97718f1f4a9 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -69,7 +69,7 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
             }
 
             init_late_loggers(handler, tcx);
-            if !tcx.sess.crate_types().contains(&CrateType::Executable) {
+            if !tcx.crate_types().contains(&CrateType::Executable) {
                 tcx.sess.fatal("miri only makes sense on bin crates");
             }
 
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 22e9b46347a..a9ab696cdf4 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -113,7 +113,6 @@ const PERMITTED_DEPS_LOCATION: &str = concat!(file!(), ":", line!());
 /// rustc. Please check with the compiler team before adding an entry.
 const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     // tidy-alphabetical-start
-    "addr2line",
     "adler",
     "ahash",
     "aho-corasick",
diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs
index b386b000bef..3a4d9c53d7b 100644
--- a/src/tools/tidy/src/pal.rs
+++ b/src/tools/tidy/src/pal.rs
@@ -52,6 +52,7 @@ const EXCEPTION_PATHS: &[&str] = &[
     // FIXME: platform-specific code should be moved to `sys`
     "library/std/src/io/copy.rs",
     "library/std/src/io/stdio.rs",
+    "library/std/src/lib.rs", // for miniz_oxide leaking docs, which itself workaround
     "library/std/src/path.rs",
     "library/std/src/sys_common", // Should only contain abstractions over platforms
     "library/std/src/net/test.rs", // Utility helpers for tests
diff --git a/tests/codegen/method-declaration.rs b/tests/codegen/method-declaration.rs
new file mode 100644
index 00000000000..4ae332b0107
--- /dev/null
+++ b/tests/codegen/method-declaration.rs
@@ -0,0 +1,26 @@
+// compile-flags: -g -Cno-prepopulate-passes
+
+// Verify that we added a declaration for a method.
+
+// CHECK: define{{.*}}@method{{.*}} !dbg ![[METHOD_DEF_DBG:[0-9]+]]
+// CHECK: define{{.*}}@function{{.*}} !dbg ![[FUNC_DEF_DBG:[0-9]+]]
+
+#![crate_type = "lib"]
+
+// CHECK-DAG: ![[FOO_DBG:[0-9]+]] = !DICompositeType(tag: {{.*}} name: "Foo", {{.*}} identifier:
+pub struct Foo;
+
+impl Foo {
+    // CHECK-DAG: ![[METHOD_DEF_DBG]] = distinct !DISubprogram(name: "method"{{.*}}, scope: ![[FOO_DBG]]{{.*}}DISPFlagDefinition{{.*}}, declaration: ![[METHOD_DECL_DBG:[0-9]+]]
+    // CHECK-DAG: ![[METHOD_DECL_DBG]] = !DISubprogram(name: "method"{{.*}}, scope: ![[FOO_DBG]]
+    #[no_mangle]
+    pub fn method() {}
+}
+
+// CHECK: ![[FUNC_DEF_DBG]] = distinct !DISubprogram(name: "function"
+// CHECK-NOT: declaration
+// CHECK-SAME: DISPFlagDefinition
+// CHECK-NOT: declaration
+// CHECK-SAME: )
+#[no_mangle]
+pub fn function() {}
diff --git a/tests/codegen/ptr-arithmetic.rs b/tests/codegen/ptr-arithmetic.rs
new file mode 100644
index 00000000000..292bfdaf357
--- /dev/null
+++ b/tests/codegen/ptr-arithmetic.rs
@@ -0,0 +1,34 @@
+// compile-flags: -O -Z merge-functions=disabled
+// ignore-debug (the extra assertions get in the way)
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: ptr @i32_add(
+// CHECK-SAME: [[WORD:i[0-9]+]] noundef %n)
+#[no_mangle]
+pub unsafe fn i32_add(p: *const i32, n: usize) -> *const i32 {
+    // CHECK: %[[TEMP:.+]] = getelementptr inbounds i32, ptr %p, [[WORD]] %n
+    // CHECK: ret ptr %[[TEMP]]
+    p.add(n)
+}
+
+// Ensure we tell LLVM that the negation in `sub` can't overflow.
+
+// CHECK-LABEL: ptr @i32_sub(
+// CHECK-SAME: [[WORD:i[0-9]+]] noundef %n)
+#[no_mangle]
+pub unsafe fn i32_sub(p: *const i32, n: usize) -> *const i32 {
+    // CHECK: %[[DELTA:.+]] = sub nsw [[WORD]] 0, %n
+    // CHECK: %[[TEMP:.+]] = getelementptr inbounds i32, ptr %p, [[WORD]] %[[DELTA]]
+    // CHECK: ret ptr %[[TEMP]]
+    p.sub(n)
+}
+
+// CHECK-LABEL: ptr @i32_offset(
+// CHECK-SAME: [[WORD:i[0-9]+]] noundef %d)
+#[no_mangle]
+pub unsafe fn i32_offset(p: *const i32, d: isize) -> *const i32 {
+    // CHECK: %[[TEMP:.+]] = getelementptr inbounds i32, ptr %p, [[WORD]] %d
+    // CHECK: ret ptr %[[TEMP]]
+    p.offset(d)
+}
diff --git a/tests/ui/async-await/in-trait/return-type-suggestion.rs b/tests/ui/async-await/in-trait/return-type-suggestion.rs
index 92a9e035e89..cdab4ea0f37 100644
--- a/tests/ui/async-await/in-trait/return-type-suggestion.rs
+++ b/tests/ui/async-await/in-trait/return-type-suggestion.rs
@@ -6,7 +6,6 @@ trait A {
     async fn e() {
         Ok(())
         //~^ ERROR mismatched types
-        //~| HELP consider using a semicolon here
     }
 }
 
diff --git a/tests/ui/async-await/in-trait/return-type-suggestion.stderr b/tests/ui/async-await/in-trait/return-type-suggestion.stderr
index d9309459812..179c9ed93db 100644
--- a/tests/ui/async-await/in-trait/return-type-suggestion.stderr
+++ b/tests/ui/async-await/in-trait/return-type-suggestion.stderr
@@ -2,9 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/return-type-suggestion.rs:7:9
    |
 LL |         Ok(())
-   |         ^^^^^^- help: consider using a semicolon here: `;`
-   |         |
-   |         expected `()`, found `Result<(), _>`
+   |         ^^^^^^ expected `()`, found `Result<(), _>`
    |
    = note: expected unit type `()`
                    found enum `Result<(), _>`
diff --git a/tests/ui/fmt/suggest-inline-args.rs b/tests/ui/fmt/suggest-inline-args.rs
new file mode 100644
index 00000000000..515335ed9f4
--- /dev/null
+++ b/tests/ui/fmt/suggest-inline-args.rs
@@ -0,0 +1,28 @@
+mod foo {
+    pub fn bar() -> i32 {
+        1
+    }
+}
+
+fn bar() -> i32 {
+    2
+}
+
+fn main() {
+    let stderr = 3;
+    eprintln!({stderr});
+    //~^ ERROR format argument must be a string literal
+    //~| HELP quote your inlined format argument to use as string literal
+    eprintln!({1});
+    //~^ ERROR format argument must be a string literal
+    //~| HELP you might be missing a string literal to format with
+    eprintln!({foo::bar()});
+    //~^ ERROR format argument must be a string literal
+    //~| HELP you might be missing a string literal to format with
+    eprintln!({bar()});
+    //~^ ERROR format argument must be a string literal
+    //~| HELP you might be missing a string literal to format with
+    eprintln!({1; 2});
+    //~^ ERROR format argument must be a string literal
+    //~| HELP you might be missing a string literal to format with
+}
diff --git a/tests/ui/fmt/suggest-inline-args.stderr b/tests/ui/fmt/suggest-inline-args.stderr
new file mode 100644
index 00000000000..cf70568cf3f
--- /dev/null
+++ b/tests/ui/fmt/suggest-inline-args.stderr
@@ -0,0 +1,57 @@
+error: format argument must be a string literal
+  --> $DIR/suggest-inline-args.rs:13:15
+   |
+LL |     eprintln!({stderr});
+   |               ^^^^^^^^
+   |
+help: quote your inlined format argument to use as string literal
+   |
+LL |     eprintln!("{stderr}");
+   |               +        +
+
+error: format argument must be a string literal
+  --> $DIR/suggest-inline-args.rs:16:15
+   |
+LL |     eprintln!({1});
+   |               ^^^
+   |
+help: you might be missing a string literal to format with
+   |
+LL |     eprintln!("{}", {1});
+   |               +++++
+
+error: format argument must be a string literal
+  --> $DIR/suggest-inline-args.rs:19:15
+   |
+LL |     eprintln!({foo::bar()});
+   |               ^^^^^^^^^^^^
+   |
+help: you might be missing a string literal to format with
+   |
+LL |     eprintln!("{}", {foo::bar()});
+   |               +++++
+
+error: format argument must be a string literal
+  --> $DIR/suggest-inline-args.rs:22:15
+   |
+LL |     eprintln!({bar()});
+   |               ^^^^^^^
+   |
+help: you might be missing a string literal to format with
+   |
+LL |     eprintln!("{}", {bar()});
+   |               +++++
+
+error: format argument must be a string literal
+  --> $DIR/suggest-inline-args.rs:25:15
+   |
+LL |     eprintln!({1; 2});
+   |               ^^^^^^
+   |
+help: you might be missing a string literal to format with
+   |
+LL |     eprintln!("{}", {1; 2});
+   |               +++++
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/implied-bounds/implied_bounds_entailment_skip_non_outlives.rs b/tests/ui/implied-bounds/implied_bounds_entailment_skip_non_outlives.rs
new file mode 100644
index 00000000000..8dcc35a281a
--- /dev/null
+++ b/tests/ui/implied-bounds/implied_bounds_entailment_skip_non_outlives.rs
@@ -0,0 +1,23 @@
+// check-pass
+// See issue #109356. We don't want a false positive to the `implied_bounds_entailment` lint.
+
+use std::borrow::Cow;
+
+pub trait Trait {
+    fn method(self) -> Option<Cow<'static, str>>
+    where
+        Self: Sized;
+}
+
+impl<'a> Trait for Cow<'a, str> {
+    // If we're not careful here, we'll check `WF(return-type)` using the trait
+    // and impl where clauses, requiring that `Cow<'a, str>: Sized`. This is
+    // obviously true, but if we pick the `Self: Sized` clause from the trait
+    // over the "inherent impl", we will require `'a == 'static`, which triggers
+    // the `implied_bounds_entailment` lint.
+    fn method(self) -> Option<Cow<'static, str>> {
+        None
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/implied-bounds/trait-where-clause-implied.rs b/tests/ui/implied-bounds/trait-where-clause-implied.rs
new file mode 100644
index 00000000000..5f9ab66d3c8
--- /dev/null
+++ b/tests/ui/implied-bounds/trait-where-clause-implied.rs
@@ -0,0 +1,15 @@
+// check-pass
+
+pub trait Trait<'a, 'b> {
+    fn method(self, _: &'static &'static ())
+    where
+        'a: 'b;
+}
+
+impl<'a> Trait<'a, 'static> for () {
+    // On first glance, this seems like we have the extra implied bound that
+    // `'a: 'static`, but we know this from the trait method where clause.
+    fn method(self, _: &'static &'a ()) {}
+}
+
+fn main() {}
diff --git a/tests/ui/lazy-type-alias/leading-where-clause.fixed b/tests/ui/lazy-type-alias/leading-where-clause.fixed
new file mode 100644
index 00000000000..07ebc09b30e
--- /dev/null
+++ b/tests/ui/lazy-type-alias/leading-where-clause.fixed
@@ -0,0 +1,15 @@
+// run-rustfix
+
+#![feature(lazy_type_alias)]
+#![allow(incomplete_features)]
+
+// Check that we *reject* leading where-clauses on lazy type aliases.
+
+type Alias<T>
+
+= T where String: From<T>;
+//~^^^ ERROR where clauses are not allowed before the type for type aliases
+
+fn main() {
+    let _: Alias<&str>;
+}
diff --git a/tests/ui/lazy-type-alias/leading-where-clause.rs b/tests/ui/lazy-type-alias/leading-where-clause.rs
new file mode 100644
index 00000000000..4a654293472
--- /dev/null
+++ b/tests/ui/lazy-type-alias/leading-where-clause.rs
@@ -0,0 +1,16 @@
+// run-rustfix
+
+#![feature(lazy_type_alias)]
+#![allow(incomplete_features)]
+
+// Check that we *reject* leading where-clauses on lazy type aliases.
+
+type Alias<T>
+where
+    String: From<T>,
+= T;
+//~^^^ ERROR where clauses are not allowed before the type for type aliases
+
+fn main() {
+    let _: Alias<&str>;
+}
diff --git a/tests/ui/lazy-type-alias/leading-where-clause.stderr b/tests/ui/lazy-type-alias/leading-where-clause.stderr
new file mode 100644
index 00000000000..8ddf0ce6c65
--- /dev/null
+++ b/tests/ui/lazy-type-alias/leading-where-clause.stderr
@@ -0,0 +1,16 @@
+error: where clauses are not allowed before the type for type aliases
+  --> $DIR/leading-where-clause.rs:9:1
+   |
+LL | / where
+LL | |     String: From<T>,
+   | |____________________^
+   |
+   = note: see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
+help: move it to the end of the type declaration
+   |
+LL + 
+LL ~ = T where String: From<T>;
+   |
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lazy-type-alias/trailing-where-clause.rs b/tests/ui/lazy-type-alias/trailing-where-clause.rs
new file mode 100644
index 00000000000..ac9598fe5f6
--- /dev/null
+++ b/tests/ui/lazy-type-alias/trailing-where-clause.rs
@@ -0,0 +1,13 @@
+#![feature(lazy_type_alias)]
+#![allow(incomplete_features)]
+
+// Check that we allow & respect trailing where-clauses on lazy type aliases.
+
+type Alias<T> = T
+where
+    String: From<T>;
+
+fn main() {
+    let _: Alias<&str>;
+    let _: Alias<()>; //~ ERROR the trait bound `String: From<()>` is not satisfied
+}
diff --git a/tests/ui/lazy-type-alias/trailing-where-clause.stderr b/tests/ui/lazy-type-alias/trailing-where-clause.stderr
new file mode 100644
index 00000000000..d7606ba6b2a
--- /dev/null
+++ b/tests/ui/lazy-type-alias/trailing-where-clause.stderr
@@ -0,0 +1,22 @@
+error[E0277]: the trait bound `String: From<()>` is not satisfied
+  --> $DIR/trailing-where-clause.rs:12:12
+   |
+LL |     let _: Alias<()>;
+   |            ^^^^^^^^^ the trait `From<()>` is not implemented for `String`
+   |
+   = help: the following other types implement trait `From<T>`:
+             <String as From<char>>
+             <String as From<Box<str>>>
+             <String as From<Cow<'a, str>>>
+             <String as From<&str>>
+             <String as From<&mut str>>
+             <String as From<&String>>
+note: required by a bound on the type alias `Alias`
+  --> $DIR/trailing-where-clause.rs:8:13
+   |
+LL |     String: From<T>;
+   |             ^^^^^^^ required by this bound
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/return/return-struct.rs b/tests/ui/return/return-struct.rs
new file mode 100644
index 00000000000..446445c17ba
--- /dev/null
+++ b/tests/ui/return/return-struct.rs
@@ -0,0 +1,24 @@
+struct S;
+
+enum Age {
+    Years(i64, i64)
+}
+
+fn foo() {
+    let mut age = 29;
+    Age::Years({age += 1; age}, 55)
+    //~^ ERROR mismatched types
+}
+
+fn bar() {
+    let mut age = 29;
+    Age::Years(age, 55)
+    //~^ ERROR mismatched types
+}
+
+fn baz() {
+    S
+    //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/return/return-struct.stderr b/tests/ui/return/return-struct.stderr
new file mode 100644
index 00000000000..e6c0363e363
--- /dev/null
+++ b/tests/ui/return/return-struct.stderr
@@ -0,0 +1,35 @@
+error[E0308]: mismatched types
+  --> $DIR/return-struct.rs:9:5
+   |
+LL |     Age::Years({age += 1; age}, 55)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Age`
+   |
+help: consider using a semicolon here
+   |
+LL |     Age::Years({age += 1; age}, 55);
+   |                                    +
+help: try adding a return type
+   |
+LL | fn foo() -> Age {
+   |          ++++++
+
+error[E0308]: mismatched types
+  --> $DIR/return-struct.rs:15:5
+   |
+LL | fn bar() {
+   |          - help: try adding a return type: `-> Age`
+LL |     let mut age = 29;
+LL |     Age::Years(age, 55)
+   |     ^^^^^^^^^^^^^^^^^^^ expected `()`, found `Age`
+
+error[E0308]: mismatched types
+  --> $DIR/return-struct.rs:20:5
+   |
+LL | fn baz() {
+   |          - help: try adding a return type: `-> S`
+LL |     S
+   |     ^ expected `()`, found `S`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/sanitize/issue-114275-cfi-const-expr-in-arry-len.rs b/tests/ui/sanitize/issue-114275-cfi-const-expr-in-arry-len.rs
new file mode 100644
index 00000000000..8f870be1372
--- /dev/null
+++ b/tests/ui/sanitize/issue-114275-cfi-const-expr-in-arry-len.rs
@@ -0,0 +1,15 @@
+// Regression test for issue 114275 `typeid::typeid_itanium_cxx_abi::transform_ty`
+// was expecting array type lengths to be evaluated, this was causing an ICE.
+//
+// build-pass
+// compile-flags: -Ccodegen-units=1 -Clto -Zsanitizer=cfi -Ctarget-feature=-crt-static
+// needs-sanitizer-cfi
+
+#![crate_type = "lib"]
+
+#[repr(transparent)]
+pub struct Array([u8; 1 * 1]);
+
+pub extern "C" fn array() -> Array {
+    loop {}
+}
diff --git a/tests/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr b/tests/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr
index 438075083d3..bb8b9b37067 100644
--- a/tests/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr
+++ b/tests/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr
@@ -5,7 +5,7 @@ LL |   fn vindictive() -> bool { true }
    |   ----------------------- `vindictive` defined here returns `bool`
 ...
 LL |       vindictive()
-   |       -^^^^^^^^^^^- help: consider using a semicolon here: `;`
+   |       -^^^^^^^^^^^- help: consider using a semicolon here to finish the statement: `;`
    |  _____|
    | |
 LL | |     (1, 2)
diff --git a/tests/ui/suggestions/missing-semicolon.fixed b/tests/ui/suggestions/missing-semicolon.fixed
new file mode 100644
index 00000000000..df355f0b007
--- /dev/null
+++ b/tests/ui/suggestions/missing-semicolon.fixed
@@ -0,0 +1,38 @@
+// run-rustfix
+#![allow(dead_code, unused_variables, path_statements)]
+fn a() {
+    let x = 5;
+    let y = x; //~ ERROR expected function
+    (); //~ ERROR expected `;`, found `}`
+}
+
+fn b() {
+    let x = 5;
+    let y = x; //~ ERROR expected function
+    ();
+}
+fn c() {
+    let x = 5;
+    x; //~ ERROR expected function
+    ()
+}
+fn d() { // ok
+    let x = || ();
+    x
+    ()
+}
+fn e() { // ok
+    let x = || ();
+    x
+    ();
+}
+fn f()
+ {
+    let y = 5; //~ ERROR expected function
+    (); //~ ERROR expected `;`, found `}`
+}
+fn g() {
+    5; //~ ERROR expected function
+    ();
+}
+fn main() {}
diff --git a/tests/ui/suggestions/missing-semicolon.rs b/tests/ui/suggestions/missing-semicolon.rs
new file mode 100644
index 00000000000..12ef3d33e5f
--- /dev/null
+++ b/tests/ui/suggestions/missing-semicolon.rs
@@ -0,0 +1,38 @@
+// run-rustfix
+#![allow(dead_code, unused_variables, path_statements)]
+fn a() {
+    let x = 5;
+    let y = x //~ ERROR expected function
+    () //~ ERROR expected `;`, found `}`
+}
+
+fn b() {
+    let x = 5;
+    let y = x //~ ERROR expected function
+    ();
+}
+fn c() {
+    let x = 5;
+    x //~ ERROR expected function
+    ()
+}
+fn d() { // ok
+    let x = || ();
+    x
+    ()
+}
+fn e() { // ok
+    let x = || ();
+    x
+    ();
+}
+fn f()
+ {
+    let y = 5 //~ ERROR expected function
+    () //~ ERROR expected `;`, found `}`
+}
+fn g() {
+    5 //~ ERROR expected function
+    ();
+}
+fn main() {}
diff --git a/tests/ui/suggestions/missing-semicolon.stderr b/tests/ui/suggestions/missing-semicolon.stderr
new file mode 100644
index 00000000000..54a64f664b5
--- /dev/null
+++ b/tests/ui/suggestions/missing-semicolon.stderr
@@ -0,0 +1,75 @@
+error: expected `;`, found `}`
+  --> $DIR/missing-semicolon.rs:6:7
+   |
+LL |     ()
+   |       ^ help: add `;` here
+LL | }
+   | - unexpected token
+
+error: expected `;`, found `}`
+  --> $DIR/missing-semicolon.rs:32:7
+   |
+LL |     ()
+   |       ^ help: add `;` here
+LL | }
+   | - unexpected token
+
+error[E0618]: expected function, found `{integer}`
+  --> $DIR/missing-semicolon.rs:5:13
+   |
+LL |       let x = 5;
+   |           - `x` has type `{integer}`
+LL |       let y = x
+   |               ^- help: consider using a semicolon here to finish the statement: `;`
+   |  _____________|
+   | |
+LL | |     ()
+   | |______- call expression requires function
+
+error[E0618]: expected function, found `{integer}`
+  --> $DIR/missing-semicolon.rs:11:13
+   |
+LL |       let x = 5;
+   |           - `x` has type `{integer}`
+LL |       let y = x
+   |               ^- help: consider using a semicolon here to finish the statement: `;`
+   |  _____________|
+   | |
+LL | |     ();
+   | |______- call expression requires function
+
+error[E0618]: expected function, found `{integer}`
+  --> $DIR/missing-semicolon.rs:16:5
+   |
+LL |       let x = 5;
+   |           - `x` has type `{integer}`
+LL |       x
+   |       ^- help: consider using a semicolon here to finish the statement: `;`
+   |  _____|
+   | |
+LL | |     ()
+   | |______- call expression requires function
+
+error[E0618]: expected function, found `{integer}`
+  --> $DIR/missing-semicolon.rs:31:13
+   |
+LL |       let y = 5
+   |               ^- help: consider using a semicolon here to finish the statement: `;`
+   |  _____________|
+   | |
+LL | |     ()
+   | |______- call expression requires function
+
+error[E0618]: expected function, found `{integer}`
+  --> $DIR/missing-semicolon.rs:35:5
+   |
+LL |       5
+   |       ^- help: consider using a semicolon here to finish the statement: `;`
+   |  _____|
+   | |
+LL | |     ();
+   | |______- call expression requires function
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0618`.
diff --git a/tests/ui/traits/new-solver/runaway-impl-candidate-selection.rs b/tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.rs
index 1dca86d3630..1dca86d3630 100644
--- a/tests/ui/traits/new-solver/runaway-impl-candidate-selection.rs
+++ b/tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.rs
diff --git a/tests/ui/traits/new-solver/runaway-impl-candidate-selection.stderr b/tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.stderr
index 47004821ad7..47004821ad7 100644
--- a/tests/ui/traits/new-solver/runaway-impl-candidate-selection.stderr
+++ b/tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.stderr
diff --git a/tests/ui/traits/new-solver/coinduction/fixpoint-exponential-growth.rs b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs
index fcafdcf637a..fcafdcf637a 100644
--- a/tests/ui/traits/new-solver/coinduction/fixpoint-exponential-growth.rs
+++ b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs
diff --git a/tests/ui/traits/new-solver/coinduction/fixpoint-exponential-growth.stderr b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr
index 7d3535e1f01..7d3535e1f01 100644
--- a/tests/ui/traits/new-solver/coinduction/fixpoint-exponential-growth.stderr
+++ b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr
diff --git a/tests/ui/traits/new-solver/coinduction/incompleteness-unstable-result.rs b/tests/ui/traits/new-solver/cycles/coinduction/incompleteness-unstable-result.rs
index 0cd14f05c8d..0cd14f05c8d 100644
--- a/tests/ui/traits/new-solver/coinduction/incompleteness-unstable-result.rs
+++ b/tests/ui/traits/new-solver/cycles/coinduction/incompleteness-unstable-result.rs
diff --git a/tests/ui/traits/new-solver/coinduction/incompleteness-unstable-result.stderr b/tests/ui/traits/new-solver/cycles/coinduction/incompleteness-unstable-result.stderr
index f1871ff0564..f1871ff0564 100644
--- a/tests/ui/traits/new-solver/coinduction/incompleteness-unstable-result.stderr
+++ b/tests/ui/traits/new-solver/cycles/coinduction/incompleteness-unstable-result.stderr
diff --git a/tests/ui/traits/new-solver/cycles/double-cycle-inductive-coinductive.rs b/tests/ui/traits/new-solver/cycles/double-cycle-inductive-coinductive.rs
new file mode 100644
index 00000000000..5617e45adf6
--- /dev/null
+++ b/tests/ui/traits/new-solver/cycles/double-cycle-inductive-coinductive.rs
@@ -0,0 +1,37 @@
+// compile-flags: -Ztrait-solver=next
+#![feature(rustc_attrs)]
+
+// Test that having both an inductive and a coinductive cycle
+// is handled correctly.
+
+#[rustc_coinductive]
+trait Trait {}
+impl<T: Inductive + Coinductive> Trait for T {}
+
+trait Inductive {}
+impl<T: Trait> Inductive for T {}
+#[rustc_coinductive]
+trait Coinductive {}
+impl<T: Trait> Coinductive for T {}
+
+fn impls_trait<T: Trait>() {}
+
+#[rustc_coinductive]
+trait TraitRev {}
+impl<T: CoinductiveRev + InductiveRev> TraitRev for T {}
+
+trait InductiveRev {}
+impl<T: TraitRev> InductiveRev for T {}
+#[rustc_coinductive]
+trait CoinductiveRev {}
+impl<T: TraitRev> CoinductiveRev for T {}
+
+fn impls_trait_rev<T: TraitRev>() {}
+
+fn main() {
+    impls_trait::<()>();
+    //~^ ERROR overflow evaluating the requirement
+
+    impls_trait_rev::<()>();
+    //~^ ERROR overflow evaluating the requirement
+}
diff --git a/tests/ui/traits/new-solver/cycles/double-cycle-inductive-coinductive.stderr b/tests/ui/traits/new-solver/cycles/double-cycle-inductive-coinductive.stderr
new file mode 100644
index 00000000000..4b8846da535
--- /dev/null
+++ b/tests/ui/traits/new-solver/cycles/double-cycle-inductive-coinductive.stderr
@@ -0,0 +1,29 @@
+error[E0275]: overflow evaluating the requirement `(): Trait`
+  --> $DIR/double-cycle-inductive-coinductive.rs:32:5
+   |
+LL |     impls_trait::<()>();
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`double_cycle_inductive_coinductive`)
+note: required by a bound in `impls_trait`
+  --> $DIR/double-cycle-inductive-coinductive.rs:17:19
+   |
+LL | fn impls_trait<T: Trait>() {}
+   |                   ^^^^^ required by this bound in `impls_trait`
+
+error[E0275]: overflow evaluating the requirement `(): TraitRev`
+  --> $DIR/double-cycle-inductive-coinductive.rs:35:5
+   |
+LL |     impls_trait_rev::<()>();
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`double_cycle_inductive_coinductive`)
+note: required by a bound in `impls_trait_rev`
+  --> $DIR/double-cycle-inductive-coinductive.rs:29:23
+   |
+LL | fn impls_trait_rev<T: TraitRev>() {}
+   |                       ^^^^^^^^ required by this bound in `impls_trait_rev`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.rs b/tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.rs
new file mode 100644
index 00000000000..cda98789886
--- /dev/null
+++ b/tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.rs
@@ -0,0 +1,48 @@
+// compile-flags: -Ztrait-solver=next
+#![feature(trivial_bounds, marker_trait_attr)]
+#![allow(trivial_bounds)]
+// This previously triggered a bug in the provisional cache.
+//
+// This has the proof tree
+// - `MultipleCandidates: Trait` proven via impl-one
+//   - `MultipleNested: Trait` via impl
+//     - `MultipleCandidates: Trait` (inductive cycle ~> OVERFLOW)
+//     - `DoesNotImpl: Trait` (ERR)
+// - `MultipleCandidates: Trait` proven via impl-two
+//   - `MultipleNested: Trait` (in provisional cache ~> OVERFLOW)
+//
+// We previously incorrectly treated the `MultipleCandidates: Trait` as
+// overflow because it was in the cache and reached via an inductive cycle.
+// It should be `NoSolution`.
+
+struct MultipleCandidates;
+struct MultipleNested;
+struct DoesNotImpl;
+
+#[marker]
+trait Trait {}
+
+// impl-one
+impl Trait for MultipleCandidates
+where
+    MultipleNested: Trait
+{}
+
+// impl-two
+impl Trait for MultipleCandidates
+where
+    MultipleNested: Trait,
+{}
+
+impl Trait for MultipleNested
+where
+    MultipleCandidates: Trait,
+    DoesNotImpl: Trait,
+{}
+
+fn impls_trait<T: Trait>() {}
+
+fn main() {
+    impls_trait::<MultipleCandidates>();
+    //~^ ERROR the trait bound `MultipleCandidates: Trait` is not satisfied
+}
diff --git a/tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.stderr b/tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.stderr
new file mode 100644
index 00000000000..57227321a6d
--- /dev/null
+++ b/tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `MultipleCandidates: Trait` is not satisfied
+  --> $DIR/inductive-cycle-but-err.rs:46:19
+   |
+LL |     impls_trait::<MultipleCandidates>();
+   |                   ^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `MultipleCandidates`
+   |
+   = help: the trait `Trait` is implemented for `MultipleCandidates`
+note: required by a bound in `impls_trait`
+  --> $DIR/inductive-cycle-but-err.rs:43:19
+   |
+LL | fn impls_trait<T: Trait>() {}
+   |                   ^^^^^ required by this bound in `impls_trait`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/new-solver/cycles/inductive-cycle-but-ok.rs b/tests/ui/traits/new-solver/cycles/inductive-cycle-but-ok.rs
new file mode 100644
index 00000000000..d4851eb694b
--- /dev/null
+++ b/tests/ui/traits/new-solver/cycles/inductive-cycle-but-ok.rs
@@ -0,0 +1,44 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+#![feature(trivial_bounds, marker_trait_attr)]
+#![allow(trivial_bounds)]
+
+// This previously triggered a bug in the provisional cache.
+//
+// This has the proof tree
+// - `Root: Trait` proven via impl
+//   - `MultipleCandidates: Trait`
+//     - candidate: overflow-impl
+//       - `Root: Trait` (inductive cycle ~> OVERFLOW)
+//     - candidate: trivial-impl ~> YES
+//     - merge respones ~> YES
+//   - `MultipleCandidates: Trait` (in provisional cache ~> OVERFLOW)
+//
+// We previously incorrectly treated the `MultipleCandidates: Trait` as
+// overflow because it was in the cache and reached via an inductive cycle.
+// It should be `YES`.
+
+struct Root;
+struct MultipleCandidates;
+
+#[marker]
+trait Trait {}
+impl Trait for Root
+where
+    MultipleCandidates: Trait,
+    MultipleCandidates: Trait,
+{}
+
+// overflow-impl
+impl Trait for MultipleCandidates
+where
+    Root: Trait,
+{}
+// trivial-impl
+impl Trait for MultipleCandidates {}
+
+fn impls_trait<T: Trait>() {}
+
+fn main() {
+    impls_trait::<Root>();
+}
diff --git a/tests/ui/traits/new-solver/cycles/inductive-cycle-discarded-coinductive-constraints.rs b/tests/ui/traits/new-solver/cycles/inductive-cycle-discarded-coinductive-constraints.rs
new file mode 100644
index 00000000000..530e6d0ecf3
--- /dev/null
+++ b/tests/ui/traits/new-solver/cycles/inductive-cycle-discarded-coinductive-constraints.rs
@@ -0,0 +1,36 @@
+// check-pass
+// compile-flags: -Ztrait-solver=next
+#![feature(rustc_attrs, marker_trait_attr)]
+#[rustc_coinductive]
+trait Trait {}
+
+impl<T, U> Trait for (T, U)
+where
+    (U, T): Trait,
+    (T, U): Inductive,
+    (): ConstrainToU32<T>,
+{}
+
+trait ConstrainToU32<T> {}
+impl ConstrainToU32<u32> for () {}
+
+// We only prefer the candidate without an inductive cycle
+// once the inductive cycle has the same constraints as the
+// other goal.
+#[marker]
+trait Inductive {}
+impl<T, U> Inductive for (T, U)
+where
+    (T, U): Trait,
+{}
+
+impl Inductive for (u32, u32) {}
+
+fn impls_trait<T, U>()
+where
+    (T, U): Trait,
+{}
+
+fn main() {
+    impls_trait::<_, _>();
+}
diff --git a/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.rs b/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.rs
index f06b98a79cf..3cfe7ab87f6 100644
--- a/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.rs
+++ b/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.rs
@@ -39,7 +39,7 @@ fn impls_ar<T: AR>() {}
 
 fn main() {
     impls_a::<()>();
-    //~^ ERROR overflow evaluating the requirement `(): A`
+    // FIXME(-Ztrait-solver=next): This is broken and should error.
 
     impls_ar::<()>();
     //~^ ERROR overflow evaluating the requirement `(): AR`
diff --git a/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.stderr b/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.stderr
index 33fac603cbd..0e1c86c1bb3 100644
--- a/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.stderr
+++ b/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.stderr
@@ -1,16 +1,3 @@
-error[E0275]: overflow evaluating the requirement `(): A`
-  --> $DIR/inductive-not-on-stack.rs:41:5
-   |
-LL |     impls_a::<()>();
-   |     ^^^^^^^^^^^^^
-   |
-   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inductive_not_on_stack`)
-note: required by a bound in `impls_a`
-  --> $DIR/inductive-not-on-stack.rs:25:15
-   |
-LL | fn impls_a<T: A>() {}
-   |               ^ required by this bound in `impls_a`
-
 error[E0275]: overflow evaluating the requirement `(): AR`
   --> $DIR/inductive-not-on-stack.rs:44:5
    |
@@ -24,6 +11,6 @@ note: required by a bound in `impls_ar`
 LL | fn impls_ar<T: AR>() {}
    |                ^^ required by this bound in `impls_ar`
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/new-solver/leak-check-coinductive-cycle.rs b/tests/ui/traits/new-solver/cycles/leak-check-coinductive-cycle.rs
index 1f7d4a49c90..a6d31872673 100644
--- a/tests/ui/traits/new-solver/leak-check-coinductive-cycle.rs
+++ b/tests/ui/traits/new-solver/cycles/leak-check-coinductive-cycle.rs
@@ -1,5 +1,5 @@
-// check-pass
 // compile-flags: -Ztrait-solver=next
+// check-pass
 #![feature(rustc_attrs)]
 
 #[rustc_coinductive]
diff --git a/tests/ui/traits/new-solver/provisional-result-done.rs b/tests/ui/traits/new-solver/cycles/provisional-result-done.rs
index 589d34dd7ab..589d34dd7ab 100644
--- a/tests/ui/traits/new-solver/provisional-result-done.rs
+++ b/tests/ui/traits/new-solver/cycles/provisional-result-done.rs
diff --git a/tests/ui/traits/new-solver/dyn-any-dont-prefer-impl.rs b/tests/ui/traits/new-solver/dyn-any-dont-prefer-impl.rs
index 7d15b8c6392..af35a6195e0 100644
--- a/tests/ui/traits/new-solver/dyn-any-dont-prefer-impl.rs
+++ b/tests/ui/traits/new-solver/dyn-any-dont-prefer-impl.rs
@@ -1,6 +1,10 @@
 // compile-flags: -Ztrait-solver=next
 // check-pass
 
+// Test that selection prefers the builtin trait object impl for `Any`
+// instead of the user defined impl. Both impls apply to the trait
+// object.
+
 use std::any::Any;
 
 fn needs_usize(_: &usize) {}
diff --git a/tests/ui/traits/new-solver/exponential-trait-goals.rs b/tests/ui/traits/new-solver/overflow/exponential-trait-goals.rs
index b37f09ee185..b37f09ee185 100644
--- a/tests/ui/traits/new-solver/exponential-trait-goals.rs
+++ b/tests/ui/traits/new-solver/overflow/exponential-trait-goals.rs
diff --git a/tests/ui/traits/new-solver/exponential-trait-goals.stderr b/tests/ui/traits/new-solver/overflow/exponential-trait-goals.stderr
index 28a99cbbca6..28a99cbbca6 100644
--- a/tests/ui/traits/new-solver/exponential-trait-goals.stderr
+++ b/tests/ui/traits/new-solver/overflow/exponential-trait-goals.stderr
diff --git a/tests/ui/traits/new-solver/recursive-self-normalization-2.rs b/tests/ui/traits/new-solver/overflow/recursive-self-normalization-2.rs
index d086db475ac..d086db475ac 100644
--- a/tests/ui/traits/new-solver/recursive-self-normalization-2.rs
+++ b/tests/ui/traits/new-solver/overflow/recursive-self-normalization-2.rs
diff --git a/tests/ui/traits/new-solver/recursive-self-normalization-2.stderr b/tests/ui/traits/new-solver/overflow/recursive-self-normalization-2.stderr
index eebaf21d7df..eebaf21d7df 100644
--- a/tests/ui/traits/new-solver/recursive-self-normalization-2.stderr
+++ b/tests/ui/traits/new-solver/overflow/recursive-self-normalization-2.stderr
diff --git a/tests/ui/traits/new-solver/recursive-self-normalization.rs b/tests/ui/traits/new-solver/overflow/recursive-self-normalization.rs
index d15df7dea73..d15df7dea73 100644
--- a/tests/ui/traits/new-solver/recursive-self-normalization.rs
+++ b/tests/ui/traits/new-solver/overflow/recursive-self-normalization.rs
diff --git a/tests/ui/traits/new-solver/recursive-self-normalization.stderr b/tests/ui/traits/new-solver/overflow/recursive-self-normalization.stderr
index 6a87fe2f121..6a87fe2f121 100644
--- a/tests/ui/traits/new-solver/recursive-self-normalization.stderr
+++ b/tests/ui/traits/new-solver/overflow/recursive-self-normalization.stderr
diff --git a/tests/ui/where-clauses/where-clause-placement-type-alias.stderr b/tests/ui/where-clauses/where-clause-placement-type-alias.stderr
index b3c155a48dd..d341148b04c 100644
--- a/tests/ui/where-clauses/where-clause-placement-type-alias.stderr
+++ b/tests/ui/where-clauses/where-clause-placement-type-alias.stderr
@@ -4,7 +4,8 @@ error: where clauses are not allowed after the type for type aliases
 LL | type Bar = () where u32: Copy;
    |               ^^^^^^^^^^^^^^^
    |
-   = note: see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
+   = note: see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable
 
 error: where clauses are not allowed after the type for type aliases
   --> $DIR/where-clause-placement-type-alias.rs:8:15
@@ -12,7 +13,8 @@ error: where clauses are not allowed after the type for type aliases
 LL | type Baz = () where;
    |               ^^^^^
    |
-   = note: see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
+   = note: see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
+   = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable
 
 error: aborting due to 2 previous errors
 
diff --git a/triagebot.toml b/triagebot.toml
index 3b2114855c1..c513dce3f40 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -490,7 +490,7 @@ cc = ["@nnethercote"]
 [assign]
 warn_non_default_branch = true
 contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
-users_on_vacation = ["jyn514", "WaffleLapkin"]
+users_on_vacation = ["jyn514", "WaffleLapkin", "clubby789"]
 
 [assign.adhoc_groups]
 compiler-team = [
@@ -527,7 +527,6 @@ bootstrap = [
 ]
 infra-ci = [
     "@Mark-Simulacrum",
-    "@pietroalbini",
 ]
 rustdoc = [
     "@jsha",