about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml2
-rw-r--r--clippy_config/Cargo.toml2
-rw-r--r--clippy_lints/Cargo.toml2
-rw-r--r--clippy_lints/src/eta_reduction.rs4
-rw-r--r--clippy_lints/src/functions/must_use.rs5
-rw-r--r--clippy_lints/src/future_not_send.rs2
-rw-r--r--clippy_lints/src/inherent_impl.rs15
-rw-r--r--clippy_lints/src/large_stack_arrays.rs9
-rw-r--r--clippy_lints/src/min_ident_chars.rs6
-rw-r--r--clippy_lints/src/misc_early/mod.rs4
-rw-r--r--clippy_lints/src/no_effect.rs3
-rw-r--r--clippy_lints/src/non_copy_const.rs2
-rw-r--r--clippy_lints/src/returns.rs4
-rw-r--r--clippy_lints/src/trailing_empty_array.rs6
-rw-r--r--clippy_lints/src/trait_bounds.rs20
-rw-r--r--clippy_lints/src/types/type_complexity.rs2
-rw-r--r--clippy_lints/src/unnested_or_patterns.rs8
-rw-r--r--clippy_lints/src/utils/author.rs28
-rw-r--r--clippy_lints/src/zero_repeat_side_effects.rs5
-rw-r--r--clippy_utils/Cargo.toml2
-rw-r--r--clippy_utils/src/hir_utils.rs32
-rw-r--r--clippy_utils/src/lib.rs16
-rw-r--r--declare_clippy_lint/Cargo.toml2
-rw-r--r--rust-toolchain2
-rw-r--r--tests/ui/author/repeat.stdout3
-rw-r--r--tests/ui/track-diagnostics.stderr2
26 files changed, 112 insertions, 76 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 6e4878440c6..bb4dc97e748 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy"
-version = "0.1.81"
+version = "0.1.82"
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
 readme = "README.md"
diff --git a/clippy_config/Cargo.toml b/clippy_config/Cargo.toml
index be0b048ac0c..e1b2edc8a6f 100644
--- a/clippy_config/Cargo.toml
+++ b/clippy_config/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_config"
-version = "0.1.81"
+version = "0.1.82"
 edition = "2021"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml
index 5708ffba08f..eb04c006f89 100644
--- a/clippy_lints/Cargo.toml
+++ b/clippy_lints/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_lints"
-version = "0.1.81"
+version = "0.1.82"
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
 readme = "README.md"
diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs
index d2a34c75583..0ed7859418b 100644
--- a/clippy_lints/src/eta_reduction.rs
+++ b/clippy_lints/src/eta_reduction.rs
@@ -15,7 +15,7 @@ use rustc_middle::ty::{
 use rustc_session::declare_lint_pass;
 use rustc_span::symbol::sym;
 use rustc_target::spec::abi::Abi;
-use rustc_trait_selection::error_reporting::traits::InferCtxtExt as _;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt as _;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -178,7 +178,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
                                 // 'cuz currently nothing changes after deleting this check.
                                 local_used_in(cx, l, args) || local_used_after_expr(cx, l, expr)
                             }) {
-                                match cx.tcx.infer_ctxt().build().type_implements_fn_trait(
+                                match cx.tcx.infer_ctxt().build().err_ctxt().type_implements_fn_trait(
                                     cx.param_env,
                                     Binder::bind_with_vars(callee_ty_adjusted, List::empty()),
                                     ty::PredicatePolarity::Positive,
diff --git a/clippy_lints/src/functions/must_use.rs b/clippy_lints/src/functions/must_use.rs
index cce8617821e..b179d7b5249 100644
--- a/clippy_lints/src/functions/must_use.rs
+++ b/clippy_lints/src/functions/must_use.rs
@@ -16,6 +16,7 @@ use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::is_must_use_ty;
 use clippy_utils::visitors::for_each_expr_without_closures;
 use clippy_utils::{return_ty, trait_ref_of_method};
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 
 use core::ops::ControlFlow;
 
@@ -117,11 +118,11 @@ fn check_needless_must_use(
         // Ignore async functions unless Future::Output type is a must_use type
         if sig.header.is_async() {
             let infcx = cx.tcx.infer_ctxt().build();
-            if let Some(future_ty) = infcx.get_impl_future_output_ty(return_ty(cx, item_id))
+            if let Some(future_ty) = infcx.err_ctxt().get_impl_future_output_ty(return_ty(cx, item_id))
                 && !is_must_use_ty(cx, future_ty)
             {
                 return;
-            }
+            };
         }
 
         span_lint_and_help(
diff --git a/clippy_lints/src/future_not_send.rs b/clippy_lints/src/future_not_send.rs
index 2643de3b196..9488ba75686 100644
--- a/clippy_lints/src/future_not_send.rs
+++ b/clippy_lints/src/future_not_send.rs
@@ -9,7 +9,7 @@ use rustc_middle::ty::{self, AliasTy, ClauseKind, PredicateKind};
 use rustc_session::declare_lint_pass;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{sym, Span};
-use rustc_trait_selection::error_reporting::traits::suggestions::TypeErrCtxtExt;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::traits::{self, FulfillmentError, ObligationCtxt};
 
 declare_clippy_lint! {
diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs
index 95ae591884b..0d3786dad4b 100644
--- a/clippy_lints/src/inherent_impl.rs
+++ b/clippy_lints/src/inherent_impl.rs
@@ -56,19 +56,18 @@ impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl {
         let Ok(impls) = cx.tcx.crate_inherent_impls(()) else {
             return;
         };
-        let inherent_impls = cx
-            .tcx
-            .with_stable_hashing_context(|hcx| impls.inherent_impls.to_sorted(&hcx, true));
 
-        for (_, impl_ids) in inherent_impls.into_iter().filter(|(&id, impls)| {
-            impls.len() > 1
+        for (&id, impl_ids) in &impls.inherent_impls {
+            if impl_ids.len() < 2
             // Check for `#[allow]` on the type definition
-            && !is_lint_allowed(
+            || is_lint_allowed(
                 cx,
                 MULTIPLE_INHERENT_IMPL,
                 cx.tcx.local_def_id_to_hir_id(id),
-            )
-        }) {
+            ) {
+                continue;
+            }
+
             for impl_id in impl_ids.iter().map(|id| id.expect_local()) {
                 let impl_ty = cx.tcx.type_of(impl_id).instantiate_identity();
                 match type_map.entry(impl_ty) {
diff --git a/clippy_lints/src/large_stack_arrays.rs b/clippy_lints/src/large_stack_arrays.rs
index d2c3062c8bd..15a75b06089 100644
--- a/clippy_lints/src/large_stack_arrays.rs
+++ b/clippy_lints/src/large_stack_arrays.rs
@@ -106,13 +106,12 @@ fn might_be_expanded<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> bool {
     ///
     /// This is a fail-safe to a case where even the `is_from_proc_macro` is unable to determain the
     /// correct result.
-    fn repeat_expr_might_be_expanded<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> bool {
-        let ExprKind::Repeat(_, ArrayLen::Body(anon_const)) = expr.kind else {
+    fn repeat_expr_might_be_expanded(expr: &Expr<'_>) -> bool {
+        let ExprKind::Repeat(_, ArrayLen::Body(len_ct)) = expr.kind else {
             return false;
         };
-        let len_span = cx.tcx.def_span(anon_const.def_id);
-        !expr.span.contains(len_span)
+        !expr.span.contains(len_ct.span())
     }
 
-    expr.span.from_expansion() || is_from_proc_macro(cx, expr) || repeat_expr_might_be_expanded(cx, expr)
+    expr.span.from_expansion() || is_from_proc_macro(cx, expr) || repeat_expr_might_be_expanded(expr)
 }
diff --git a/clippy_lints/src/min_ident_chars.rs b/clippy_lints/src/min_ident_chars.rs
index e96369147d8..53fa444e93c 100644
--- a/clippy_lints/src/min_ident_chars.rs
+++ b/clippy_lints/src/min_ident_chars.rs
@@ -139,11 +139,11 @@ impl Visitor<'_> for IdentVisitor<'_, '_> {
                 return;
             }
 
-            // `struct Awa<T>(T)`
-            //                ^
+            // `struct Array<T, const N: usize>([T; N])`
+            //                                   ^  ^
             if let Node::PathSegment(path) = node {
                 if let Res::Def(def_kind, ..) = path.res
-                    && let DefKind::TyParam = def_kind
+                    && let DefKind::TyParam | DefKind::ConstParam = def_kind
                 {
                     return;
                 }
diff --git a/clippy_lints/src/misc_early/mod.rs b/clippy_lints/src/misc_early/mod.rs
index fedcfd11fdc..4cba13a05c2 100644
--- a/clippy_lints/src/misc_early/mod.rs
+++ b/clippy_lints/src/misc_early/mod.rs
@@ -364,8 +364,8 @@ declare_lint_pass!(MiscEarlyLints => [
 ]);
 
 impl EarlyLintPass for MiscEarlyLints {
-    fn check_generics(&mut self, cx: &EarlyContext<'_>, gen: &Generics) {
-        for param in &gen.params {
+    fn check_generics(&mut self, cx: &EarlyContext<'_>, generics: &Generics) {
+        for param in &generics.params {
             builtin_type_shadow::check(cx, param);
         }
     }
diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs
index 0ecfa7baa72..9d326c06eff 100644
--- a/clippy_lints/src/no_effect.rs
+++ b/clippy_lints/src/no_effect.rs
@@ -15,6 +15,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::impl_lint_pass;
 use rustc_span::Span;
+use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use std::ops::Deref;
 
 declare_clippy_lint! {
@@ -159,7 +160,7 @@ impl NoEffect {
                                 // Remove `impl Future<Output = T>` to get `T`
                                 if cx.tcx.ty_is_opaque_future(ret_ty)
                                     && let Some(true_ret_ty) =
-                                        cx.tcx.infer_ctxt().build().get_impl_future_output_ty(ret_ty)
+                                        cx.tcx.infer_ctxt().build().err_ctxt().get_impl_future_output_ty(ret_ty)
                                 {
                                     ret_ty = true_ret_ty;
                                 }
diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs
index 06c0f3dc39d..15bb328b446 100644
--- a/clippy_lints/src/non_copy_const.rs
+++ b/clippy_lints/src/non_copy_const.rs
@@ -234,7 +234,7 @@ impl<'tcx> NonCopyConst<'tcx> {
 
     fn is_value_unfrozen_raw(
         cx: &LateContext<'tcx>,
-        result: Result<Option<ty::ValTree<'tcx>>, ErrorHandled>,
+        result: Result<Result<ty::ValTree<'tcx>, Ty<'tcx>>, ErrorHandled>,
         ty: Ty<'tcx>,
     ) -> bool {
         result.map_or_else(
diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs
index d9a79fab14a..8ced47b48a4 100644
--- a/clippy_lints/src/returns.rs
+++ b/clippy_lints/src/returns.rs
@@ -394,8 +394,8 @@ fn check_final_expr<'tcx>(
 
             // Returns may be used to turn an expression into a statement in rustc's AST.
             // This allows the addition of attributes, like `#[allow]` (See: clippy#9361)
-            // `#[expect(clippy::needless_return)]` needs to be handled separately to
-            // actually fulfill the expectation (clippy::#12998)
+            // `#[expect(clippy::needless_return)]` needs to be handled separatly to
+            // actually fullfil the expectation (clippy::#12998)
             match cx.tcx.hir().attrs(expr.hir_id) {
                 [] => {},
                 [attr] => {
diff --git a/clippy_lints/src/trailing_empty_array.rs b/clippy_lints/src/trailing_empty_array.rs
index 462084e96a8..db8c63892b8 100644
--- a/clippy_lints/src/trailing_empty_array.rs
+++ b/clippy_lints/src/trailing_empty_array.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::has_repr_attr;
 use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::Const;
+use rustc_middle::ty::{Const, FeedConstTy};
 use rustc_session::declare_lint_pass;
 
 declare_clippy_lint! {
@@ -53,14 +53,14 @@ impl<'tcx> LateLintPass<'tcx> for TrailingEmptyArray {
     }
 }
 
-fn is_struct_with_trailing_zero_sized_array(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
+fn is_struct_with_trailing_zero_sized_array<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool {
     if let ItemKind::Struct(data, _) = &item.kind
         // First check if last field is an array
         && let Some(last_field) = data.fields().last()
         && let rustc_hir::TyKind::Array(_, rustc_hir::ArrayLen::Body(length)) = last_field.ty.kind
 
         // Then check if that array is zero-sized
-        && let length = Const::from_anon_const(cx.tcx, length.def_id)
+        && let length = Const::from_const_arg(cx.tcx, length, FeedConstTy::No)
         && let length = length.try_eval_target_usize(cx.tcx, cx.param_env)
         && let Some(length) = length
     {
diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs
index 174ef8d8084..922a0006ee5 100644
--- a/clippy_lints/src/trait_bounds.rs
+++ b/clippy_lints/src/trait_bounds.rs
@@ -104,9 +104,9 @@ impl TraitBounds {
 impl_lint_pass!(TraitBounds => [TYPE_REPETITION_IN_BOUNDS, TRAIT_DUPLICATION_IN_BOUNDS]);
 
 impl<'tcx> LateLintPass<'tcx> for TraitBounds {
-    fn check_generics(&mut self, cx: &LateContext<'tcx>, gen: &'tcx Generics<'_>) {
-        self.check_type_repetition(cx, gen);
-        check_trait_bound_duplication(cx, gen);
+    fn check_generics(&mut self, cx: &LateContext<'tcx>, generics: &'tcx Generics<'_>) {
+        self.check_type_repetition(cx, generics);
+        check_trait_bound_duplication(cx, generics);
     }
 
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
@@ -240,7 +240,7 @@ impl TraitBounds {
     }
 
     #[allow(clippy::mutable_key_type)]
-    fn check_type_repetition<'tcx>(&self, cx: &LateContext<'tcx>, gen: &'tcx Generics<'_>) {
+    fn check_type_repetition<'tcx>(&self, cx: &LateContext<'tcx>, generics: &'tcx Generics<'_>) {
         struct SpanlessTy<'cx, 'tcx> {
             ty: &'tcx Ty<'tcx>,
             cx: &'cx LateContext<'tcx>,
@@ -260,12 +260,12 @@ impl TraitBounds {
         }
         impl Eq for SpanlessTy<'_, '_> {}
 
-        if gen.span.from_expansion() {
+        if generics.span.from_expansion() {
             return;
         }
         let mut map: UnhashMap<SpanlessTy<'_, '_>, Vec<&GenericBound<'_>>> = UnhashMap::default();
         let mut applicability = Applicability::MaybeIncorrect;
-        for bound in gen.predicates {
+        for bound in generics.predicates {
             if let WherePredicate::BoundPredicate(ref p) = bound
                 && p.origin != PredicateOrigin::ImplTrait
                 && p.bounds.len() as u64 <= self.max_trait_bounds
@@ -303,8 +303,8 @@ impl TraitBounds {
     }
 }
 
-fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
-    if gen.span.from_expansion() {
+fn check_trait_bound_duplication(cx: &LateContext<'_>, generics: &'_ Generics<'_>) {
+    if generics.span.from_expansion() {
         return;
     }
 
@@ -315,7 +315,7 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
     //       |
     // collects each of these where clauses into a set keyed by generic name and comparable trait
     // eg. (T, Clone)
-    let where_predicates = gen
+    let where_predicates = generics
         .predicates
         .iter()
         .filter_map(|pred| {
@@ -344,7 +344,7 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
     //            |
     // compare trait bounds keyed by generic name and comparable trait to collected where
     // predicates eg. (T, Clone)
-    for predicate in gen.predicates.iter().filter(|pred| !pred.in_where_clause()) {
+    for predicate in generics.predicates.iter().filter(|pred| !pred.in_where_clause()) {
         if let WherePredicate::BoundPredicate(bound_predicate) = predicate
             && bound_predicate.origin != PredicateOrigin::ImplTrait
             && !bound_predicate.span.from_expansion()
diff --git a/clippy_lints/src/types/type_complexity.rs b/clippy_lints/src/types/type_complexity.rs
index 0aa50c99c16..b6e765d7c39 100644
--- a/clippy_lints/src/types/type_complexity.rs
+++ b/clippy_lints/src/types/type_complexity.rs
@@ -57,7 +57,7 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor {
                     bound
                         .bound_generic_params
                         .iter()
-                        .any(|gen| matches!(gen.kind, GenericParamKind::Lifetime { .. }))
+                        .any(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
                 });
                 if has_lifetime_parameters {
                     // complex trait bounds like A<'a, 'b>
diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs
index 4498795ea14..98f0be3135d 100644
--- a/clippy_lints/src/unnested_or_patterns.rs
+++ b/clippy_lints/src/unnested_or_patterns.rs
@@ -123,7 +123,7 @@ fn remove_all_parens(pat: &mut P<Pat>) {
     struct Visitor;
     impl MutVisitor for Visitor {
         fn visit_pat(&mut self, pat: &mut P<Pat>) {
-            noop_visit_pat(pat, self);
+            walk_pat(self, pat);
             let inner = match &mut pat.kind {
                 Paren(i) => mem::replace(&mut i.kind, Wild),
                 _ => return,
@@ -140,7 +140,7 @@ fn insert_necessary_parens(pat: &mut P<Pat>) {
     impl MutVisitor for Visitor {
         fn visit_pat(&mut self, pat: &mut P<Pat>) {
             use ast::BindingMode;
-            noop_visit_pat(pat, self);
+            walk_pat(self, pat);
             let target = match &mut pat.kind {
                 // `i @ a | b`, `box a | b`, and `& mut? a | b`.
                 Ident(.., Some(p)) | Box(p) | Ref(p, _) if matches!(&p.kind, Or(ps) if ps.len() > 1) => p,
@@ -162,7 +162,7 @@ fn unnest_or_patterns(pat: &mut P<Pat>) -> bool {
     impl MutVisitor for Visitor {
         fn visit_pat(&mut self, p: &mut P<Pat>) {
             // This is a bottom up transformation, so recurse first.
-            noop_visit_pat(p, self);
+            walk_pat(self, p);
 
             // Don't have an or-pattern? Just quit early on.
             let Or(alternatives) = &mut p.kind else { return };
@@ -191,7 +191,7 @@ fn unnest_or_patterns(pat: &mut P<Pat>) -> bool {
 
             // Deal with `Some(Some(0)) | Some(Some(1))`.
             if this_level_changed {
-                noop_visit_pat(p, self);
+                walk_pat(self, p);
             }
         }
     }
diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs
index e9d69407df8..316c1f32d3a 100644
--- a/clippy_lints/src/utils/author.rs
+++ b/clippy_lints/src/utils/author.rs
@@ -5,10 +5,9 @@ use clippy_utils::{get_attr, higher};
 use rustc_ast::ast::{LitFloatType, LitKind};
 use rustc_ast::LitIntType;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_hir as hir;
 use rustc_hir::{
-    ArrayLen, BindingMode, CaptureBy, Closure, ClosureKind, CoroutineKind, ExprKind, FnRetTy, HirId, Lit, PatKind,
-    QPath, StmtKind, TyKind,
+    self as hir, ArrayLen, BindingMode, CaptureBy, Closure, ClosureKind, ConstArg, ConstArgKind, CoroutineKind,
+    ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind,
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::declare_lint_pass;
@@ -270,6 +269,21 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
         }
     }
 
+    fn const_arg(&self, const_arg: &Binding<&ConstArg<'_>>) {
+        match const_arg.value.kind {
+            ConstArgKind::Path(ref qpath) => {
+                bind!(self, qpath);
+                chain!(self, "let ConstArgKind::Path(ref {qpath}) = {const_arg}.kind");
+                self.qpath(qpath);
+            },
+            ConstArgKind::Anon(anon_const) => {
+                bind!(self, anon_const);
+                chain!(self, "let ConstArgKind::Anon({anon_const}) = {const_arg}.kind");
+                self.body(field!(anon_const.body));
+            },
+        }
+    }
+
     fn lit(&self, lit: &Binding<&Lit>) {
         let kind = |kind| chain!(self, "let LitKind::{kind} = {lit}.node");
         macro_rules! kind {
@@ -602,10 +616,10 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
                 self.expr(value);
                 match length.value {
                     ArrayLen::Infer(..) => chain!(self, "let ArrayLen::Infer(..) = length"),
-                    ArrayLen::Body(anon_const) => {
-                        bind!(self, anon_const);
-                        chain!(self, "let ArrayLen::Body({anon_const}) = {length}");
-                        self.body(field!(anon_const.body));
+                    ArrayLen::Body(const_arg) => {
+                        bind!(self, const_arg);
+                        chain!(self, "let ArrayLen::Body({const_arg}) = {length}");
+                        self.const_arg(const_arg);
                     },
                 }
             },
diff --git a/clippy_lints/src/zero_repeat_side_effects.rs b/clippy_lints/src/zero_repeat_side_effects.rs
index fa1cc41d1dd..fdc1d06e67a 100644
--- a/clippy_lints/src/zero_repeat_side_effects.rs
+++ b/clippy_lints/src/zero_repeat_side_effects.rs
@@ -5,7 +5,7 @@ use clippy_utils::visitors::for_each_expr_without_closures;
 use rustc_ast::LitKind;
 use rustc_data_structures::packed::Pu128;
 use rustc_errors::Applicability;
-use rustc_hir::{ArrayLen, ExprKind, Node};
+use rustc_hir::{ArrayLen, ConstArgKind, ExprKind, Node};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::Ty;
 use rustc_session::declare_lint_pass;
@@ -61,7 +61,8 @@ impl LateLintPass<'_> for ZeroRepeatSideEffects {
         // the const item depends on `#[cfg]s` and has different values in different compilation
         // sessions).
         else if let ExprKind::Repeat(inner_expr, length) = expr.kind
-            && let ArrayLen::Body(anon_const) = length
+            && let ArrayLen::Body(const_arg) = length
+            && let ConstArgKind::Anon(anon_const) = const_arg.kind
             && let length_expr = hir_map.body(anon_const.body).value
             && !length_expr.span.from_expansion()
             && let ExprKind::Lit(literal) = length_expr.kind
diff --git a/clippy_utils/Cargo.toml b/clippy_utils/Cargo.toml
index 6e53ff3ee6e..f0c64fdd573 100644
--- a/clippy_utils/Cargo.toml
+++ b/clippy_utils/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_utils"
-version = "0.1.81"
+version = "0.1.82"
 edition = "2021"
 publish = false
 
diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs
index 8706cec5d38..28178a61a93 100644
--- a/clippy_utils/src/hir_utils.rs
+++ b/clippy_utils/src/hir_utils.rs
@@ -7,9 +7,9 @@ use rustc_data_structures::fx::FxHasher;
 use rustc_hir::def::Res;
 use rustc_hir::MatchSource::TryDesugar;
 use rustc_hir::{
-    ArrayLen, AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy,
-    GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeName, Pat, PatField,
-    PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind,
+    ArrayLen, AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr,
+    ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime,
+    LifetimeName, Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind,
 };
 use rustc_lexer::{tokenize, TokenKind};
 use rustc_lint::LateContext;
@@ -227,7 +227,7 @@ impl HirEqInterExpr<'_, '_, '_> {
     pub fn eq_array_length(&mut self, left: ArrayLen<'_>, right: ArrayLen<'_>) -> bool {
         match (left, right) {
             (ArrayLen::Infer(..), ArrayLen::Infer(..)) => true,
-            (ArrayLen::Body(l_ct), ArrayLen::Body(r_ct)) => self.eq_body(l_ct.body, r_ct.body),
+            (ArrayLen::Body(l_ct), ArrayLen::Body(r_ct)) => self.eq_const_arg(l_ct, r_ct),
             (_, _) => false,
         }
     }
@@ -411,7 +411,7 @@ impl HirEqInterExpr<'_, '_, '_> {
 
     fn eq_generic_arg(&mut self, left: &GenericArg<'_>, right: &GenericArg<'_>) -> bool {
         match (left, right) {
-            (GenericArg::Const(l), GenericArg::Const(r)) => self.eq_body(l.value.body, r.value.body),
+            (GenericArg::Const(l), GenericArg::Const(r)) => self.eq_const_arg(l, r),
             (GenericArg::Lifetime(l_lt), GenericArg::Lifetime(r_lt)) => Self::eq_lifetime(l_lt, r_lt),
             (GenericArg::Type(l_ty), GenericArg::Type(r_ty)) => self.eq_ty(l_ty, r_ty),
             (GenericArg::Infer(l_inf), GenericArg::Infer(r_inf)) => self.eq_ty(&l_inf.to_ty(), &r_inf.to_ty()),
@@ -419,6 +419,17 @@ impl HirEqInterExpr<'_, '_, '_> {
         }
     }
 
+    fn eq_const_arg(&mut self, left: &ConstArg<'_>, right: &ConstArg<'_>) -> bool {
+        match (&left.kind, &right.kind) {
+            (ConstArgKind::Path(l_p), ConstArgKind::Path(r_p)) => self.eq_qpath(l_p, r_p),
+            (ConstArgKind::Anon(l_an), ConstArgKind::Anon(r_an)) => self.eq_body(l_an.body, r_an.body),
+            // Use explicit match for now since ConstArg is undergoing flux.
+            (ConstArgKind::Path(..), ConstArgKind::Anon(..)) | (ConstArgKind::Anon(..), ConstArgKind::Path(..)) => {
+                false
+            },
+        }
+    }
+
     fn eq_lifetime(left: &Lifetime, right: &Lifetime) -> bool {
         left.res == right.res
     }
@@ -1123,7 +1134,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
     pub fn hash_array_length(&mut self, length: ArrayLen<'_>) {
         match length {
             ArrayLen::Infer(..) => {},
-            ArrayLen::Body(anon_const) => self.hash_body(anon_const.body),
+            ArrayLen::Body(ct) => self.hash_const_arg(ct),
         }
     }
 
@@ -1134,12 +1145,19 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
         self.maybe_typeck_results = old_maybe_typeck_results;
     }
 
+    fn hash_const_arg(&mut self, const_arg: &ConstArg<'_>) {
+        match &const_arg.kind {
+            ConstArgKind::Path(path) => self.hash_qpath(path),
+            ConstArgKind::Anon(anon) => self.hash_body(anon.body),
+        }
+    }
+
     fn hash_generic_args(&mut self, arg_list: &[GenericArg<'_>]) {
         for arg in arg_list {
             match *arg {
                 GenericArg::Lifetime(l) => self.hash_lifetime(l),
                 GenericArg::Type(ty) => self.hash_ty(ty),
-                GenericArg::Const(ref ca) => self.hash_body(ca.value.body),
+                GenericArg::Const(ca) => self.hash_const_arg(ca),
                 GenericArg::Infer(ref inf) => self.hash_ty(&inf.to_ty()),
             }
         }
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index 476370133ae..1d5f1a2a2bb 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -102,11 +102,11 @@ use rustc_hir::hir_id::{HirIdMap, HirIdSet};
 use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
 use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
 use rustc_hir::{
-    self as hir, def, Arm, ArrayLen, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstContext,
-    Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind,
-    ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat,
-    PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef,
-    TyKind, UnOp,
+    self as hir, def, Arm, ArrayLen, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind,
+    ConstContext, Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem,
+    ImplItemKind, ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode,
+    Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef,
+    TraitRef, TyKind, UnOp,
 };
 use rustc_lexer::{tokenize, TokenKind};
 use rustc_lint::{LateContext, Level, Lint, LintContext};
@@ -914,7 +914,8 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
         },
         ExprKind::Tup(items) | ExprKind::Array(items) => items.iter().all(|x| is_default_equivalent(cx, x)),
         ExprKind::Repeat(x, ArrayLen::Body(len)) => {
-            if let ExprKind::Lit(const_lit) = cx.tcx.hir().body(len.body).value.kind
+            if let ConstArgKind::Anon(anon_const) = len.kind
+                && let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind
                 && let LitKind::Int(v, _) = const_lit.node
                 && v <= 32
                 && is_default_equivalent(cx, x)
@@ -943,7 +944,8 @@ fn is_default_equivalent_from(cx: &LateContext<'_>, from_func: &Expr<'_>, arg: &
             }) => return sym.is_empty() && is_path_lang_item(cx, ty, LangItem::String),
             ExprKind::Array([]) => return is_path_diagnostic_item(cx, ty, sym::Vec),
             ExprKind::Repeat(_, ArrayLen::Body(len)) => {
-                if let ExprKind::Lit(const_lit) = cx.tcx.hir().body(len.body).value.kind
+                if let ConstArgKind::Anon(anon_const) = len.kind
+                    && let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind
                     && let LitKind::Int(v, _) = const_lit.node
                 {
                     return v == 0 && is_path_diagnostic_item(cx, ty, sym::Vec);
diff --git a/declare_clippy_lint/Cargo.toml b/declare_clippy_lint/Cargo.toml
index 86d945c14a5..80106f683c2 100644
--- a/declare_clippy_lint/Cargo.toml
+++ b/declare_clippy_lint/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "declare_clippy_lint"
-version = "0.1.81"
+version = "0.1.82"
 edition = "2021"
 publish = false
 
diff --git a/rust-toolchain b/rust-toolchain
index a61c22c59f9..69fb11a4824 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1,4 +1,4 @@
 [toolchain]
-channel = "nightly-2024-07-11"
+channel = "nightly-2024-07-25"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
 profile = "minimal"
diff --git a/tests/ui/author/repeat.stdout b/tests/ui/author/repeat.stdout
index c2a369610cc..d9e3f864f12 100644
--- a/tests/ui/author/repeat.stdout
+++ b/tests/ui/author/repeat.stdout
@@ -1,7 +1,8 @@
 if let ExprKind::Repeat(value, length) = expr.kind
     && let ExprKind::Lit(ref lit) = value.kind
     && let LitKind::Int(1, LitIntType::Unsigned(UintTy::U8)) = lit.node
-    && let ArrayLen::Body(anon_const) = length
+    && let ArrayLen::Body(const_arg) = length
+    && let ConstArgKind::Anon(anon_const) = const_arg.kind
     && expr1 = &cx.tcx.hir().body(anon_const.body).value
     && let ExprKind::Lit(ref lit1) = expr1.kind
     && let LitKind::Int(5, LitIntType::Unsuffixed) = lit1.node
diff --git a/tests/ui/track-diagnostics.stderr b/tests/ui/track-diagnostics.stderr
index 410e80f2528..83451fb658d 100644
--- a/tests/ui/track-diagnostics.stderr
+++ b/tests/ui/track-diagnostics.stderr
@@ -3,7 +3,7 @@ error[E0308]: mismatched types
    |
 LL | const S: A = B;
    |              ^ expected `A`, found `B`
--Ztrack-diagnostics: created at compiler/rustc_infer/src/infer/error_reporting/mod.rs:LL:CC
+-Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs:LL:CC
 
 error: aborting due to 1 previous error