diff --git a/Cargo.toml b/Cargo.toml index 6e4878440c68..bb4dc97e748e 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 be0b048ac0c7..e1b2edc8a6ff 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 5708ffba08fd..eb04c006f89f 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 d2a34c755832..0ed7859418bc 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 cce8617821e2..b179d7b52492 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 2643de3b196f..9488ba756865 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 95ae591884bc..0d3786dad4b1 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 d2c3062c8bd9..15a75b060896 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 e96369147d8c..53fa444e93c4 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)` - // ^ + // `struct Array([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 fedcfd11fdcc..4cba13a05c24 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 0ecfa7baa72d..9d326c06eff6 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` 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 06c0f3dc39d6..15bb328b4465 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>, ErrorHandled>, + result: Result, 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 d9a79fab14a0..8ced47b48a43 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 462084e96a86..db8c63892b84 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 174ef8d80842..922a0006ee51 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, 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 0aa50c99c169..b6e765d7c393 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 4498795ea144..98f0be3135db 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) { struct Visitor; impl MutVisitor for Visitor { fn visit_pat(&mut self, pat: &mut P) { - 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) { impl MutVisitor for Visitor { fn visit_pat(&mut self, pat: &mut P) { 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) -> bool { impl MutVisitor for Visitor { fn visit_pat(&mut self, p: &mut P) { // 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) -> 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 e9d69407df8b..316c1f32d3a2 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 fa1cc41d1dd1..fdc1d06e67a1 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 6e53ff3ee6e9..f0c64fdd573c 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 8706cec5d388..28178a61a932 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 476370133aee..1d5f1a2a2bb1 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 86d945c14a58..80106f683c2a 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 a61c22c59f98..69fb11a4824a 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 c2a369610cc1..d9e3f864f12f 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 410e80f25280..83451fb658d0 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