1
Fork 0

Fix rustdoc and clippy

This commit is contained in:
Jana Dönszelmann 2025-02-09 22:49:57 +01:00
parent 7e0f5b5016
commit f321f107e3
No known key found for this signature in database
31 changed files with 135 additions and 122 deletions

View file

@ -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 { .. }))
}

View file

@ -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));
}
}
}
}
}

View file

@ -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`"
);
};

View file

@ -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)
};

View file

@ -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 items deprecation, if present.
pub deprecation: Option<Deprecation>,

View file

@ -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"),
);
}

View file

@ -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");
},
);
}
}

View file

@ -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();

View file

@ -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 {

View file

@ -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))
}

View file

@ -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};

View file

@ -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.

View file

@ -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))

View file

@ -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
}

View file

@ -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 {

View file

@ -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;
};

View file

@ -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,

View file

@ -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
}

View file

@ -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);
},
);
}

View file

@ -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
));
},
);
}
}
}

View file

@ -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());

View file

@ -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<'_>) {

View file

@ -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(

View file

@ -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,

View file

@ -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 {

View file

@ -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 {

View file

@ -1,3 +1,13 @@
error: attempted to include a large file
--> tests/ui-toml/large_include_file/large_include_file.rs:19:1
|
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:14:43
|
@ -5,8 +15,6 @@ LL | const TOO_BIG_INCLUDE_BYTES: &[u8; 654] = include_bytes!("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
@ -16,13 +24,5 @@ LL | const TOO_BIG_INCLUDE_STR: &str = include_str!("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
|
LL | #[doc = include_str!("too_big.txt")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the configuration allows a maximum size of 600 bytes
error: aborting due to 3 previous errors

View file

@ -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() {}

View file

@ -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() {}
| ^^^^^^^^^^^^^^^^^^

View file

@ -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

View file

@ -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