diff options
| author | Jana Dönszelmann <jana@donsz.nl> | 2025-02-09 22:49:57 +0100 |
|---|---|---|
| committer | Jana Dönszelmann <jana@donsz.nl> | 2025-02-24 14:31:19 +0100 |
| commit | f321f107e3af37996ac6cca74294d581f2fb20e7 (patch) | |
| tree | a82de0a09a3efe657bbfb3c7d8a63d291ce9b6e3 | |
| parent | 7e0f5b50168c63bd1879067c043559ef0f01671e (diff) | |
| download | rust-f321f107e3af37996ac6cca74294d581f2fb20e7.tar.gz rust-f321f107e3af37996ac6cca74294d581f2fb20e7.zip | |
Fix rustdoc and clippy
31 files changed, 134 insertions, 121 deletions
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 06c49366659..0ef4e6b3fe3 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1145,6 +1145,7 @@ impl AttributeExt for Attribute { } fn is_doc_comment(&self) -> bool { + // FIXME(jdonszelmann): make the 2nd check unnecessary here matches!(self, Attribute::Parsed(AttributeKind::DocComment { .. })) } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index dcc5fd12d81..ceffe5e5ce0 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2737,13 +2737,13 @@ fn add_without_unwanted_attributes<'hir>( import_parent: Option<DefId>, ) { for attr in new_attrs { - if matches!(attr.kind, hir::AttrKind::DocComment(..)) { + if attr.is_doc_comment() { attrs.push((Cow::Borrowed(attr), import_parent)); continue; } let mut attr = attr.clone(); - match attr.kind { - hir::AttrKind::Normal(ref mut normal) => { + match attr { + hir::Attribute::Unparsed(ref mut normal) => { if let [ident] = &*normal.path.segments { let ident = ident.name; if ident == sym::doc { @@ -2755,7 +2755,11 @@ fn add_without_unwanted_attributes<'hir>( } } } - _ => unreachable!(), + hir::Attribute::Parsed(..) => { + if is_inline { + attrs.push((Cow::Owned(attr), import_parent)); + } + } } } } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index fc7c4b42047..178b6a60b41 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -265,7 +265,7 @@ impl ExternalCrate { let attr_value = attr.value_str().expect("syntax should already be validated"); let Some(prim) = PrimitiveType::from_symbol(attr_value) else { span_bug!( - attr.span, + attr.span(), "primitive `{attr_value}` is not a member of `PrimitiveType`" ); }; diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs index 1ac3c040b59..3ac7abd0aa5 100644 --- a/src/librustdoc/doctest/rust.rs +++ b/src/librustdoc/doctest/rust.rs @@ -123,7 +123,7 @@ impl HirCollector<'_> { .iter() .find(|attr| attr.doc_str().is_some()) .map(|attr| { - attr.span.ctxt().outer_expn().expansion_cause().unwrap_or(attr.span) + attr.span().ctxt().outer_expn().expansion_cause().unwrap_or(attr.span()) }) .unwrap_or(DUMMY_SP) }; diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index a92f3ded774..8f6496e9626 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -30,7 +30,7 @@ pub type FxHashMap<K, V> = HashMap<K, V>; // re-export for use in src/librustdoc /// This integer is incremented with every breaking change to the API, /// and is returned along with the JSON blob as [`Crate::format_version`]. /// Consuming code should assert that this value matches the format version(s) that it supports. -pub const FORMAT_VERSION: u32 = 39; +pub const FORMAT_VERSION: u32 = 40; /// The root of the emitted JSON blob. /// @@ -120,7 +120,9 @@ pub struct Item { pub docs: Option<String>, /// This mapping resolves [intra-doc links](https://github.com/rust-lang/rfcs/blob/master/text/1946-intra-rustdoc-links.md) from the docstring to their IDs pub links: HashMap<String, Id>, - /// Stringified versions of the attributes on this item (e.g. `"#[inline]"`) + /// Stringified versions of parsed attributes on this item. + /// Essentially debug printed (e.g. `#[inline]` becomes something similar to `#[attr="Inline(Hint)"]`). + /// Equivalent to the hir pretty-printing of attributes. pub attrs: Vec<String>, /// Information about the item’s deprecation, if present. pub deprecation: Option<Deprecation>, diff --git a/src/tools/clippy/clippy_lints/src/attrs/inline_always.rs b/src/tools/clippy/clippy_lints/src/attrs/inline_always.rs index 2325f914b0b..cb63fadb4e2 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/inline_always.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/inline_always.rs @@ -20,7 +20,7 @@ pub(super) fn check(cx: &LateContext<'_>, span: Span, name: Symbol, attrs: &[Att span_lint( cx, INLINE_ALWAYS, - attr.span, + attr.span(), format!("you have declared `#[inline(always)]` on `{name}`. This is usually a bad idea"), ); } diff --git a/src/tools/clippy/clippy_lints/src/attrs/repr_attributes.rs b/src/tools/clippy/clippy_lints/src/attrs/repr_attributes.rs index 6d1ab46aa0c..6cc47596bbb 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/repr_attributes.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/repr_attributes.rs @@ -1,6 +1,7 @@ +use rustc_attr_parsing::{find_attr, AttributeKind, ReprAttr}; use rustc_hir::Attribute; use rustc_lint::LateContext; -use rustc_span::{Span, sym}; +use rustc_span::Span; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::msrvs; @@ -14,30 +15,21 @@ pub(super) fn check(cx: &LateContext<'_>, item_span: Span, attrs: &[Attribute], } fn check_packed(cx: &LateContext<'_>, item_span: Span, attrs: &[Attribute]) { - if let Some(items) = attrs.iter().find_map(|attr| { - if attr.ident().is_some_and(|ident| matches!(ident.name, sym::repr)) { - attr.meta_item_list() - } else { - None + if let Some(reprs) = find_attr!(attrs, AttributeKind::Repr(r) => r) { + let packed_span = reprs.iter().find(|(r, _)| matches!(r, ReprAttr::ReprPacked(..))).map(|(_, s)| *s); + + if let Some(packed_span) = packed_span && !reprs.iter().any(|(x, _)| *x == ReprAttr::ReprC || *x == ReprAttr::ReprRust) { + span_lint_and_then( + cx, + REPR_PACKED_WITHOUT_ABI, + item_span, + "item uses `packed` representation without ABI-qualification", + |diag| { + diag.warn("unqualified `#[repr(packed)]` defaults to `#[repr(Rust, packed)]`, which has no stable ABI") + .help("qualify the desired ABI explicity via `#[repr(C, packed)]` or `#[repr(Rust, packed)]`") + .span_label(packed_span, "`packed` representation set here"); + }, + ); } - }) && let Some(packed) = items - .iter() - .find(|item| item.ident().is_some_and(|ident| matches!(ident.name, sym::packed))) - && !items.iter().any(|item| { - item.ident() - .is_some_and(|ident| matches!(ident.name, sym::C | sym::Rust)) - }) - { - span_lint_and_then( - cx, - REPR_PACKED_WITHOUT_ABI, - item_span, - "item uses `packed` representation without ABI-qualification", - |diag| { - diag.warn("unqualified `#[repr(packed)]` defaults to `#[repr(Rust, packed)]`, which has no stable ABI") - .help("qualify the desired ABI explicity via `#[repr(C, packed)]` or `#[repr(Rust, packed)]`") - .span_label(packed.span(), "`packed` representation set here"); - }, - ); } } diff --git a/src/tools/clippy/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs b/src/tools/clippy/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs index 478ba7a187b..6ee3290fa76 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs @@ -15,7 +15,7 @@ pub(super) fn check( ) { if cfg_attr.has_name(sym::clippy) && let Some(ident) = behind_cfg_attr.ident() - && Level::from_symbol(ident.name, Some(attr.id)).is_some() + && Level::from_symbol(ident.name, || Some(attr.id)).is_some() && let Some(items) = behind_cfg_attr.meta_item_list() { let nb_items = items.len(); diff --git a/src/tools/clippy/clippy_lints/src/attrs/utils.rs b/src/tools/clippy/clippy_lints/src/attrs/utils.rs index a667649f734..0e650e49392 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/utils.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/utils.rs @@ -17,7 +17,7 @@ pub(super) fn is_word(nmi: &MetaItemInner, expected: Symbol) -> bool { } pub(super) fn is_lint_level(symbol: Symbol, attr_id: AttrId) -> bool { - Level::from_symbol(symbol, Some(attr_id)).is_some() + Level::from_symbol(symbol, || Some(attr_id)).is_some() } pub(super) fn is_relevant_item(cx: &LateContext<'_>, item: &Item<'_>) -> bool { diff --git a/src/tools/clippy/clippy_lints/src/default_union_representation.rs b/src/tools/clippy/clippy_lints/src/default_union_representation.rs index 9f020d3081c..6e6d81db11c 100644 --- a/src/tools/clippy/clippy_lints/src/default_union_representation.rs +++ b/src/tools/clippy/clippy_lints/src/default_union_representation.rs @@ -1,10 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_then; +use rustc_attr_parsing::{find_attr, AttributeKind, ReprAttr}; use rustc_hir::{HirId, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, FieldDef}; use rustc_session::declare_lint_pass; -use rustc_span::sym; declare_clippy_lint! { /// ### What it does @@ -97,16 +97,7 @@ fn is_zst<'tcx>(cx: &LateContext<'tcx>, field: &FieldDef, args: ty::GenericArgsR } fn has_c_repr_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool { - cx.tcx.hir().attrs(hir_id).iter().any(|attr| { - if attr.has_name(sym::repr) { - if let Some(items) = attr.meta_item_list() { - for item in items { - if item.is_word() && matches!(item.name_or_empty(), sym::C) { - return true; - } - } - } - } - false - }) + let attrs = cx.tcx.hir().attrs(hir_id); + + find_attr!(attrs, AttributeKind::Repr(r) if r.iter().any(|(x, _)| *x == ReprAttr::ReprC)) } diff --git a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs index 4e8853821c3..6de16e306c9 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs @@ -1,3 +1,4 @@ + use clippy_config::Conf; use clippy_config::types::create_disallowed_map; use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; diff --git a/src/tools/clippy/clippy_lints/src/doc/include_in_doc_without_cfg.rs b/src/tools/clippy/clippy_lints/src/doc/include_in_doc_without_cfg.rs index 4b40fc0b1ee..aa29705cf93 100644 --- a/src/tools/clippy/clippy_lints/src/doc/include_in_doc_without_cfg.rs +++ b/src/tools/clippy/clippy_lints/src/doc/include_in_doc_without_cfg.rs @@ -1,18 +1,17 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_opt; -use rustc_ast::AttrStyle; use rustc_errors::Applicability; -use rustc_hir::{AttrArgs, AttrKind, Attribute}; -use rustc_lint::LateContext; +use rustc_lint::EarlyContext; +use rustc_ast::{Attribute, AttrKind, AttrArgs, AttrStyle}; use super::DOC_INCLUDE_WITHOUT_CFG; -pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) { +pub fn check(cx: &EarlyContext<'_>, attrs: &[Attribute]) { for attr in attrs { if !attr.span.from_expansion() && let AttrKind::Normal(ref item) = attr.kind && attr.doc_str().is_some() - && let AttrArgs::Eq { expr: meta, .. } = &item.args + && let AttrArgs::Eq { expr: meta, .. } = &item.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/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs index 713d62a8801..42192801af7 100644 --- a/src/tools/clippy/clippy_lints/src/doc/mod.rs +++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs @@ -20,7 +20,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{AnonConst, Attribute, Expr, ImplItemKind, ItemKind, Node, Safety, TraitItemKind}; -use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; use rustc_middle::hir::nested_filter; use rustc_middle::ty; use rustc_resolve::rustdoc::{ @@ -577,6 +577,13 @@ impl_lint_pass!(Documentation => [ DOC_INCLUDE_WITHOUT_CFG, ]); + +impl EarlyLintPass for Documentation { + fn check_attributes(&mut self, cx: &EarlyContext<'_>, attrs: &[rustc_ast::Attribute]) { + include_in_doc_without_cfg::check(cx, attrs); + } +} + impl<'tcx> LateLintPass<'tcx> for Documentation { fn check_attributes(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) { let Some(headers) = check_attrs(cx, &self.valid_idents, attrs) else { @@ -704,14 +711,13 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &[ Some(("fake".into(), "fake".into())) } - include_in_doc_without_cfg::check(cx, attrs); if suspicious_doc_comments::check(cx, attrs) || is_doc_hidden(attrs) { return None; } let (fragments, _) = attrs_to_doc_fragments( attrs.iter().filter_map(|attr| { - if attr.span.in_external_macro(cx.sess().source_map()) { + if !attr.doc_str_and_comment_kind().is_some() || attr.span().in_external_macro(cx.sess().source_map()) { None } else { Some((attr, None)) diff --git a/src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs b/src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs index 84393213e6f..bfc36deea7b 100644 --- a/src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs +++ b/src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs @@ -3,6 +3,7 @@ use rustc_ast::AttrStyle; use rustc_ast::token::CommentKind; use rustc_errors::Applicability; use rustc_hir::Attribute; +use rustc_attr_parsing::AttributeKind; use rustc_lint::LateContext; use rustc_span::Span; @@ -36,15 +37,14 @@ fn collect_doc_replacements(attrs: &[Attribute]) -> Vec<(Span, String)> { attrs .iter() .filter_map(|attr| { - 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('!') + if let Attribute::Parsed(AttributeKind::DocComment{ style: AttrStyle::Outer, kind, comment, ..}) = attr + && let Some(com) = comment.as_str().strip_prefix('!') { - let sugg = match com_kind { + let sugg = match kind { CommentKind::Line => format!("//!{com}"), CommentKind::Block => format!("/*!{com}*/"), }; - Some((attr.span, sugg)) + Some((attr.span(), sugg)) } else { None } diff --git a/src/tools/clippy/clippy_lints/src/doc/too_long_first_doc_paragraph.rs b/src/tools/clippy/clippy_lints/src/doc/too_long_first_doc_paragraph.rs index 1f89cab9148..1eda73a9672 100644 --- a/src/tools/clippy/clippy_lints/src/doc/too_long_first_doc_paragraph.rs +++ b/src/tools/clippy/clippy_lints/src/doc/too_long_first_doc_paragraph.rs @@ -1,5 +1,6 @@ use rustc_errors::Applicability; use rustc_hir::{Attribute, Item, ItemKind}; +use rustc_attr_parsing::AttributeKind; use rustc_lint::LateContext; use clippy_utils::diagnostics::span_lint_and_then; @@ -43,9 +44,9 @@ pub(super) fn check( let mut should_suggest_empty_doc = false; for attr in attrs { - if let Some(doc) = attr.doc_str() { - spans.push(attr.span); - let doc = doc.as_str(); + if let Attribute::Parsed(AttributeKind::DocComment {span, comment, ..}) = attr { + spans.push(span); + let doc = comment.as_str(); let doc = doc.trim(); if spans.len() == 1 { // We make this suggestion only if the first doc line ends with a punctuation @@ -78,7 +79,7 @@ pub(super) fn check( && let new_span = first_span.with_hi(second_span.lo()).with_lo(first_span.hi()) && let Some(snippet) = snippet_opt(cx, new_span) { - let Some(first) = snippet_opt(cx, first_span) else { + let Some(first) = snippet_opt(cx, *first_span) else { return; }; let Some(comment_form) = first.get(..3) else { diff --git a/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs b/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs index 0599e08e6c0..0bdb99d7b9a 100644 --- a/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs +++ b/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs @@ -46,7 +46,8 @@ impl<'tcx> LateLintPass<'tcx> for FourForwardSlashes { .hir() .attrs(item.hir_id()) .iter() - .fold(item.span.shrink_to_lo(), |span, attr| span.to(attr.span)); + .filter(|i| i.is_doc_comment()) + .fold(item.span.shrink_to_lo(), |span, attr| span.to(attr.span())); let (Some(file), _, _, end_line, _) = sm.span_to_location_info(span) else { return; }; diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs index e6e3ea59a9f..dbc08fca362 100644 --- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs +++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs @@ -95,6 +95,7 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr } } +// FIXME: needs to be an EARLY LINT. all attribute lints should be #[allow(clippy::too_many_arguments)] fn check_needless_must_use( cx: &LateContext<'_>, @@ -117,7 +118,7 @@ fn check_needless_must_use( fn_header_span, "this unit-returning function has a `#[must_use]` attribute", |diag| { - diag.span_suggestion(attr.span, "remove the attribute", "", Applicability::MachineApplicable); + diag.span_suggestion(attr.span(), "remove the attribute", "", Applicability::MachineApplicable); }, ); } else { @@ -130,7 +131,7 @@ fn check_needless_must_use( "this unit-returning function has a `#[must_use]` attribute", |diag| { let mut attrs_without_must_use = attrs.to_vec(); - attrs_without_must_use.retain(|a| a.id != attr.id); + attrs_without_must_use.retain(|a| a.id() != attr.id()); let sugg_str = attrs_without_must_use .iter() .map(|a| { @@ -143,7 +144,7 @@ fn check_needless_must_use( .join(", "); diag.span_suggestion( - attrs[0].span.with_hi(attrs[attrs.len() - 1].span.hi()), + attrs[0].span().with_hi(attrs[attrs.len() - 1].span().hi()), "change these attributes to", sugg_str, Applicability::MachineApplicable, diff --git a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs index 39ff3c13bcc..5b58113169b 100644 --- a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs +++ b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs @@ -183,7 +183,7 @@ fn suggestion<'tcx>( fn field_with_attrs_span(tcx: TyCtxt<'_>, field: &hir::ExprField<'_>) -> Span { if let Some(attr) = tcx.hir().attrs(field.hir_id).first() { - field.span.with_lo(attr.span.lo()) + field.span.with_lo(attr.span().lo()) } else { field.span } diff --git a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs index 1b900f6be8e..9b4a3b3f9c8 100644 --- a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs +++ b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs @@ -42,10 +42,10 @@ impl<'tcx> LateLintPass<'tcx> for InlineFnWithoutBody { span_lint_and_then( cx, INLINE_FN_WITHOUT_BODY, - attr.span, + attr.span(), format!("use of `#[inline]` on trait method `{}` which has no body", item.ident), |diag| { - diag.suggest_remove_item(cx, attr.span, "remove", Applicability::MachineApplicable); + diag.suggest_remove_item(cx, attr.span(), "remove", Applicability::MachineApplicable); }, ); } diff --git a/src/tools/clippy/clippy_lints/src/large_include_file.rs b/src/tools/clippy/clippy_lints/src/large_include_file.rs index f3d62b513e8..53dc070833b 100644 --- a/src/tools/clippy/clippy_lints/src/large_include_file.rs +++ b/src/tools/clippy/clippy_lints/src/large_include_file.rs @@ -3,10 +3,11 @@ 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::LitKind; -use rustc_hir::{AttrArgs, AttrKind, Attribute, Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass}; +use rustc_hir::{Expr, ExprKind}; +use rustc_ast::{Attribute, AttrArgs, AttrKind}; +use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; use rustc_session::impl_lint_pass; -use rustc_span::{Span, sym}; +use rustc_span::sym; declare_clippy_lint! { /// ### What it does @@ -52,24 +53,6 @@ impl LargeIncludeFile { impl_lint_pass!(LargeIncludeFile => [LARGE_INCLUDE_FILE]); -impl LargeIncludeFile { - fn emit_lint(&self, cx: &LateContext<'_>, span: Span) { - #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] - span_lint_and_then( - cx, - LARGE_INCLUDE_FILE, - span, - "attempted to include a large file", - |diag| { - diag.note(format!( - "the configuration allows a maximum size of {} bytes", - self.max_file_size - )); - }, - ); - } -} - impl LateLintPass<'_> for LargeIncludeFile { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) { if let ExprKind::Lit(lit) = &expr.kind @@ -85,18 +68,32 @@ impl LateLintPass<'_> for LargeIncludeFile { && (cx.tcx.is_diagnostic_item(sym::include_bytes_macro, macro_call.def_id) || cx.tcx.is_diagnostic_item(sym::include_str_macro, macro_call.def_id)) { - self.emit_lint(cx, expr.span.source_callsite()); + #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] + span_lint_and_then( + cx, + LARGE_INCLUDE_FILE, + expr.span.source_callsite(), + "attempted to include a large file", + |diag| { + diag.note(format!( + "the configuration allows a maximum size of {} bytes", + self.max_file_size + )); + }, + ); } } +} - fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &Attribute) { +impl EarlyLintPass for LargeIncludeFile { + fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) { 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 item) = attr.kind && let Some(doc) = attr.doc_str() && doc.as_str().len() as u64 > self.max_file_size - && let AttrArgs::Eq { expr: meta, .. } = &item.args + && let AttrArgs::Eq { expr: meta, .. } = &item.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. @@ -113,7 +110,19 @@ impl LateLintPass<'_> for LargeIncludeFile { && let sub_snippet = sub_snippet.trim() && (sub_snippet.starts_with("include_str!") || sub_snippet.starts_with("include_bytes!")) { - self.emit_lint(cx, attr.span); + #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] + span_lint_and_then( + cx, + LARGE_INCLUDE_FILE, + attr.span, + "attempted to include a large file", + |diag| { + diag.note(format!( + "the configuration allows a maximum size of {} bytes", + self.max_file_size + )); + }, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index 13218331a67..177f83921cd 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -407,9 +407,9 @@ mod zombie_processes; use clippy_config::{Conf, get_configuration_metadata, sanitize_explanation}; use clippy_utils::macros::FormatArgsStorage; +use utils::attr_collector::{AttrCollector, AttrStorage}; use rustc_data_structures::fx::FxHashSet; use rustc_lint::{Lint, LintId}; -use utils::attr_collector::{AttrCollector, AttrStorage}; /// Register all pre expansion lints /// @@ -717,6 +717,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(move |_| Box::new(disallowed_names::DisallowedNames::new(conf))); store.register_late_pass(move |tcx| Box::new(functions::Functions::new(tcx, conf))); store.register_late_pass(move |_| Box::new(doc::Documentation::new(conf))); + store.register_early_pass(move || Box::new(doc::Documentation::new(conf))); store.register_late_pass(|_| Box::new(neg_multiply::NegMultiply)); store.register_late_pass(|_| Box::new(let_if_seq::LetIfSeq)); store.register_late_pass(|_| Box::new(mixed_read_write_in_expression::EvalOrderDependence)); @@ -860,6 +861,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_early_pass(|| Box::new(pub_use::PubUse)); store.register_late_pass(|_| Box::new(format_push_string::FormatPushString)); store.register_late_pass(move |_| Box::new(large_include_file::LargeIncludeFile::new(conf))); + store.register_early_pass(move || Box::new(large_include_file::LargeIncludeFile::new(conf))); store.register_late_pass(|_| Box::new(strings::TrimSplitWhitespace)); store.register_late_pass(|_| Box::new(rc_clone_in_vec_init::RcCloneInVecInit)); store.register_early_pass(|| Box::<duplicate_mod::DuplicateMod>::default()); diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs index 37412866539..165e8c2ea05 100644 --- a/src/tools/clippy/clippy_lints/src/macro_use.rs +++ b/src/tools/clippy/clippy_lints/src/macro_use.rs @@ -94,7 +94,7 @@ impl LateLintPass<'_> for MacroUseImports { { for kid in cx.tcx.module_children(id) { if let Res::Def(DefKind::Macro(_mac_type), mac_id) = kid.res { - let span = mac_attr.span; + let span = mac_attr.span(); let def_path = cx.tcx.def_path_str(mac_id); self.imports.push((def_path, span, hir_id)); } @@ -104,8 +104,8 @@ impl LateLintPass<'_> for MacroUseImports { } } fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &hir::Attribute) { - if attr.span.from_expansion() { - self.push_unique_macro(cx, attr.span); + if attr.span().from_expansion() { + self.push_unique_macro(cx, attr.span()); } } fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) { diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs index 00800231fe4..83d8a509390 100644 --- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs +++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs @@ -116,7 +116,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive { if let Some(non_exhaustive) = attr::find_by_name(cx.tcx.hir().attrs(item.hir_id()), sym::non_exhaustive) { - diag.span_note(non_exhaustive.span, "the struct is already non-exhaustive"); + diag.span_note(non_exhaustive.span(), "the struct is already non-exhaustive"); } else { let indent = snippet_indent(cx, item.span).unwrap_or_default(); diag.span_suggestion_verbose( diff --git a/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs b/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs index b73b9083a99..6eca3f12cf2 100644 --- a/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs +++ b/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs @@ -54,7 +54,7 @@ impl<'tcx> LateLintPass<'tcx> for NoMangleWithRustAbi { .span .with_lo(fn_sig.span.lo() + BytePos::from_usize(fn_attrs.len())) .shrink_to_lo(); - let attr_snippet = snippet(cx, attr.span, ".."); + let attr_snippet = snippet(cx, attr.span(), ".."); span_lint_and_then( cx, diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs index 93abf95e357..16916e3aaad 100644 --- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -432,7 +432,7 @@ fn include_attrs_in_span(cx: &LateContext<'_>, hir_id: HirId, span: Span) -> Spa .hir() .attrs(hir_id) .iter() - .fold(span, |acc, attr| acc.to(attr.span))) + .fold(span, |acc, attr| acc.to(attr.span()))) } enum HasSafetyComment { diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 40ddd75b7fa..7fc25e3617d 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -93,6 +93,7 @@ use std::sync::{Mutex, MutexGuard, OnceLock}; use itertools::Itertools; use rustc_ast::ast::{self, LitKind, RangeLimits}; +use rustc_attr_parsing::{find_attr, AttributeKind}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::packed::Pu128; use rustc_data_structures::unhash::UnhashMap; @@ -1949,7 +1950,7 @@ pub fn has_attr(attrs: &[hir::Attribute], symbol: Symbol) -> bool { } pub fn has_repr_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool { - has_attr(cx.tcx.hir().attrs(hir_id), sym::repr) + find_attr!(cx.tcx.hir().attrs(hir_id), AttributeKind::Repr(..)) } pub fn any_parent_has_attr(tcx: TyCtxt<'_>, node: HirId, symbol: Symbol) -> bool { diff --git a/src/tools/clippy/tests/ui-toml/large_include_file/large_include_file.stderr b/src/tools/clippy/tests/ui-toml/large_include_file/large_include_file.stderr index 82b926cc53b..c9f0e661dbd 100644 --- a/src/tools/clippy/tests/ui-toml/large_include_file/large_include_file.stderr +++ b/src/tools/clippy/tests/ui-toml/large_include_file/large_include_file.stderr @@ -1,26 +1,26 @@ error: attempted to include a large file - --> tests/ui-toml/large_include_file/large_include_file.rs:14:43 + --> tests/ui-toml/large_include_file/large_include_file.rs:19:1 | -LL | const TOO_BIG_INCLUDE_BYTES: &[u8; 654] = include_bytes!("too_big.txt"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[doc = include_str!("too_big.txt")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the configuration allows a maximum size of 600 bytes = note: `-D clippy::large-include-file` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::large_include_file)]` error: attempted to include a large file - --> tests/ui-toml/large_include_file/large_include_file.rs:16:35 + --> tests/ui-toml/large_include_file/large_include_file.rs:14:43 | -LL | const TOO_BIG_INCLUDE_STR: &str = include_str!("too_big.txt"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | const TOO_BIG_INCLUDE_BYTES: &[u8; 654] = include_bytes!("too_big.txt"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the configuration allows a maximum size of 600 bytes error: attempted to include a large file - --> tests/ui-toml/large_include_file/large_include_file.rs:19:1 + --> tests/ui-toml/large_include_file/large_include_file.rs:16:35 | -LL | #[doc = include_str!("too_big.txt")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | const TOO_BIG_INCLUDE_STR: &str = include_str!("too_big.txt"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the configuration allows a maximum size of 600 bytes diff --git a/src/tools/clippy/tests/ui/must_use_unit.fixed b/src/tools/clippy/tests/ui/must_use_unit.fixed index b92d9379c90..f2b990beddc 100644 --- a/src/tools/clippy/tests/ui/must_use_unit.fixed +++ b/src/tools/clippy/tests/ui/must_use_unit.fixed @@ -24,8 +24,8 @@ fn main() { ); } -#[cfg_attr(all(), deprecated)] +#[cfg_attr(all(), )] fn issue_12320() {} -#[cfg_attr(all(), deprecated, doc = "foo")] +#[cfg_attr(all(), deprecateddoc = "foo", doc = "foo", must_use)] fn issue_12320_2() {} diff --git a/src/tools/clippy/tests/ui/must_use_unit.stderr b/src/tools/clippy/tests/ui/must_use_unit.stderr index b435568deea..40a0dc3ca9b 100644 --- a/src/tools/clippy/tests/ui/must_use_unit.stderr +++ b/src/tools/clippy/tests/ui/must_use_unit.stderr @@ -25,19 +25,21 @@ LL | #[must_use = "With note"] LL | pub fn must_use_with_note() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +[Unparsed(AttrItem { path: AttrPath { segments: [must_use#0], span: tests/ui/must_use_unit.rs:30:19: 30:27 (#0) }, args: Empty, id: HashIgnoredAttrId { attr_id: AttrId(9) }, style: Outer, span: tests/ui/must_use_unit.rs:30:19: 30:27 (#0) }), Parsed(Deprecation { deprecation: Deprecation { since: Unspecified, note: None, suggestion: None }, span: tests/ui/must_use_unit.rs:30:29: 30:39 (#0) })] error: this unit-returning function has a `#[must_use]` attribute --> tests/ui/must_use_unit.rs:31:1 | LL | #[cfg_attr(all(), must_use, deprecated)] - | -------------------- help: change these attributes to: `deprecated` + | -------------------- help: change these attributes to LL | fn issue_12320() {} | ^^^^^^^^^^^^^^^^ +[Unparsed(AttrItem { path: AttrPath { segments: [doc#0], span: tests/ui/must_use_unit.rs:33:31: 33:34 (#0) }, args: Eq { eq_span: tests/ui/must_use_unit.rs:33:35: 33:36 (#0), expr: MetaItemLit { symbol: "foo", suffix: None, kind: Str("foo", Cooked), span: tests/ui/must_use_unit.rs:33:37: 33:42 (#0) } }, id: HashIgnoredAttrId { attr_id: AttrId(12) }, style: Outer, span: tests/ui/must_use_unit.rs:33:31: 33:42 (#0) }), Unparsed(AttrItem { path: AttrPath { segments: [must_use#0], span: tests/ui/must_use_unit.rs:33:44: 33:52 (#0) }, args: Empty, id: HashIgnoredAttrId { attr_id: AttrId(13) }, style: Outer, span: tests/ui/must_use_unit.rs:33:44: 33:52 (#0) }), Parsed(Deprecation { deprecation: Deprecation { since: Unspecified, note: None, suggestion: None }, span: tests/ui/must_use_unit.rs:33:19: 33:29 (#0) })] error: this unit-returning function has a `#[must_use]` attribute --> tests/ui/must_use_unit.rs:34:1 | LL | #[cfg_attr(all(), deprecated, doc = "foo", must_use)] - | --------------------------------- help: change these attributes to: `deprecated, doc = "foo"` + | -- help: change these attributes to: `doc = "foo",` LL | fn issue_12320_2() {} | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/rustdoc-json/enums/discriminant/struct.rs b/tests/rustdoc-json/enums/discriminant/struct.rs index 0ac40cda733..24d5f5b08c2 100644 --- a/tests/rustdoc-json/enums/discriminant/struct.rs +++ b/tests/rustdoc-json/enums/discriminant/struct.rs @@ -1,7 +1,7 @@ // ignore-tidy-linelength #[repr(i32)] -//@ is "$.index[*][?(@.name=='Foo')].attrs" '["#[repr(i32)]"]' +//@ is "$.index[*][?(@.name=='Foo')].attrs" '["#[attr=\"Repr([ReprInt(SignedInt(I32))])\")]\n"]' pub enum Foo { //@ is "$.index[*][?(@.name=='Struct')].inner.variant.discriminant" null //@ count "$.index[*][?(@.name=='Struct')].inner.variant.kind.struct.fields[*]" 0 diff --git a/tests/rustdoc-json/enums/discriminant/tuple.rs b/tests/rustdoc-json/enums/discriminant/tuple.rs index fbff5aacd67..a50ae8b9189 100644 --- a/tests/rustdoc-json/enums/discriminant/tuple.rs +++ b/tests/rustdoc-json/enums/discriminant/tuple.rs @@ -1,7 +1,7 @@ // ignore-tidy-linelength #[repr(u32)] -//@ is "$.index[*][?(@.name=='Foo')].attrs" '["#[repr(u32)]"]' +//@ is "$.index[*][?(@.name=='Foo')].attrs" '["#[attr=\"Repr([ReprInt(UnsignedInt(U32))])\")]\n"]' pub enum Foo { //@ is "$.index[*][?(@.name=='Tuple')].inner.variant.discriminant" null //@ count "$.index[*][?(@.name=='Tuple')].inner.variant.kind.tuple[*]" 0 |
