From bc410fc9f59e0cfbda6a6b4a96bf3d975227bbbe Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 14 Dec 2024 14:53:11 +0000 Subject: [PATCH 01/12] Stop handling specialization in clippy's to_string_trait_impl lint ToString can no longer be specialized, so no need to account for it in to_string_trait_impl either. --- clippy_lints/src/to_string_trait_impl.rs | 3 -- tests/ui/to_string_trait_impl.rs | 43 ------------------------ tests/ui/to_string_trait_impl.stderr | 14 +------- 3 files changed, 1 insertion(+), 59 deletions(-) diff --git a/clippy_lints/src/to_string_trait_impl.rs b/clippy_lints/src/to_string_trait_impl.rs index 0361836cdec7..9596b85664b3 100644 --- a/clippy_lints/src/to_string_trait_impl.rs +++ b/clippy_lints/src/to_string_trait_impl.rs @@ -1,5 +1,4 @@ use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::ty::implements_trait; use rustc_hir::{Impl, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; @@ -54,8 +53,6 @@ impl<'tcx> LateLintPass<'tcx> for ToStringTraitImpl { }) = it.kind && let Some(trait_did) = trait_ref.trait_def_id() && cx.tcx.is_diagnostic_item(sym::ToString, trait_did) - && let Some(display_did) = cx.tcx.get_diagnostic_item(sym::Display) - && !implements_trait(cx, cx.tcx.type_of(it.owner_id).instantiate_identity(), display_did, &[]) { span_lint_and_help( cx, diff --git a/tests/ui/to_string_trait_impl.rs b/tests/ui/to_string_trait_impl.rs index 4c1202d42034..7be9f7994f08 100644 --- a/tests/ui/to_string_trait_impl.rs +++ b/tests/ui/to_string_trait_impl.rs @@ -30,46 +30,3 @@ impl Bar { String::from("Bar") } } - -mod issue12263 { - pub struct MyStringWrapper<'a>(&'a str); - - impl std::fmt::Display for MyStringWrapper<'_> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.0.fmt(f) - } - } - - impl ToString for MyStringWrapper<'_> { - fn to_string(&self) -> String { - self.0.to_string() - } - } - - pub struct S(T); - impl std::fmt::Display for S { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - todo!() - } - } - // no specialization if the generics differ, so lint - impl ToString for S { - fn to_string(&self) -> String { - todo!() - } - } - - pub struct S2(T); - impl std::fmt::Display for S2 { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - todo!() - } - } - - // also specialization if the generics don't differ - impl ToString for S2 { - fn to_string(&self) -> String { - todo!() - } - } -} diff --git a/tests/ui/to_string_trait_impl.stderr b/tests/ui/to_string_trait_impl.stderr index 304c9a5e1fb7..fe8afc215f0c 100644 --- a/tests/ui/to_string_trait_impl.stderr +++ b/tests/ui/to_string_trait_impl.stderr @@ -12,17 +12,5 @@ LL | | } = note: `-D clippy::to-string-trait-impl` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::to_string_trait_impl)]` -error: direct implementation of `ToString` - --> tests/ui/to_string_trait_impl.rs:56:5 - | -LL | / impl ToString for S { -LL | | fn to_string(&self) -> String { -LL | | todo!() -LL | | } -LL | | } - | |_____^ - | - = help: prefer implementing `Display` instead - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error From acf9177431d34f027d4a59d2775c77e37104b9e1 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 13 Dec 2024 12:19:46 +0000 Subject: [PATCH 02/12] Add some convenience helper methods on `hir::Safety` --- clippy_lints/src/derive.rs | 4 ++-- clippy_lints/src/eta_reduction.rs | 2 +- clippy_lints/src/functions/misnamed_getters.rs | 4 ++-- clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs | 4 ++-- clippy_lints/src/inherent_to_string.rs | 4 ++-- clippy_lints/src/multiple_unsafe_ops_per_block.rs | 6 +++--- clippy_lints/src/new_without_default.rs | 2 +- clippy_lints/src/ptr.rs | 4 ++-- clippy_lints/src/undocumented_unsafe_blocks.rs | 4 ++-- clippy_utils/src/check_proc_macro.rs | 2 +- clippy_utils/src/ty.rs | 4 ++-- clippy_utils/src/visitors.rs | 10 +++++----- 12 files changed, 25 insertions(+), 25 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 8125dab8adf6..f65edd362530 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -7,7 +7,7 @@ use rustc_errors::Applicability; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{FnKind, Visitor, walk_expr, walk_fn, walk_item}; use rustc_hir::{ - self as hir, BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, Impl, Item, ItemKind, Safety, UnsafeSource, + self as hir, BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, Impl, Item, ItemKind, UnsafeSource, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; @@ -421,7 +421,7 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> { id: LocalDefId, ) -> Self::Result { if let Some(header) = kind.header() - && header.safety == Safety::Unsafe + && header.safety.is_unsafe() { ControlFlow::Break(()) } else { diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 8c22e43349f6..2cd48ef98e52 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -281,7 +281,7 @@ fn check_inputs( } fn check_sig<'tcx>(closure_sig: FnSig<'tcx>, call_sig: FnSig<'tcx>) -> bool { - call_sig.safety == Safety::Safe && !has_late_bound_to_non_late_bound_regions(closure_sig, call_sig) + call_sig.safety.is_safe() && !has_late_bound_to_non_late_bound_regions(closure_sig, call_sig) } /// This walks through both signatures and checks for any time a late-bound region is expected by an diff --git a/clippy_lints/src/functions/misnamed_getters.rs b/clippy_lints/src/functions/misnamed_getters.rs index 2cbc4b072341..017571c38db6 100644 --- a/clippy_lints/src/functions/misnamed_getters.rs +++ b/clippy_lints/src/functions/misnamed_getters.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; -use rustc_hir::{Body, ExprKind, FnDecl, ImplicitSelfKind, Safety}; +use rustc_hir::{Body, ExprKind, FnDecl, ImplicitSelfKind}; use rustc_lint::LateContext; use rustc_middle::ty; use rustc_span::Span; @@ -34,7 +34,7 @@ pub fn check_fn(cx: &LateContext<'_>, kind: FnKind<'_>, decl: &FnDecl<'_>, body: ImplicitSelfKind::None => return, }; - let name = if sig.header.safety == Safety::Unsafe { + let name = if sig.header.safety.is_unsafe() { name.strip_suffix("_unchecked").unwrap_or(name) } else { name diff --git a/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs index 4986a311eba8..3ded8dc30127 100644 --- a/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs +++ b/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs @@ -42,7 +42,7 @@ fn check_raw_ptr<'tcx>( body: &'tcx hir::Body<'tcx>, def_id: LocalDefId, ) { - if safety == hir::Safety::Safe && cx.effective_visibilities.is_exported(def_id) { + if safety.is_safe() && cx.effective_visibilities.is_exported(def_id) { let raw_ptrs = iter_input_pats(decl, body) .filter_map(|arg| raw_ptr_arg(cx, arg)) .collect::(); @@ -58,7 +58,7 @@ fn check_raw_ptr<'tcx>( }, hir::ExprKind::MethodCall(_, recv, args, _) => { let def_id = typeck.type_dependent_def_id(e.hir_id).unwrap(); - if cx.tcx.fn_sig(def_id).skip_binder().skip_binder().safety == hir::Safety::Unsafe { + if cx.tcx.fn_sig(def_id).skip_binder().skip_binder().safety.is_unsafe() { check_arg(cx, &raw_ptrs, recv); for arg in args { check_arg(cx, &raw_ptrs, arg); diff --git a/clippy_lints/src/inherent_to_string.rs b/clippy_lints/src/inherent_to_string.rs index ec6174bc0301..e096dd251759 100644 --- a/clippy_lints/src/inherent_to_string.rs +++ b/clippy_lints/src/inherent_to_string.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::ty::{implements_trait, is_type_lang_item}; use clippy_utils::{return_ty, trait_ref_of_method}; -use rustc_hir::{GenericParamKind, ImplItem, ImplItemKind, LangItem, Safety}; +use rustc_hir::{GenericParamKind, ImplItem, ImplItemKind, LangItem}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; use rustc_span::sym; @@ -95,7 +95,7 @@ impl<'tcx> LateLintPass<'tcx> for InherentToString { if let ImplItemKind::Fn(ref signature, _) = impl_item.kind // #11201 && let header = signature.header - && header.safety == Safety::Safe + && header.safety.is_safe() && header.abi == Abi::Rust && impl_item.ident.name == sym::to_string && let decl = signature.decl diff --git a/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/clippy_lints/src/multiple_unsafe_ops_per_block.rs index 12bcc608174f..79252bba74d7 100644 --- a/clippy_lints/src/multiple_unsafe_ops_per_block.rs +++ b/clippy_lints/src/multiple_unsafe_ops_per_block.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::visitors::{Descend, Visitable, for_each_expr}; use core::ops::ControlFlow::Continue; use hir::def::{DefKind, Res}; -use hir::{BlockCheckMode, ExprKind, QPath, Safety, UnOp}; +use hir::{BlockCheckMode, ExprKind, QPath, UnOp}; use rustc_ast::Mutability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; @@ -133,7 +133,7 @@ fn collect_unsafe_exprs<'tcx>( ty::FnPtr(sig_tys, hdr) => sig_tys.with(hdr), _ => return Continue(Descend::Yes), }; - if sig.safety() == Safety::Unsafe { + if sig.safety().is_unsafe() { unsafe_ops.push(("unsafe function call occurs here", expr.span)); } }, @@ -144,7 +144,7 @@ fn collect_unsafe_exprs<'tcx>( .type_dependent_def_id(expr.hir_id) .map(|def_id| cx.tcx.fn_sig(def_id)) { - if sig.skip_binder().safety() == Safety::Unsafe { + if sig.skip_binder().safety().is_unsafe() { unsafe_ops.push(("unsafe method call occurs here", expr.span)); } } diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index b60fea3f03e0..abdce69e7645 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -75,7 +75,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault { if let hir::ImplItemKind::Fn(ref sig, _) = impl_item.kind { let name = impl_item.ident.name; let id = impl_item.owner_id; - if sig.header.safety == hir::Safety::Unsafe { + if sig.header.safety.is_unsafe() { // can't be implemented for unsafe new return; } diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index dec4c18a309e..44a8789462b0 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -8,7 +8,7 @@ use rustc_hir::hir_id::{HirId, HirIdMap}; use rustc_hir::intravisit::{Visitor, walk_expr}; use rustc_hir::{ self as hir, AnonConst, BinOpKind, BindingMode, Body, Expr, ExprKind, FnRetTy, FnSig, GenericArg, ImplItemKind, - ItemKind, Lifetime, Mutability, Node, Param, PatKind, QPath, Safety, TraitFn, TraitItem, TraitItemKind, TyKind, + ItemKind, Lifetime, Mutability, Node, Param, PatKind, QPath, TraitFn, TraitItem, TraitItemKind, TyKind, }; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{Obligation, ObligationCause}; @@ -541,7 +541,7 @@ fn check_mut_from_ref<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Optio .collect(); if let Some(args) = args && !args.is_empty() - && body.is_none_or(|body| sig.header.safety == Safety::Unsafe || contains_unsafe_block(cx, body.value)) + && body.is_none_or(|body| sig.header.safety.is_unsafe() || contains_unsafe_block(cx, body.value)) { span_lint_and_then( cx, diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs index b79e59f857bb..45d730985bb1 100644 --- a/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -203,7 +203,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { let item_has_safety_comment = item_has_safety_comment(cx, item); match (&item.kind, item_has_safety_comment) { // lint unsafe impl without safety comment - (ItemKind::Impl(impl_), HasSafetyComment::No) if impl_.safety == hir::Safety::Unsafe => { + (ItemKind::Impl(impl_), HasSafetyComment::No) if impl_.safety.is_unsafe() => { if !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, item.hir_id()) && !is_unsafe_from_proc_macro(cx, item.span) { @@ -227,7 +227,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { } }, // lint safe impl with unnecessary safety comment - (ItemKind::Impl(impl_), HasSafetyComment::Yes(pos)) if impl_.safety == hir::Safety::Safe => { + (ItemKind::Impl(impl_), HasSafetyComment::Yes(pos)) if impl_.safety.is_safe() => { if !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, item.hir_id()) { let (span, help_span) = mk_spans(pos); diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index 3269bf758ac0..b71b53ea3bbf 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -373,7 +373,7 @@ fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) { TyKind::Ptr(MutTy { ty, .. }) => (Pat::Str("*"), ty_search_pat(ty).1), TyKind::Ref(_, MutTy { ty, .. }) => (Pat::Str("&"), ty_search_pat(ty).1), TyKind::BareFn(bare_fn) => ( - if bare_fn.safety == Safety::Unsafe { + if bare_fn.safety.is_unsafe() { Pat::Str("unsafe") } else if bare_fn.abi != Abi::Rust { Pat::Str("extern") diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index 260d1b801e3d..bc3c3ca5c217 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -9,7 +9,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{Expr, FnDecl, LangItem, Safety, TyKind}; +use rustc_hir::{Expr, FnDecl, LangItem, TyKind}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; use rustc_middle::mir::ConstValue; @@ -531,7 +531,7 @@ pub fn peel_mid_ty_refs_is_mutable(ty: Ty<'_>) -> (Ty<'_>, usize, Mutability) { /// Returns `true` if the given type is an `unsafe` function. pub fn type_is_unsafe_function<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { match ty.kind() { - ty::FnDef(..) | ty::FnPtr(..) => ty.fn_sig(cx.tcx).safety() == Safety::Unsafe, + ty::FnDef(..) | ty::FnPtr(..) => ty.fn_sig(cx.tcx).safety().is_unsafe(), _ => false, } } diff --git a/clippy_utils/src/visitors.rs b/clippy_utils/src/visitors.rs index 351e619d7b1e..b3d998fbc529 100644 --- a/clippy_utils/src/visitors.rs +++ b/clippy_utils/src/visitors.rs @@ -7,7 +7,7 @@ use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::intravisit::{self, Visitor, walk_block, walk_expr}; use rustc_hir::{ AnonConst, Arm, Block, BlockCheckMode, Body, BodyId, Expr, ExprKind, HirId, ItemId, ItemKind, LetExpr, Pat, QPath, - Safety, Stmt, UnOp, UnsafeSource, StructTailExpr, + Stmt, UnOp, UnsafeSource, StructTailExpr, }; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; @@ -426,15 +426,15 @@ pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool { .cx .typeck_results() .type_dependent_def_id(e.hir_id) - .is_some_and(|id| self.cx.tcx.fn_sig(id).skip_binder().safety() == Safety::Unsafe) => + .is_some_and(|id| self.cx.tcx.fn_sig(id).skip_binder().safety().is_unsafe()) => { ControlFlow::Break(()) }, ExprKind::Call(func, _) => match *self.cx.typeck_results().expr_ty(func).peel_refs().kind() { - ty::FnDef(id, _) if self.cx.tcx.fn_sig(id).skip_binder().safety() == Safety::Unsafe => { + ty::FnDef(id, _) if self.cx.tcx.fn_sig(id).skip_binder().safety().is_unsafe() => { ControlFlow::Break(()) }, - ty::FnPtr(_, hdr) if hdr.safety == Safety::Unsafe => ControlFlow::Break(()), + ty::FnPtr(_, hdr) if hdr.safety.is_unsafe() => ControlFlow::Break(()), _ => walk_expr(self, e), }, ExprKind::Path(ref p) @@ -458,7 +458,7 @@ pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool { } fn visit_nested_item(&mut self, id: ItemId) -> Self::Result { if let ItemKind::Impl(i) = &self.cx.tcx.hir().item(id).kind - && i.safety == Safety::Unsafe + && i.safety.is_unsafe() { ControlFlow::Break(()) } else { From f332026bc750db559f4ac204a8fe24d5029a9710 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 2 Dec 2024 11:27:57 +0000 Subject: [PATCH 03/12] Rename `value` field to `expr` to simplify later commits' diffs --- clippy_lints/src/attrs/should_panic_without_expect.rs | 2 +- clippy_lints/src/doc/include_in_doc_without_cfg.rs | 2 +- clippy_lints/src/large_include_file.rs | 2 +- clippy_utils/src/ast_utils.rs | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/attrs/should_panic_without_expect.rs b/clippy_lints/src/attrs/should_panic_without_expect.rs index 97cffeb098ef..1d6b3388e59f 100644 --- a/clippy_lints/src/attrs/should_panic_without_expect.rs +++ b/clippy_lints/src/attrs/should_panic_without_expect.rs @@ -9,7 +9,7 @@ use rustc_span::sym; pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) { if let AttrKind::Normal(normal_attr) = &attr.kind { - if let AttrArgs::Eq { value: AttrArgsEq::Ast(_), .. } = &normal_attr.item.args { + if let AttrArgs::Eq { expr: AttrArgsEq::Ast(_), .. } = &normal_attr.item.args { // `#[should_panic = ".."]` found, good return; } diff --git a/clippy_lints/src/doc/include_in_doc_without_cfg.rs b/clippy_lints/src/doc/include_in_doc_without_cfg.rs index 2182689f9851..f2886164a460 100644 --- a/clippy_lints/src/doc/include_in_doc_without_cfg.rs +++ b/clippy_lints/src/doc/include_in_doc_without_cfg.rs @@ -12,7 +12,7 @@ pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) { if !attr.span.from_expansion() && let AttrKind::Normal(ref normal) = attr.kind && normal.item.path == sym::doc - && let AttrArgs::Eq { value: AttrArgsEq::Hir(ref meta), .. } = normal.item.args + && let AttrArgs::Eq { expr: AttrArgsEq::Hir(ref meta), .. } = normal.item.args && !attr.span.contains(meta.span) // Since the `include_str` is already expanded at this point, we can only take the // whole attribute snippet and then modify for our suggestion. diff --git a/clippy_lints/src/large_include_file.rs b/clippy_lints/src/large_include_file.rs index b38e362410ef..a0657a233c10 100644 --- a/clippy_lints/src/large_include_file.rs +++ b/clippy_lints/src/large_include_file.rs @@ -96,7 +96,7 @@ impl LateLintPass<'_> for LargeIncludeFile { && let AttrKind::Normal(ref normal) = attr.kind && let Some(doc) = attr.doc_str() && doc.as_str().len() as u64 > self.max_file_size - && let AttrArgs::Eq { value: AttrArgsEq::Hir(ref meta), .. } = normal.item.args + && let AttrArgs::Eq { expr: AttrArgsEq::Hir(ref meta), .. } = normal.item.args && !attr.span.contains(meta.span) // Since the `include_str` is already expanded at this point, we can only take the // whole attribute snippet and then modify for our suggestion. diff --git a/clippy_utils/src/ast_utils.rs b/clippy_utils/src/ast_utils.rs index 12074dd16e60..6df0748c1177 100644 --- a/clippy_utils/src/ast_utils.rs +++ b/clippy_utils/src/ast_utils.rs @@ -872,8 +872,8 @@ pub fn eq_attr_args(l: &AttrArgs, r: &AttrArgs) -> bool { match (l, r) { (Empty, Empty) => true, (Delimited(la), Delimited(ra)) => eq_delim_args(la, ra), - (Eq { value: AttrArgsEq::Ast(le), .. }, Eq{ value: AttrArgsEq::Ast(re), .. }) => eq_expr(le, re), - (Eq { value: AttrArgsEq::Hir(ll), .. }, Eq{ value: AttrArgsEq::Hir(rl), .. }) => ll.kind == rl.kind, + (Eq { expr: AttrArgsEq::Ast(le), .. }, Eq{ expr: AttrArgsEq::Ast(re), .. }) => eq_expr(le, re), + (Eq { expr: AttrArgsEq::Hir(ll), .. }, Eq{ expr: AttrArgsEq::Hir(rl), .. }) => ll.kind == rl.kind, _ => false, } } From 6dfa37f02a86b4474fbae70e724f7fd6c9f32985 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20D=C3=B6nszelmann?= Date: Thu, 17 Oct 2024 01:14:01 +0200 Subject: [PATCH 04/12] Add hir::Attribute --- clippy_lints/src/attrs/inline_always.rs | 2 +- .../src/attrs/should_panic_without_expect.rs | 4 +- clippy_lints/src/cognitive_complexity.rs | 3 +- clippy_lints/src/doc/empty_line_after.rs | 4 +- .../src/doc/include_in_doc_without_cfg.rs | 10 ++-- clippy_lints/src/doc/mod.rs | 3 +- .../src/doc/suspicious_doc_comments.rs | 5 +- .../src/doc/too_long_first_doc_paragraph.rs | 3 +- clippy_lints/src/functions/must_use.rs | 3 +- clippy_lints/src/large_include_file.rs | 8 +-- clippy_lints/src/macro_use.rs | 3 +- .../src/matches/match_like_matches.rs | 4 +- clippy_lints/src/missing_doc.rs | 16 ++--- clippy_lints/src/missing_inline.rs | 4 +- clippy_lints/src/needless_pass_by_value.rs | 5 +- clippy_utils/src/ast_utils.rs | 3 +- clippy_utils/src/attrs.rs | 58 +++++++++---------- clippy_utils/src/lib.rs | 31 +++++----- clippy_utils/src/msrvs.rs | 16 ++--- 19 files changed, 90 insertions(+), 95 deletions(-) diff --git a/clippy_lints/src/attrs/inline_always.rs b/clippy_lints/src/attrs/inline_always.rs index d41bb580c6cd..2325f914b0b0 100644 --- a/clippy_lints/src/attrs/inline_always.rs +++ b/clippy_lints/src/attrs/inline_always.rs @@ -1,7 +1,7 @@ use super::INLINE_ALWAYS; use super::utils::is_word; use clippy_utils::diagnostics::span_lint; -use rustc_ast::Attribute; +use rustc_hir::Attribute; use rustc_lint::LateContext; use rustc_span::symbol::Symbol; use rustc_span::{Span, sym}; diff --git a/clippy_lints/src/attrs/should_panic_without_expect.rs b/clippy_lints/src/attrs/should_panic_without_expect.rs index 1d6b3388e59f..b4ed8a68a325 100644 --- a/clippy_lints/src/attrs/should_panic_without_expect.rs +++ b/clippy_lints/src/attrs/should_panic_without_expect.rs @@ -2,14 +2,14 @@ use super::{Attribute, SHOULD_PANIC_WITHOUT_EXPECT}; use clippy_utils::diagnostics::span_lint_and_sugg; use rustc_ast::token::{Token, TokenKind}; use rustc_ast::tokenstream::TokenTree; -use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind}; +use rustc_ast::{AttrArgs, AttrKind}; use rustc_errors::Applicability; use rustc_lint::EarlyContext; use rustc_span::sym; pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) { if let AttrKind::Normal(normal_attr) = &attr.kind { - if let AttrArgs::Eq { expr: AttrArgsEq::Ast(_), .. } = &normal_attr.item.args { + if let AttrArgs::Eq { .. } = &normal_attr.item.args { // `#[should_panic = ".."]` found, good return; } diff --git a/clippy_lints/src/cognitive_complexity.rs b/clippy_lints/src/cognitive_complexity.rs index 383fae7992b6..a1ff20dee721 100644 --- a/clippy_lints/src/cognitive_complexity.rs +++ b/clippy_lints/src/cognitive_complexity.rs @@ -5,9 +5,8 @@ use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::visitors::for_each_expr_without_closures; use clippy_utils::{LimitStack, get_async_fn_body, is_async_fn}; use core::ops::ControlFlow; -use rustc_ast::ast::Attribute; use rustc_hir::intravisit::FnKind; -use rustc_hir::{Body, Expr, ExprKind, FnDecl}; +use rustc_hir::{Attribute, Body, Expr, ExprKind, FnDecl}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::impl_lint_pass; use rustc_span::def_id::LocalDefId; diff --git a/clippy_lints/src/doc/empty_line_after.rs b/clippy_lints/src/doc/empty_line_after.rs index de7a2c2433f4..099194d4e746 100644 --- a/clippy_lints/src/doc/empty_line_after.rs +++ b/clippy_lints/src/doc/empty_line_after.rs @@ -2,10 +2,10 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::{SpanRangeExt, snippet_indent}; use clippy_utils::tokenize_with_text; use itertools::Itertools; +use rustc_ast::AttrStyle; use rustc_ast::token::CommentKind; -use rustc_ast::{AttrKind, AttrStyle, Attribute}; use rustc_errors::{Applicability, Diag, SuggestionStyle}; -use rustc_hir::{ItemKind, Node}; +use rustc_hir::{AttrKind, Attribute, ItemKind, Node}; use rustc_lexer::TokenKind; use rustc_lint::LateContext; use rustc_span::{BytePos, ExpnKind, InnerSpan, Span, SpanData}; diff --git a/clippy_lints/src/doc/include_in_doc_without_cfg.rs b/clippy_lints/src/doc/include_in_doc_without_cfg.rs index f2886164a460..0bb16a0c77d5 100644 --- a/clippy_lints/src/doc/include_in_doc_without_cfg.rs +++ b/clippy_lints/src/doc/include_in_doc_without_cfg.rs @@ -1,18 +1,18 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_opt; -use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind, AttrStyle, Attribute}; +use rustc_ast::{AttrStyle}; use rustc_errors::Applicability; use rustc_lint::LateContext; -use rustc_span::sym; +use rustc_hir::{Attribute, AttrKind, AttrArgs}; use super::DOC_INCLUDE_WITHOUT_CFG; pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) { for attr in attrs { if !attr.span.from_expansion() - && let AttrKind::Normal(ref normal) = attr.kind - && normal.item.path == sym::doc - && let AttrArgs::Eq { expr: AttrArgsEq::Hir(ref meta), .. } = normal.item.args + && let AttrKind::Normal(ref item) = attr.kind + && attr.doc_str().is_some() + && let AttrArgs::Eq { expr: meta, .. } = &item.args && !attr.span.contains(meta.span) // Since the `include_str` is already expanded at this point, we can only take the // whole attribute snippet and then modify for our suggestion. diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index 88ac871acf68..f65acd7978a7 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -16,10 +16,9 @@ use pulldown_cmark::Event::{ }; use pulldown_cmark::Tag::{BlockQuote, CodeBlock, FootnoteDefinition, Heading, Item, Link, Paragraph}; use pulldown_cmark::{BrokenLink, CodeBlockKind, CowStr, Options, TagEnd}; -use rustc_ast::ast::Attribute; use rustc_data_structures::fx::FxHashSet; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{AnonConst, Expr, ImplItemKind, ItemKind, Node, Safety, TraitItemKind}; +use rustc_hir::{AnonConst, Attribute, Expr, ImplItemKind, ItemKind, Node, Safety, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::nested_filter; use rustc_middle::lint::in_external_macro; diff --git a/clippy_lints/src/doc/suspicious_doc_comments.rs b/clippy_lints/src/doc/suspicious_doc_comments.rs index f6f942b10cad..84393213e6f0 100644 --- a/clippy_lints/src/doc/suspicious_doc_comments.rs +++ b/clippy_lints/src/doc/suspicious_doc_comments.rs @@ -1,7 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_then; +use rustc_ast::AttrStyle; use rustc_ast::token::CommentKind; -use rustc_ast::{AttrKind, AttrStyle, Attribute}; use rustc_errors::Applicability; +use rustc_hir::Attribute; use rustc_lint::LateContext; use rustc_span::Span; @@ -35,7 +36,7 @@ fn collect_doc_replacements(attrs: &[Attribute]) -> Vec<(Span, String)> { attrs .iter() .filter_map(|attr| { - if let AttrKind::DocComment(com_kind, sym) = attr.kind + if let Some((sym, com_kind)) = attr.doc_str_and_comment_kind() && let AttrStyle::Outer = attr.style && let Some(com) = sym.as_str().strip_prefix('!') { diff --git a/clippy_lints/src/doc/too_long_first_doc_paragraph.rs b/clippy_lints/src/doc/too_long_first_doc_paragraph.rs index 0165d24c7df2..0f9ff5508532 100644 --- a/clippy_lints/src/doc/too_long_first_doc_paragraph.rs +++ b/clippy_lints/src/doc/too_long_first_doc_paragraph.rs @@ -1,6 +1,5 @@ -use rustc_ast::ast::Attribute; use rustc_errors::Applicability; -use rustc_hir::{Item, ItemKind}; +use rustc_hir::{Attribute, Item, ItemKind}; use rustc_lint::LateContext; use clippy_utils::diagnostics::span_lint_and_then; diff --git a/clippy_lints/src/functions/must_use.rs b/clippy_lints/src/functions/must_use.rs index 175d92d2d790..2b26285429af 100644 --- a/clippy_lints/src/functions/must_use.rs +++ b/clippy_lints/src/functions/must_use.rs @@ -1,9 +1,8 @@ use hir::FnSig; -use rustc_ast::ast::Attribute; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::def_id::DefIdSet; -use rustc_hir::{self as hir, QPath}; +use rustc_hir::{self as hir, Attribute, QPath}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LintContext}; use rustc_middle::lint::in_external_macro; diff --git a/clippy_lints/src/large_include_file.rs b/clippy_lints/src/large_include_file.rs index a0657a233c10..66d4c40ab5e4 100644 --- a/clippy_lints/src/large_include_file.rs +++ b/clippy_lints/src/large_include_file.rs @@ -2,8 +2,8 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::macros::root_macro_call_first_node; use clippy_utils::source::snippet_opt; -use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind, Attribute, LitKind}; -use rustc_hir::{Expr, ExprKind}; +use rustc_ast::{LitKind}; +use rustc_hir::{Expr, ExprKind, Attribute, AttrArgs, AttrKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; use rustc_span::{Span, sym}; @@ -93,10 +93,10 @@ impl LateLintPass<'_> for LargeIncludeFile { if !attr.span.from_expansion() // Currently, rustc limits the usage of macro at the top-level of attributes, // so we don't need to recurse into each level. - && let AttrKind::Normal(ref normal) = attr.kind + && let AttrKind::Normal(ref item) = attr.kind && let Some(doc) = attr.doc_str() && doc.as_str().len() as u64 > self.max_file_size - && let AttrArgs::Eq { expr: AttrArgsEq::Hir(ref meta), .. } = normal.item.args + && let AttrArgs::Eq { expr: meta, .. } = &item.args && !attr.span.contains(meta.span) // Since the `include_str` is already expanded at this point, we can only take the // whole attribute snippet and then modify for our suggestion. diff --git a/clippy_lints/src/macro_use.rs b/clippy_lints/src/macro_use.rs index 22aa681b6819..3c669d94d693 100644 --- a/clippy_lints/src/macro_use.rs +++ b/clippy_lints/src/macro_use.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::source::snippet; use hir::def::{DefKind, Res}; -use rustc_ast::ast; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir as hir; @@ -104,7 +103,7 @@ impl LateLintPass<'_> for MacroUseImports { self.push_unique_macro_pat_ty(cx, item.span); } } - fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) { + fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &hir::Attribute) { if attr.span.from_expansion() { self.push_unique_macro(cx, attr.span); } diff --git a/clippy_lints/src/matches/match_like_matches.rs b/clippy_lints/src/matches/match_like_matches.rs index 47472ab831f2..223d0dc76569 100644 --- a/clippy_lints/src/matches/match_like_matches.rs +++ b/clippy_lints/src/matches/match_like_matches.rs @@ -2,9 +2,9 @@ use super::REDUNDANT_PATTERN_MATCHING; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::{is_lint_allowed, is_wild, span_contains_comment}; -use rustc_ast::{Attribute, LitKind}; +use rustc_ast::LitKind; use rustc_errors::Applicability; -use rustc_hir::{Arm, BorrowKind, Expr, ExprKind, Pat, PatKind, QPath}; +use rustc_hir::{Arm, Attribute, BorrowKind, Expr, ExprKind, Pat, PatKind, QPath}; use rustc_lint::{LateContext, LintContext}; use rustc_middle::ty; use rustc_span::source_map::Spanned; diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 1300c7d10628..b6f49dcc163f 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -10,8 +10,9 @@ use clippy_utils::attrs::is_doc_hidden; use clippy_utils::diagnostics::span_lint; use clippy_utils::is_from_proc_macro; use clippy_utils::source::SpanRangeExt; -use rustc_ast::ast::{self, MetaItem, MetaItemKind}; +use rustc_ast::ast::MetaItemInner; use rustc_hir as hir; +use rustc_hir::Attribute; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -67,9 +68,8 @@ impl MissingDoc { *self.doc_hidden_stack.last().expect("empty doc_hidden_stack") } - fn has_include(meta: Option) -> bool { - if let Some(meta) = meta - && let MetaItemKind::List(list) = meta.kind + fn has_include(meta: Option<&[MetaItemInner]>) -> bool { + if let Some(list) = meta && let Some(meta) = list.first() && let Some(name) = meta.ident() { @@ -83,7 +83,7 @@ impl MissingDoc { &self, cx: &LateContext<'_>, def_id: LocalDefId, - attrs: &[ast::Attribute], + attrs: &[Attribute], sp: Span, article: &'static str, desc: &'static str, @@ -129,7 +129,7 @@ impl MissingDoc { let has_doc = attrs .iter() - .any(|a| a.doc_str().is_some() || Self::has_include(a.meta())) + .any(|a| a.doc_str().is_some() || Self::has_include(a.meta_item_list().as_deref())) || matches!(self.search_span(sp), Some(span) if span_to_snippet_contains_docs(cx, span)); if !has_doc { @@ -172,12 +172,12 @@ impl MissingDoc { impl_lint_pass!(MissingDoc => [MISSING_DOCS_IN_PRIVATE_ITEMS]); impl<'tcx> LateLintPass<'tcx> for MissingDoc { - fn check_attributes(&mut self, _: &LateContext<'tcx>, attrs: &'tcx [ast::Attribute]) { + fn check_attributes(&mut self, _: &LateContext<'tcx>, attrs: &'tcx [Attribute]) { let doc_hidden = self.doc_hidden() || is_doc_hidden(attrs); self.doc_hidden_stack.push(doc_hidden); } - fn check_attributes_post(&mut self, _: &LateContext<'tcx>, _: &'tcx [ast::Attribute]) { + fn check_attributes_post(&mut self, _: &LateContext<'tcx>, _: &'tcx [Attribute]) { self.doc_hidden_stack.pop().expect("empty doc_hidden_stack"); } diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index e587d695c846..11ff779d5316 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint; -use rustc_ast::ast; use rustc_hir as hir; +use rustc_hir::Attribute; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty::AssocItemContainer; use rustc_session::declare_lint_pass; @@ -63,7 +63,7 @@ declare_clippy_lint! { "detects missing `#[inline]` attribute for public callables (functions, trait methods, methods...)" } -fn check_missing_inline_attrs(cx: &LateContext<'_>, attrs: &[ast::Attribute], sp: Span, desc: &'static str) { +fn check_missing_inline_attrs(cx: &LateContext<'_>, attrs: &[Attribute], sp: Span, desc: &'static str) { let has_inline = attrs.iter().any(|a| a.has_name(sym::inline)); if !has_inline { span_lint( diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 6f3f371a68d6..30846fb46ac1 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -5,12 +5,11 @@ use clippy_utils::source::{SpanRangeExt, snippet}; use clippy_utils::ty::{ implements_trait, implements_trait_with_env_from_iter, is_copy, is_type_diagnostic_item, is_type_lang_item, }; -use rustc_ast::ast::Attribute; use rustc_errors::{Applicability, Diag}; use rustc_hir::intravisit::FnKind; use rustc_hir::{ - BindingMode, Body, FnDecl, GenericArg, HirId, HirIdSet, Impl, ItemKind, LangItem, Mutability, Node, PatKind, QPath, - TyKind, + Attribute, BindingMode, Body, FnDecl, GenericArg, HirId, HirIdSet, Impl, ItemKind, LangItem, Mutability, Node, + PatKind, QPath, TyKind, }; use rustc_hir_typeck::expr_use_visitor as euv; use rustc_lint::{LateContext, LateLintPass}; diff --git a/clippy_utils/src/ast_utils.rs b/clippy_utils/src/ast_utils.rs index 6df0748c1177..623d9c760861 100644 --- a/clippy_utils/src/ast_utils.rs +++ b/clippy_utils/src/ast_utils.rs @@ -872,8 +872,7 @@ pub fn eq_attr_args(l: &AttrArgs, r: &AttrArgs) -> bool { match (l, r) { (Empty, Empty) => true, (Delimited(la), Delimited(ra)) => eq_delim_args(la, ra), - (Eq { expr: AttrArgsEq::Ast(le), .. }, Eq{ expr: AttrArgsEq::Ast(re), .. }) => eq_expr(le, re), - (Eq { expr: AttrArgsEq::Hir(ll), .. }, Eq{ expr: AttrArgsEq::Hir(rl), .. }) => ll.kind == rl.kind, + (Eq { eq_span: _, expr: le }, Eq { eq_span: _, expr: re }) => eq_expr(le, re), _ => false, } } diff --git a/clippy_utils/src/attrs.rs b/clippy_utils/src/attrs.rs index b2a6657baad3..922afffb8767 100644 --- a/clippy_utils/src/attrs.rs +++ b/clippy_utils/src/attrs.rs @@ -1,4 +1,5 @@ -use rustc_ast::{ast, attr}; +use rustc_ast::attr; +use rustc_ast::attr::AttributeExt; use rustc_errors::Applicability; use rustc_lexer::TokenKind; use rustc_lint::LateContext; @@ -51,33 +52,31 @@ impl LimitStack { pub fn limit(&self) -> u64 { *self.stack.last().expect("there should always be a value in the stack") } - pub fn push_attrs(&mut self, sess: &Session, attrs: &[ast::Attribute], name: &'static str) { + pub fn push_attrs(&mut self, sess: &Session, attrs: &[impl AttributeExt], name: &'static str) { let stack = &mut self.stack; parse_attrs(sess, attrs, name, |val| stack.push(val)); } - pub fn pop_attrs(&mut self, sess: &Session, attrs: &[ast::Attribute], name: &'static str) { + pub fn pop_attrs(&mut self, sess: &Session, attrs: &[impl AttributeExt], name: &'static str) { let stack = &mut self.stack; parse_attrs(sess, attrs, name, |val| assert_eq!(stack.pop(), Some(val))); } } -pub fn get_attr<'a>( +pub fn get_attr<'a, A: AttributeExt + 'a>( sess: &'a Session, - attrs: &'a [ast::Attribute], + attrs: &'a [A], name: &'static str, -) -> impl Iterator { +) -> impl Iterator { attrs.iter().filter(move |attr| { - let attr = if let ast::AttrKind::Normal(ref normal) = attr.kind { - &normal.item - } else { + let Some(attr_segments) = attr.ident_path() else { return false; }; - let attr_segments = &attr.path.segments; - if attr_segments.len() == 2 && attr_segments[0].ident.name == sym::clippy { + + if attr_segments.len() == 2 && attr_segments[0].name == sym::clippy { BUILTIN_ATTRIBUTES .iter() .find_map(|&(builtin_name, ref deprecation_status)| { - if attr_segments[1].ident.name.as_str() == builtin_name { + if attr_segments[1].name.as_str() == builtin_name { Some(deprecation_status) } else { None @@ -85,14 +84,13 @@ pub fn get_attr<'a>( }) .map_or_else( || { - sess.dcx() - .span_err(attr_segments[1].ident.span, "usage of unknown attribute"); + sess.dcx().span_err(attr_segments[1].span, "usage of unknown attribute"); false }, |deprecation_status| { let mut diag = sess .dcx() - .struct_span_err(attr_segments[1].ident.span, "usage of deprecated attribute"); + .struct_span_err(attr_segments[1].span, "usage of deprecated attribute"); match *deprecation_status { DeprecationStatus::Deprecated => { diag.emit(); @@ -100,7 +98,7 @@ pub fn get_attr<'a>( }, DeprecationStatus::Replaced(new_name) => { diag.span_suggestion( - attr_segments[1].ident.span, + attr_segments[1].span, "consider using", new_name, Applicability::MachineApplicable, @@ -110,7 +108,7 @@ pub fn get_attr<'a>( }, DeprecationStatus::None => { diag.cancel(); - attr_segments[1].ident.name.as_str() == name + attr_segments[1].as_str() == name }, } }, @@ -121,31 +119,31 @@ pub fn get_attr<'a>( }) } -fn parse_attrs(sess: &Session, attrs: &[ast::Attribute], name: &'static str, mut f: F) { +fn parse_attrs(sess: &Session, attrs: &[impl AttributeExt], name: &'static str, mut f: F) { for attr in get_attr(sess, attrs, name) { if let Some(ref value) = attr.value_str() { if let Ok(value) = FromStr::from_str(value.as_str()) { f(value); } else { - sess.dcx().span_err(attr.span, "not a number"); + sess.dcx().span_err(attr.span(), "not a number"); } } else { - sess.dcx().span_err(attr.span, "bad clippy attribute"); + sess.dcx().span_err(attr.span(), "bad clippy attribute"); } } } -pub fn get_unique_attr<'a>( +pub fn get_unique_attr<'a, A: AttributeExt>( sess: &'a Session, - attrs: &'a [ast::Attribute], + attrs: &'a [A], name: &'static str, -) -> Option<&'a ast::Attribute> { - let mut unique_attr: Option<&ast::Attribute> = None; +) -> Option<&'a A> { + let mut unique_attr: Option<&A> = None; for attr in get_attr(sess, attrs, name) { if let Some(duplicate) = unique_attr { sess.dcx() - .struct_span_err(attr.span, format!("`{name}` is defined multiple times")) - .with_span_note(duplicate.span, "first definition found here") + .struct_span_err(attr.span(), format!("`{name}` is defined multiple times")) + .with_span_note(duplicate.span(), "first definition found here") .emit(); } else { unique_attr = Some(attr); @@ -156,16 +154,16 @@ pub fn get_unique_attr<'a>( /// Returns true if the attributes contain any of `proc_macro`, /// `proc_macro_derive` or `proc_macro_attribute`, false otherwise -pub fn is_proc_macro(attrs: &[ast::Attribute]) -> bool { - attrs.iter().any(rustc_ast::Attribute::is_proc_macro_attr) +pub fn is_proc_macro(attrs: &[impl AttributeExt]) -> bool { + attrs.iter().any(AttributeExt::is_proc_macro_attr) } /// Returns true if the attributes contain `#[doc(hidden)]` -pub fn is_doc_hidden(attrs: &[ast::Attribute]) -> bool { +pub fn is_doc_hidden(attrs: &[impl AttributeExt]) -> bool { attrs .iter() .filter(|attr| attr.has_name(sym::doc)) - .filter_map(ast::Attribute::meta_item_list) + .filter_map(AttributeExt::meta_item_list) .any(|l| attr::list_contains_name(&l, sym::hidden)) } diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 8d48cdd3cbb4..96139a08c3d1 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -135,13 +135,24 @@ use rustc_middle::hir::nested_filter; #[macro_export] macro_rules! extract_msrv_attr { - ($context:ident) => { - fn check_attributes(&mut self, cx: &rustc_lint::$context<'_>, attrs: &[rustc_ast::ast::Attribute]) { + (LateContext) => { + fn check_attributes(&mut self, cx: &rustc_lint::LateContext<'_>, attrs: &[rustc_hir::Attribute]) { let sess = rustc_lint::LintContext::sess(cx); self.msrv.check_attributes(sess, attrs); } - fn check_attributes_post(&mut self, cx: &rustc_lint::$context<'_>, attrs: &[rustc_ast::ast::Attribute]) { + fn check_attributes_post(&mut self, cx: &rustc_lint::LateContext<'_>, attrs: &[rustc_hir::Attribute]) { + let sess = rustc_lint::LintContext::sess(cx); + self.msrv.check_attributes_post(sess, attrs); + } + }; + (EarlyContext) => { + fn check_attributes(&mut self, cx: &rustc_lint::EarlyContext<'_>, attrs: &[rustc_ast::Attribute]) { + let sess = rustc_lint::LintContext::sess(cx); + self.msrv.check_attributes(sess, attrs); + } + + fn check_attributes_post(&mut self, cx: &rustc_lint::EarlyContext<'_>, attrs: &[rustc_ast::Attribute]) { let sess = rustc_lint::LintContext::sess(cx); self.msrv.check_attributes_post(sess, attrs); } @@ -1912,7 +1923,7 @@ pub fn clip(tcx: TyCtxt<'_>, u: u128, ity: UintTy) -> u128 { (u << amt) >> amt } -pub fn has_attr(attrs: &[ast::Attribute], symbol: Symbol) -> bool { +pub fn has_attr(attrs: &[hir::Attribute], symbol: Symbol) -> bool { attrs.iter().any(|attr| attr.has_name(symbol)) } @@ -2263,21 +2274,13 @@ pub fn std_or_core(cx: &LateContext<'_>) -> Option<&'static str> { pub fn is_no_std_crate(cx: &LateContext<'_>) -> bool { cx.tcx.hir().attrs(hir::CRATE_HIR_ID).iter().any(|attr| { - if let ast::AttrKind::Normal(ref normal) = attr.kind { - normal.item.path == sym::no_std - } else { - false - } + attr.name_or_empty() == sym::no_std }) } pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool { cx.tcx.hir().attrs(hir::CRATE_HIR_ID).iter().any(|attr| { - if let ast::AttrKind::Normal(ref normal) = attr.kind { - normal.item.path == sym::no_core - } else { - false - } + attr.name_or_empty() == sym::no_core }) } diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index 1eb7d54e133d..5b1c3465d05e 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -1,4 +1,4 @@ -use rustc_ast::Attribute; +use rustc_attr::AttributeExt; use rustc_attr::parse_version; use rustc_session::{RustcVersion, Session}; use rustc_span::{Symbol, sym}; @@ -124,15 +124,15 @@ impl Msrv { self.current().is_none_or(|msrv| msrv >= required) } - fn parse_attr(sess: &Session, attrs: &[Attribute]) -> Option { + fn parse_attr(sess: &Session, attrs: &[impl AttributeExt]) -> Option { let sym_msrv = Symbol::intern("msrv"); let mut msrv_attrs = attrs.iter().filter(|attr| attr.path_matches(&[sym::clippy, sym_msrv])); if let Some(msrv_attr) = msrv_attrs.next() { if let Some(duplicate) = msrv_attrs.last() { sess.dcx() - .struct_span_err(duplicate.span, "`clippy::msrv` is defined multiple times") - .with_span_note(msrv_attr.span, "first definition found here") + .struct_span_err(duplicate.span(), "`clippy::msrv` is defined multiple times") + .with_span_note(msrv_attr.span(), "first definition found here") .emit(); } @@ -142,22 +142,22 @@ impl Msrv { } sess.dcx() - .span_err(msrv_attr.span, format!("`{msrv}` is not a valid Rust version")); + .span_err(msrv_attr.span(), format!("`{msrv}` is not a valid Rust version")); } else { - sess.dcx().span_err(msrv_attr.span, "bad clippy attribute"); + sess.dcx().span_err(msrv_attr.span(), "bad clippy attribute"); } } None } - pub fn check_attributes(&mut self, sess: &Session, attrs: &[Attribute]) { + pub fn check_attributes(&mut self, sess: &Session, attrs: &[impl AttributeExt]) { if let Some(version) = Self::parse_attr(sess, attrs) { self.stack.push(version); } } - pub fn check_attributes_post(&mut self, sess: &Session, attrs: &[Attribute]) { + pub fn check_attributes_post(&mut self, sess: &Session, attrs: &[impl AttributeExt]) { if Self::parse_attr(sess, attrs).is_some() { self.stack.pop(); } From 6f65a813a2db23e0a7e42ab1b319ad59d27a26e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20D=C3=B6nszelmann?= Date: Sat, 7 Dec 2024 15:27:17 +0100 Subject: [PATCH 05/12] split attributes --- clippy_utils/src/msrvs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index 5b1c3465d05e..55986acea3d7 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -1,4 +1,4 @@ -use rustc_attr::AttributeExt; +use rustc_ast::attr::AttributeExt; use rustc_attr::parse_version; use rustc_session::{RustcVersion, Session}; use rustc_span::{Symbol, sym}; From 4d05825f3eada471dd1a83bbe9110fc3e8bc1903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20D=C3=B6nszelmann?= Date: Fri, 13 Dec 2024 14:47:11 +0100 Subject: [PATCH 06/12] rename rustc_attr to rustc_attr_parsing and create rustc_attr_data_structures --- clippy_lints/src/approx_const.rs | 3 ++- clippy_lints/src/booleans.rs | 3 ++- clippy_lints/src/incompatible_msrv.rs | 4 ++-- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/std_instead_of_core.rs | 2 +- .../src/utils/internal_lints/lint_without_lint_pass.rs | 2 +- clippy_utils/src/lib.rs | 2 +- clippy_utils/src/msrvs.rs | 4 ++-- clippy_utils/src/qualify_min_const_fn.rs | 6 +++--- 9 files changed, 15 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index ebd35fd2b27f..95c85f250e98 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -2,9 +2,10 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::msrvs::{self, Msrv}; use rustc_ast::ast::{FloatTy, LitFloatType, LitKind}; +use rustc_attr_parsing::RustcVersion; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{RustcVersion, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::symbol; use std::f64::consts as f64; diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 6eef0d42a550..f68a7a89b399 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -9,7 +9,8 @@ use rustc_errors::Applicability; use rustc_hir::intravisit::{FnKind, Visitor, walk_expr}; use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, UnOp}; use rustc_lint::{LateContext, LateLintPass, Level}; -use rustc_session::{RustcVersion, impl_lint_pass}; +use rustc_attr_parsing::RustcVersion; +use rustc_session::impl_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::{Span, sym}; diff --git a/clippy_lints/src/incompatible_msrv.rs b/clippy_lints/src/incompatible_msrv.rs index f3467adacc55..6cee7cfaca23 100644 --- a/clippy_lints/src/incompatible_msrv.rs +++ b/clippy_lints/src/incompatible_msrv.rs @@ -2,12 +2,12 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint; use clippy_utils::is_in_test; use clippy_utils::msrvs::Msrv; -use rustc_attr::{StabilityLevel, StableSince}; +use rustc_attr_parsing::{StabilityLevel, StableSince, RustcVersion}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::{Expr, ExprKind, HirId}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::TyCtxt; -use rustc_session::{RustcVersion, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::def_id::DefId; use rustc_span::{ExpnKind, Span}; diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index e80cca6e7db4..3e8315588cc7 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -35,7 +35,7 @@ extern crate rustc_abi; extern crate rustc_arena; extern crate rustc_ast; extern crate rustc_ast_pretty; -extern crate rustc_attr; +extern crate rustc_attr_parsing; extern crate rustc_data_structures; extern crate rustc_driver; extern crate rustc_errors; diff --git a/clippy_lints/src/std_instead_of_core.rs b/clippy_lints/src/std_instead_of_core.rs index 2941b9c39607..82ff13a5aff1 100644 --- a/clippy_lints/src/std_instead_of_core.rs +++ b/clippy_lints/src/std_instead_of_core.rs @@ -2,7 +2,7 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_from_proc_macro; use clippy_utils::msrvs::Msrv; -use rustc_attr::{StabilityLevel, StableSince}; +use rustc_attr_parsing::{StabilityLevel, StableSince}; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::def_id::DefId; diff --git a/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs index af38e066559c..496343d82c8d 100644 --- a/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs +++ b/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs @@ -222,7 +222,7 @@ fn check_invalid_clippy_version_attribute(cx: &LateContext<'_>, item: &'_ Item<' return; } - if rustc_attr::parse_version(value).is_none() { + if rustc_attr_parsing::parse_version(value).is_none() { span_lint_and_help( cx, INVALID_CLIPPY_VERSION_ATTRIBUTE, diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 96139a08c3d1..02bbddb413a9 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -31,7 +31,7 @@ // (Currently there is no way to opt into sysroot crates without `extern crate`.) extern crate rustc_ast; extern crate rustc_ast_pretty; -extern crate rustc_attr; +extern crate rustc_attr_parsing; extern crate rustc_const_eval; extern crate rustc_data_structures; // The `rustc_driver` crate seems to be required in order to use the `rust_ast` crate. diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index 55986acea3d7..1e6368fab368 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -1,6 +1,6 @@ use rustc_ast::attr::AttributeExt; -use rustc_attr::parse_version; -use rustc_session::{RustcVersion, Session}; +use rustc_attr_parsing::{parse_version, RustcVersion}; +use rustc_session::Session; use rustc_span::{Symbol, sym}; use serde::Deserialize; use smallvec::{SmallVec, smallvec}; diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index df3f10d6179a..104ae154e369 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -5,7 +5,7 @@ use crate::msrvs::{self, Msrv}; use hir::LangItem; -use rustc_attr::StableSince; +use rustc_attr_parsing::{RustcVersion, StableSince}; use rustc_const_eval::check_consts::ConstCx; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -381,14 +381,14 @@ fn check_terminator<'tcx>( fn is_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: &Msrv) -> bool { tcx.is_const_fn(def_id) && tcx.lookup_const_stability(def_id).is_none_or(|const_stab| { - if let rustc_attr::StabilityLevel::Stable { since, .. } = const_stab.level { + if let rustc_attr_parsing::StabilityLevel::Stable { since, .. } = const_stab.level { // Checking MSRV is manually necessary because `rustc` has no such concept. This entire // function could be removed if `rustc` provided a MSRV-aware version of `is_stable_const_fn`. // as a part of an unimplemented MSRV check https://github.com/rust-lang/rust/issues/65262. let const_stab_rust_version = match since { StableSince::Version(version) => version, - StableSince::Current => rustc_session::RustcVersion::CURRENT, + StableSince::Current => RustcVersion::CURRENT, StableSince::Err => return false, }; From 5c200c225514ef98abaef295af027333b2f6765e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 11 Dec 2024 12:29:04 +1100 Subject: [PATCH 07/12] Simplify `RefTokenTreeCursor::look_ahead`. It's only ever used with a lookahead of 0, so this commit removes the lookahead and renames it `peek`. --- clippy_lints/src/crate_in_macro_def.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/crate_in_macro_def.rs b/clippy_lints/src/crate_in_macro_def.rs index c8f814137289..76b88b746cb4 100644 --- a/clippy_lints/src/crate_in_macro_def.rs +++ b/clippy_lints/src/crate_in_macro_def.rs @@ -86,7 +86,7 @@ fn contains_unhygienic_crate_reference(tts: &TokenStream) -> Option { while let Some(curr) = cursor.next() { if !prev_is_dollar && let Some(span) = is_crate_keyword(curr) - && let Some(next) = cursor.look_ahead(0) + && let Some(next) = cursor.peek() && is_token(next, &TokenKind::PathSep) { return Some(span); From 1cb4dcafd1a65370af636f43f8f3a718e4bc66d1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 11 Dec 2024 14:38:09 +1100 Subject: [PATCH 08/12] Rename `RefTokenTreeCursor`. Because `TokenStreamIter` is a much better name for a `TokenStream` iterator. Also rename the `TokenStream::trees` method as `TokenStream::iter`, and some local variables. --- clippy_lints/src/attrs/should_panic_without_expect.rs | 2 +- clippy_lints/src/crate_in_macro_def.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/attrs/should_panic_without_expect.rs b/clippy_lints/src/attrs/should_panic_without_expect.rs index b4ed8a68a325..fd27e30a67f3 100644 --- a/clippy_lints/src/attrs/should_panic_without_expect.rs +++ b/clippy_lints/src/attrs/should_panic_without_expect.rs @@ -15,7 +15,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) { } if let AttrArgs::Delimited(args) = &normal_attr.item.args - && let mut tt_iter = args.tokens.trees() + && let mut tt_iter = args.tokens.iter() && let Some(TokenTree::Token( Token { kind: TokenKind::Ident(sym::expected, _), diff --git a/clippy_lints/src/crate_in_macro_def.rs b/clippy_lints/src/crate_in_macro_def.rs index 76b88b746cb4..7d86bd3e540a 100644 --- a/clippy_lints/src/crate_in_macro_def.rs +++ b/clippy_lints/src/crate_in_macro_def.rs @@ -82,11 +82,11 @@ fn is_macro_export(attr: &Attribute) -> bool { fn contains_unhygienic_crate_reference(tts: &TokenStream) -> Option { let mut prev_is_dollar = false; - let mut cursor = tts.trees(); - while let Some(curr) = cursor.next() { + let mut iter = tts.iter(); + while let Some(curr) = iter.next() { if !prev_is_dollar && let Some(span) = is_crate_keyword(curr) - && let Some(next) = cursor.peek() + && let Some(next) = iter.peek() && is_token(next, &TokenKind::PathSep) { return Some(span); From f415510fba005a75d206f54807109471f4766d0b Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 6 Dec 2024 14:46:28 +0100 Subject: [PATCH 09/12] introduce `LateParamRegionKind` --- clippy_lints/src/ptr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 44a8789462b0..b674b01406d3 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -475,7 +475,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>( .def_id, ), ty::ReBound(_, r) => r.kind.get_id(), - ty::ReLateParam(r) => r.bound_region.get_id(), + ty::ReLateParam(r) => r.kind.get_id(), ty::ReStatic | ty::ReVar(_) | ty::RePlaceholder(_) From c772140a1fc8cbb6a87db332ce021db7f42857bf Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 14 Dec 2024 23:20:48 -0800 Subject: [PATCH 10/12] Update clippy --- clippy_utils/src/qualify_min_const_fn.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index 104ae154e369..428b40c5771c 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -109,7 +109,7 @@ fn check_rvalue<'tcx>( ) -> McfResult { match rvalue { Rvalue::ThreadLocalRef(_) => Err((span, "cannot access thread local storage in const fn".into())), - Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) => { + Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) => { check_place(tcx, *place, span, body, msrv) }, Rvalue::CopyForDeref(place) => check_place(tcx, *place, span, body, msrv), From 4d735d831e1144319b19d06d930e6c0d31f3cf30 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 21 Dec 2024 17:05:40 +0000 Subject: [PATCH 11/12] Begin to implement type system layer of unsafe binders --- clippy_lints/src/dereference.rs | 3 ++- clippy_utils/src/visitors.rs | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index e3959903fddc..821312a9e401 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -877,7 +877,8 @@ impl TyCoercionStability { | ty::CoroutineClosure(..) | ty::Never | ty::Tuple(_) - | ty::Alias(ty::Projection, _) => Self::Deref, + | ty::Alias(ty::Projection, _) + | ty::UnsafeBinder(_) => Self::Deref, }; } } diff --git a/clippy_utils/src/visitors.rs b/clippy_utils/src/visitors.rs index 71499b1293a5..afceeec22726 100644 --- a/clippy_utils/src/visitors.rs +++ b/clippy_utils/src/visitors.rs @@ -677,6 +677,9 @@ pub fn for_each_unconsumed_temporary<'tcx, B>( ExprKind::Type(e, _) => { helper(typeck, consume, e, f)?; }, + ExprKind::UnsafeBinderCast(_, e, _) => { + helper(typeck, consume, e, f)?; + }, // Either drops temporaries, jumps out of the current expression, or has no sub expression. ExprKind::DropTemps(_) @@ -694,7 +697,6 @@ pub fn for_each_unconsumed_temporary<'tcx, B>( | ExprKind::Continue(_) | ExprKind::InlineAsm(_) | ExprKind::OffsetOf(..) - | ExprKind::UnsafeBinderCast(..) | ExprKind::Err(_) => (), } ControlFlow::Continue(()) From 416f7e84c0cb385378a4d5187655e05e7b673ee3 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 26 Dec 2024 14:47:30 +0100 Subject: [PATCH 12/12] Bump nightly version -> 2024-12-26 --- clippy_utils/README.md | 2 +- rust-toolchain | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_utils/README.md b/clippy_utils/README.md index 395c4a23e768..73fefbcd5705 100644 --- a/clippy_utils/README.md +++ b/clippy_utils/README.md @@ -8,7 +8,7 @@ This crate is only guaranteed to build with this `nightly` toolchain: ``` -nightly-2024-12-15 +nightly-2024-12-26 ``` diff --git a/rust-toolchain b/rust-toolchain index 874893691c07..1000d90f52a5 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,6 +1,6 @@ [toolchain] # begin autogenerated nightly -channel = "nightly-2024-12-15" +channel = "nightly-2024-12-26" # end autogenerated nightly components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] profile = "minimal"