diff --git a/clippy_lints/src/attrs/mod.rs b/clippy_lints/src/attrs/mod.rs index bc885d4d502c..78701b336822 100644 --- a/clippy_lints/src/attrs/mod.rs +++ b/clippy_lints/src/attrs/mod.rs @@ -14,11 +14,12 @@ mod useless_attribute; mod utils; use clippy_config::Conf; +use clippy_utils::check_clippy_attr; use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::msrvs::{self, Msrv, MsrvStack}; use rustc_ast::{self as ast, AttrArgs, AttrItemKind, AttrKind, Attribute, MetaItemInner, MetaItemKind}; use rustc_hir::{ImplItem, ImplItemKind, Item, ItemKind, TraitFn, TraitItem, TraitItemKind}; -use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; +use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; use rustc_session::impl_lint_pass; use rustc_span::sym; use utils::is_lint_level; @@ -582,6 +583,7 @@ impl EarlyLintPass for PostExpansionEarlyAttributes { } fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) { + check_clippy_attr(cx.sess(), attr); if let Some(items) = &attr.meta_item_list() && let Some(name) = attr.name() { diff --git a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs index 34cfb6514be0..ae7702105462 100644 --- a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs +++ b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs @@ -11,7 +11,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{Applicability, Diag}; use rustc_hir::intravisit::{Visitor, walk_expr}; use rustc_hir::{Arm, Expr, ExprKind, MatchSource}; -use rustc_lint::{LateContext, LintContext}; +use rustc_lint::LateContext; use rustc_middle::ty::{GenericArgKind, RegionKind, Ty, TypeVisitableExt}; use rustc_span::Span; @@ -184,7 +184,6 @@ impl<'a, 'tcx> SigDropChecker<'a, 'tcx> { fn has_sig_drop_attr_impl(&mut self, ty: Ty<'tcx>) -> bool { if let Some(adt) = ty.ty_adt_def() && get_builtin_attr( - self.cx.sess(), #[allow(deprecated)] self.cx.tcx.get_all_attrs(adt.did()), sym::has_significant_drop, diff --git a/clippy_lints/src/significant_drop_tightening.rs b/clippy_lints/src/significant_drop_tightening.rs index c94e739f006a..86b3387ae643 100644 --- a/clippy_lints/src/significant_drop_tightening.rs +++ b/clippy_lints/src/significant_drop_tightening.rs @@ -8,7 +8,7 @@ use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{Visitor, walk_expr}; use rustc_hir::{self as hir, HirId}; -use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{GenericArgKind, Ty, Unnormalized}; use rustc_session::impl_lint_pass; use rustc_span::symbol::Ident; @@ -170,7 +170,6 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> { fn has_sig_drop_attr_uncached(&mut self, ty: Ty<'tcx>, depth: usize) -> bool { if let Some(adt) = ty.ty_adt_def() { let mut iter = get_builtin_attr( - self.cx.sess(), #[allow(deprecated)] self.cx.tcx.get_all_attrs(adt.did()), sym::has_significant_drop, diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 7ba28f95a719..c60d84785a22 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -9,7 +9,7 @@ use rustc_hir::{ self as hir, BindingMode, CaptureBy, Closure, ClosureKind, ConstArg, ConstArgKind, CoroutineKind, ExprKind, FnRetTy, HirId, Lit, PatExprKind, PatKind, QPath, StmtKind, StructTailExpr, }; -use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{FloatTy, IntTy, UintTy}; use rustc_session::declare_lint_pass; use rustc_span::symbol::{Ident, Symbol}; @@ -863,5 +863,5 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { fn has_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool { let attrs = cx.tcx.hir_attrs(hir_id); - get_builtin_attr(cx.sess(), attrs, sym::author).count() > 0 + get_builtin_attr(attrs, sym::author).count() > 0 } diff --git a/clippy_lints/src/utils/dump_hir.rs b/clippy_lints/src/utils/dump_hir.rs index b490866f0a11..4d9691314f1b 100644 --- a/clippy_lints/src/utils/dump_hir.rs +++ b/clippy_lints/src/utils/dump_hir.rs @@ -1,7 +1,7 @@ use clippy_utils::{get_builtin_attr, sym}; use hir::TraitItem; use rustc_hir as hir; -use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; declare_lint_pass!( @@ -60,5 +60,5 @@ impl<'tcx> LateLintPass<'tcx> for DumpHir { fn has_attr(cx: &LateContext<'_>, hir_id: hir::HirId) -> bool { let attrs = cx.tcx.hir_attrs(hir_id); - get_builtin_attr(cx.sess(), attrs, sym::dump).count() > 0 + get_builtin_attr(attrs, sym::dump).count() > 0 } diff --git a/clippy_utils/src/attrs.rs b/clippy_utils/src/attrs.rs index 6e7434771369..ff9454680d91 100644 --- a/clippy_utils/src/attrs.rs +++ b/clippy_utils/src/attrs.rs @@ -12,51 +12,51 @@ use rustc_session::Session; use rustc_span::{Span, Symbol}; use std::str::FromStr; +/// Validates a single clippy attribute and emits errors for unknown or deprecated ones. +pub fn check_clippy_attr(sess: &Session, attr: &A) { + if let [clippy, segment2] = &*attr.path() + && *clippy == sym::clippy + { + let path_span = attr + .path_span() + .expect("Clippy attributes are unparsed and have a span"); + + match *segment2 { + sym::cyclomatic_complexity => { + sess.dcx() + .struct_span_err(path_span, "usage of deprecated attribute") + .with_span_suggestion( + path_span, + "consider using", + "clippy::cognitive_complexity", + Applicability::MachineApplicable, + ) + .emit(); + }, + sym::author + | sym::version + | sym::cognitive_complexity + | sym::dump + | sym::msrv + | sym::has_significant_drop + | sym::format_args => {}, + _ => { + sess.dcx().span_err(path_span, "usage of unknown attribute"); + }, + } + } +} + /// Given `attrs`, extract all the instances of a built-in Clippy attribute called `name` -pub fn get_builtin_attr<'a, A: AttributeExt + 'a>( - sess: &'a Session, - attrs: &'a [A], - name: Symbol, -) -> impl Iterator { +pub fn get_builtin_attr<'a, A: AttributeExt + 'a>(attrs: &'a [A], name: Symbol) -> impl Iterator { attrs.iter().filter(move |attr| { if let [clippy, segment2] = &*attr.path() && *clippy == sym::clippy { - let path_span = attr - .path_span() - .expect("Clippy attributes are unparsed and have a span"); - let new_name = match *segment2 { - sym::cyclomatic_complexity => Some("cognitive_complexity"), - sym::author - | sym::version - | sym::cognitive_complexity - | sym::dump - | sym::msrv - // The following attributes are for the 3rd party crate authors. - // See book/src/attribs.md - | sym::has_significant_drop - | sym::format_args => None, - _ => { - sess.dcx().span_err(path_span, "usage of unknown attribute"); - return false; - }, - }; - - match new_name { - Some(new_name) => { - sess.dcx() - .struct_span_err(path_span, "usage of deprecated attribute") - .with_span_suggestion( - path_span, - "consider using", - format!("clippy::{new_name}"), - Applicability::MachineApplicable, - ) - .emit(); - false - }, - None => *segment2 == name, + if *segment2 == sym::cyclomatic_complexity { + return false; } + *segment2 == name } else { false } @@ -67,7 +67,7 @@ pub fn get_builtin_attr<'a, A: AttributeExt + 'a>( /// returns that attribute, and `None` otherwise pub fn get_unique_builtin_attr<'a, A: AttributeExt>(sess: &'a Session, attrs: &'a [A], name: Symbol) -> Option<&'a A> { let mut unique_attr: Option<&A> = None; - for attr in get_builtin_attr(sess, attrs, name) { + for attr in get_builtin_attr(attrs, name) { if let Some(duplicate) = unique_attr { sess.dcx() .struct_span_err(attr.span(), format!("`{name}` is defined multiple times")) @@ -165,7 +165,7 @@ impl LimitStack { } fn parse_attrs(sess: &Session, attrs: &[impl AttributeExt], name: Symbol, mut f: F) { - for attr in get_builtin_attr(sess, attrs, name) { + for attr in get_builtin_attr(attrs, name) { let Some(value) = attr.value_str() else { sess.dcx().span_err(attr.span(), "bad clippy attribute"); continue; diff --git a/tests/ui/renamed_builtin_attr.fixed b/tests/ui/renamed_builtin_attr.fixed index 1ad7d8702bc0..3768ff1976ff 100644 --- a/tests/ui/renamed_builtin_attr.fixed +++ b/tests/ui/renamed_builtin_attr.fixed @@ -1,5 +1,3 @@ -//@compile-flags: -Zdeduplicate-diagnostics=yes - #[clippy::cognitive_complexity = "1"] //~^ ERROR: usage of deprecated attribute fn main() {} diff --git a/tests/ui/renamed_builtin_attr.rs b/tests/ui/renamed_builtin_attr.rs index 0fb43b7f4901..232e2d4920e8 100644 --- a/tests/ui/renamed_builtin_attr.rs +++ b/tests/ui/renamed_builtin_attr.rs @@ -1,5 +1,3 @@ -//@compile-flags: -Zdeduplicate-diagnostics=yes - #[clippy::cyclomatic_complexity = "1"] //~^ ERROR: usage of deprecated attribute fn main() {} diff --git a/tests/ui/renamed_builtin_attr.stderr b/tests/ui/renamed_builtin_attr.stderr index 0ebc43739d6b..5f3f9fdcc32a 100644 --- a/tests/ui/renamed_builtin_attr.stderr +++ b/tests/ui/renamed_builtin_attr.stderr @@ -1,5 +1,5 @@ error: usage of deprecated attribute - --> tests/ui/renamed_builtin_attr.rs:3:3 + --> tests/ui/renamed_builtin_attr.rs:1:3 | LL | #[clippy::cyclomatic_complexity = "1"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `clippy::cognitive_complexity` diff --git a/tests/ui/unknown_attribute.rs b/tests/ui/unknown_attribute.rs index 3241742b5d46..932f284d5b71 100644 --- a/tests/ui/unknown_attribute.rs +++ b/tests/ui/unknown_attribute.rs @@ -1,5 +1,3 @@ -//@compile-flags: -Zdeduplicate-diagnostics=yes - #[clippy::unknown] //~^ ERROR: usage of unknown attribute #[clippy::cognitive_complexity = "1"] diff --git a/tests/ui/unknown_attribute.stderr b/tests/ui/unknown_attribute.stderr index 1d4d50ffc02a..17c592b3aa07 100644 --- a/tests/ui/unknown_attribute.stderr +++ b/tests/ui/unknown_attribute.stderr @@ -1,5 +1,5 @@ error: usage of unknown attribute - --> tests/ui/unknown_attribute.rs:3:3 + --> tests/ui/unknown_attribute.rs:1:3 | LL | #[clippy::unknown] | ^^^^^^^^^^^^^^^