Auto merge of #131808 - jdonszelmann:hir-attributes, r=oli-obk,petrochenkov
Hir attributes This PR needs some explanation, it's somewhat large. - This is step one as described in https://github.com/rust-lang/compiler-team/issues/796. I've added a new `hir::Attribute` which is a lowered version of `ast::Attribute`. Right now, this has few concrete effects, however every place that after this PR parses a `hir::Attribute` should later get a pre-parsed attribute as described in https://github.com/rust-lang/compiler-team/issues/796 and transitively https://github.com/rust-lang/rust/issues/131229. - an extension trait `AttributeExt` is added, which is implemented for both `ast::Attribute` and `hir::Atribute`. This makes `hir::Attributes` mostly compatible with code that used to parse `ast::Attribute`. All its methods are also added as inherent methods to avoid having to import the trait everywhere in the compiler. - Incremental can not not hash `ast::Attribute` at all.
This commit is contained in:
commit
f2b91ccbc2
89 changed files with 1153 additions and 717 deletions
|
|
@ -4,6 +4,7 @@ use std::iter::once;
|
|||
use std::sync::Arc;
|
||||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::Mutability;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{DefId, DefIdSet, LocalDefId, LocalModDefId};
|
||||
|
|
@ -15,7 +16,6 @@ use rustc_span::hygiene::MacroKind;
|
|||
use rustc_span::symbol::{Symbol, sym};
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
use tracing::{debug, trace};
|
||||
use {rustc_ast as ast, rustc_hir as hir};
|
||||
|
||||
use super::Item;
|
||||
use crate::clean::{
|
||||
|
|
@ -43,7 +43,7 @@ pub(crate) fn try_inline(
|
|||
cx: &mut DocContext<'_>,
|
||||
res: Res,
|
||||
name: Symbol,
|
||||
attrs: Option<(&[ast::Attribute], Option<LocalDefId>)>,
|
||||
attrs: Option<(&[hir::Attribute], Option<LocalDefId>)>,
|
||||
visited: &mut DefIdSet,
|
||||
) -> Option<Vec<clean::Item>> {
|
||||
let did = res.opt_def_id()?;
|
||||
|
|
@ -206,7 +206,7 @@ pub(crate) fn try_inline_glob(
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn load_attrs<'hir>(cx: &DocContext<'hir>, did: DefId) -> &'hir [ast::Attribute] {
|
||||
pub(crate) fn load_attrs<'hir>(cx: &DocContext<'hir>, did: DefId) -> &'hir [hir::Attribute] {
|
||||
cx.tcx.get_attrs_unchecked(did)
|
||||
}
|
||||
|
||||
|
|
@ -360,7 +360,7 @@ fn build_type_alias(
|
|||
pub(crate) fn build_impls(
|
||||
cx: &mut DocContext<'_>,
|
||||
did: DefId,
|
||||
attrs: Option<(&[ast::Attribute], Option<LocalDefId>)>,
|
||||
attrs: Option<(&[hir::Attribute], Option<LocalDefId>)>,
|
||||
ret: &mut Vec<clean::Item>,
|
||||
) {
|
||||
let _prof_timer = cx.tcx.sess.prof.generic_activity("build_inherent_impls");
|
||||
|
|
@ -392,8 +392,8 @@ pub(crate) fn build_impls(
|
|||
|
||||
pub(crate) fn merge_attrs(
|
||||
cx: &mut DocContext<'_>,
|
||||
old_attrs: &[ast::Attribute],
|
||||
new_attrs: Option<(&[ast::Attribute], Option<LocalDefId>)>,
|
||||
old_attrs: &[hir::Attribute],
|
||||
new_attrs: Option<(&[hir::Attribute], Option<LocalDefId>)>,
|
||||
) -> (clean::Attributes, Option<Arc<clean::cfg::Cfg>>) {
|
||||
// NOTE: If we have additional attributes (from a re-export),
|
||||
// always insert them first. This ensure that re-export
|
||||
|
|
@ -404,14 +404,14 @@ pub(crate) fn merge_attrs(
|
|||
both.extend_from_slice(old_attrs);
|
||||
(
|
||||
if let Some(item_id) = item_id {
|
||||
Attributes::from_ast_with_additional(old_attrs, (inner, item_id.to_def_id()))
|
||||
Attributes::from_hir_with_additional(old_attrs, (inner, item_id.to_def_id()))
|
||||
} else {
|
||||
Attributes::from_ast(&both)
|
||||
Attributes::from_hir(&both)
|
||||
},
|
||||
both.cfg(cx.tcx, &cx.cache.hidden_cfg),
|
||||
)
|
||||
} else {
|
||||
(Attributes::from_ast(old_attrs), old_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg))
|
||||
(Attributes::from_hir(old_attrs), old_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -419,7 +419,7 @@ pub(crate) fn merge_attrs(
|
|||
pub(crate) fn build_impl(
|
||||
cx: &mut DocContext<'_>,
|
||||
did: DefId,
|
||||
attrs: Option<(&[ast::Attribute], Option<LocalDefId>)>,
|
||||
attrs: Option<(&[hir::Attribute], Option<LocalDefId>)>,
|
||||
ret: &mut Vec<clean::Item>,
|
||||
) {
|
||||
if !cx.inlined.insert(did.into()) {
|
||||
|
|
@ -629,7 +629,7 @@ fn build_module_items(
|
|||
visited: &mut DefIdSet,
|
||||
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
|
||||
allowed_def_ids: Option<&DefIdSet>,
|
||||
attrs: Option<(&[ast::Attribute], Option<LocalDefId>)>,
|
||||
attrs: Option<(&[hir::Attribute], Option<LocalDefId>)>,
|
||||
) -> Vec<clean::Item> {
|
||||
let mut items = Vec::new();
|
||||
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ fn generate_item_with_correct_attrs(
|
|||
};
|
||||
|
||||
let cfg = attrs.cfg(cx.tcx, &cx.cache.hidden_cfg);
|
||||
let attrs = Attributes::from_ast_iter(attrs.iter().map(|(attr, did)| (&**attr, *did)), false);
|
||||
let attrs = Attributes::from_hir_iter(attrs.iter().map(|(attr, did)| (&**attr, *did)), false);
|
||||
|
||||
let name = renamed.or(Some(name));
|
||||
let mut item = Item::from_def_id_and_attrs_and_parts(def_id, name, kind, attrs, cfg);
|
||||
|
|
@ -1036,7 +1036,7 @@ fn clean_fn_or_proc_macro<'tcx>(
|
|||
/// This is needed to make it more "readable" when documenting functions using
|
||||
/// `rustc_legacy_const_generics`. More information in
|
||||
/// <https://github.com/rust-lang/rust/issues/83167>.
|
||||
fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[ast::Attribute]) {
|
||||
fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[hir::Attribute]) {
|
||||
for meta_item_list in attrs
|
||||
.iter()
|
||||
.filter(|a| a.has_name(sym::rustc_legacy_const_generics))
|
||||
|
|
@ -2578,7 +2578,7 @@ fn get_all_import_attributes<'hir>(
|
|||
import_def_id: LocalDefId,
|
||||
target_def_id: DefId,
|
||||
is_inline: bool,
|
||||
) -> Vec<(Cow<'hir, ast::Attribute>, Option<DefId>)> {
|
||||
) -> Vec<(Cow<'hir, hir::Attribute>, Option<DefId>)> {
|
||||
let mut attrs = Vec::new();
|
||||
let mut first = true;
|
||||
for def_id in reexport_chain(cx.tcx, import_def_id, target_def_id)
|
||||
|
|
@ -2631,9 +2631,9 @@ fn filter_doc_attr_ident(ident: Symbol, is_inline: bool) -> bool {
|
|||
|
||||
/// Remove attributes from `normal` that should not be inherited by `use` re-export.
|
||||
/// Before calling this function, make sure `normal` is a `#[doc]` attribute.
|
||||
fn filter_doc_attr(normal: &mut ast::NormalAttr, is_inline: bool) {
|
||||
match normal.item.args {
|
||||
ast::AttrArgs::Delimited(ref mut args) => {
|
||||
fn filter_doc_attr(args: &mut hir::AttrArgs, is_inline: bool) {
|
||||
match args {
|
||||
hir::AttrArgs::Delimited(ref mut args) => {
|
||||
let tokens = filter_tokens_from_list(&args.tokens, |token| {
|
||||
!matches!(
|
||||
token,
|
||||
|
|
@ -2651,7 +2651,7 @@ fn filter_doc_attr(normal: &mut ast::NormalAttr, is_inline: bool) {
|
|||
});
|
||||
args.tokens = TokenStream::new(tokens);
|
||||
}
|
||||
ast::AttrArgs::Empty | ast::AttrArgs::Eq { .. } => {}
|
||||
hir::AttrArgs::Empty | hir::AttrArgs::Eq { .. } => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2676,23 +2676,23 @@ fn filter_doc_attr(normal: &mut ast::NormalAttr, is_inline: bool) {
|
|||
/// * `doc(no_inline)`
|
||||
/// * `doc(hidden)`
|
||||
fn add_without_unwanted_attributes<'hir>(
|
||||
attrs: &mut Vec<(Cow<'hir, ast::Attribute>, Option<DefId>)>,
|
||||
new_attrs: &'hir [ast::Attribute],
|
||||
attrs: &mut Vec<(Cow<'hir, hir::Attribute>, Option<DefId>)>,
|
||||
new_attrs: &'hir [hir::Attribute],
|
||||
is_inline: bool,
|
||||
import_parent: Option<DefId>,
|
||||
) {
|
||||
for attr in new_attrs {
|
||||
if matches!(attr.kind, ast::AttrKind::DocComment(..)) {
|
||||
if matches!(attr.kind, hir::AttrKind::DocComment(..)) {
|
||||
attrs.push((Cow::Borrowed(attr), import_parent));
|
||||
continue;
|
||||
}
|
||||
let mut attr = attr.clone();
|
||||
match attr.kind {
|
||||
ast::AttrKind::Normal(ref mut normal) => {
|
||||
if let [ident] = &*normal.item.path.segments {
|
||||
let ident = ident.ident.name;
|
||||
hir::AttrKind::Normal(ref mut normal) => {
|
||||
if let [ident] = &*normal.path.segments {
|
||||
let ident = ident.name;
|
||||
if ident == sym::doc {
|
||||
filter_doc_attr(normal, is_inline);
|
||||
filter_doc_attr(&mut normal.args, is_inline);
|
||||
attrs.push((Cow::Owned(attr), import_parent));
|
||||
} else if is_inline || ident != sym::cfg {
|
||||
// If it's not a `cfg()` attribute, we keep it.
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ use std::{fmt, iter};
|
|||
|
||||
use arrayvec::ArrayVec;
|
||||
use rustc_abi::{ExternAbi, VariantIdx};
|
||||
use rustc_ast::MetaItemInner;
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_attr::{ConstStability, Deprecation, Stability, StableSince};
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||
|
|
@ -454,14 +452,14 @@ impl Item {
|
|||
kind: ItemKind,
|
||||
cx: &mut DocContext<'_>,
|
||||
) -> Item {
|
||||
let ast_attrs = cx.tcx.get_attrs_unchecked(def_id);
|
||||
let hir_attrs = cx.tcx.get_attrs_unchecked(def_id);
|
||||
|
||||
Self::from_def_id_and_attrs_and_parts(
|
||||
def_id,
|
||||
name,
|
||||
kind,
|
||||
Attributes::from_ast(ast_attrs),
|
||||
ast_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
|
||||
Attributes::from_hir(hir_attrs),
|
||||
hir_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -742,10 +740,10 @@ impl Item {
|
|||
.iter()
|
||||
.filter_map(|attr| {
|
||||
if keep_as_is {
|
||||
Some(pprust::attribute_to_string(attr))
|
||||
Some(rustc_hir_pretty::attribute_to_string(&tcx, attr))
|
||||
} else if ALLOWED_ATTRIBUTES.contains(&attr.name_or_empty()) {
|
||||
Some(
|
||||
pprust::attribute_to_string(attr)
|
||||
rustc_hir_pretty::attribute_to_string(&tcx, attr)
|
||||
.replace("\\\n", "")
|
||||
.replace('\n', "")
|
||||
.replace(" ", " "),
|
||||
|
|
@ -955,7 +953,7 @@ pub(crate) trait AttributesExt {
|
|||
type AttributeIterator<'a>: Iterator<Item = ast::MetaItemInner>
|
||||
where
|
||||
Self: 'a;
|
||||
type Attributes<'a>: Iterator<Item = &'a ast::Attribute>
|
||||
type Attributes<'a>: Iterator<Item = &'a hir::Attribute>
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
|
|
@ -1009,7 +1007,7 @@ pub(crate) trait AttributesExt {
|
|||
// #[doc]
|
||||
if attr.doc_str().is_none() && attr.has_name(sym::doc) {
|
||||
// #[doc(...)]
|
||||
if let Some(list) = attr.meta().as_ref().and_then(|mi| mi.meta_item_list()) {
|
||||
if let Some(list) = attr.meta_item_list() {
|
||||
for item in list {
|
||||
// #[doc(hidden)]
|
||||
if !item.has_name(sym::cfg) {
|
||||
|
|
@ -1042,7 +1040,7 @@ pub(crate) trait AttributesExt {
|
|||
let mut meta = attr.meta_item().unwrap().clone();
|
||||
meta.path = ast::Path::from_ident(Ident::with_dummy_span(sym::target_feature));
|
||||
|
||||
if let Ok(feat_cfg) = Cfg::parse(&MetaItemInner::MetaItem(meta)) {
|
||||
if let Ok(feat_cfg) = Cfg::parse(&ast::MetaItemInner::MetaItem(meta)) {
|
||||
cfg &= feat_cfg;
|
||||
}
|
||||
}
|
||||
|
|
@ -1053,14 +1051,14 @@ pub(crate) trait AttributesExt {
|
|||
}
|
||||
}
|
||||
|
||||
impl AttributesExt for [ast::Attribute] {
|
||||
impl AttributesExt for [hir::Attribute] {
|
||||
type AttributeIterator<'a> = impl Iterator<Item = ast::MetaItemInner> + 'a;
|
||||
type Attributes<'a> = impl Iterator<Item = &'a ast::Attribute> + 'a;
|
||||
type Attributes<'a> = impl Iterator<Item = &'a hir::Attribute> + 'a;
|
||||
|
||||
fn lists(&self, name: Symbol) -> Self::AttributeIterator<'_> {
|
||||
self.iter()
|
||||
.filter(move |attr| attr.has_name(name))
|
||||
.filter_map(ast::Attribute::meta_item_list)
|
||||
.filter_map(ast::attr::AttributeExt::meta_item_list)
|
||||
.flatten()
|
||||
}
|
||||
|
||||
|
|
@ -1069,20 +1067,20 @@ impl AttributesExt for [ast::Attribute] {
|
|||
}
|
||||
}
|
||||
|
||||
impl AttributesExt for [(Cow<'_, ast::Attribute>, Option<DefId>)] {
|
||||
impl AttributesExt for [(Cow<'_, hir::Attribute>, Option<DefId>)] {
|
||||
type AttributeIterator<'a>
|
||||
= impl Iterator<Item = ast::MetaItemInner> + 'a
|
||||
where
|
||||
Self: 'a;
|
||||
type Attributes<'a>
|
||||
= impl Iterator<Item = &'a ast::Attribute> + 'a
|
||||
= impl Iterator<Item = &'a hir::Attribute> + 'a
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
fn lists(&self, name: Symbol) -> Self::AttributeIterator<'_> {
|
||||
AttributesExt::iter(self)
|
||||
.filter(move |attr| attr.has_name(name))
|
||||
.filter_map(ast::Attribute::meta_item_list)
|
||||
.filter_map(hir::Attribute::meta_item_list)
|
||||
.flatten()
|
||||
}
|
||||
|
||||
|
|
@ -1152,7 +1150,7 @@ pub struct RenderedLink {
|
|||
#[derive(Clone, Debug, Default)]
|
||||
pub(crate) struct Attributes {
|
||||
pub(crate) doc_strings: Vec<DocFragment>,
|
||||
pub(crate) other_attrs: ast::AttrVec,
|
||||
pub(crate) other_attrs: Vec<hir::Attribute>,
|
||||
}
|
||||
|
||||
impl Attributes {
|
||||
|
|
@ -1180,22 +1178,22 @@ impl Attributes {
|
|||
self.has_doc_flag(sym::hidden)
|
||||
}
|
||||
|
||||
pub(crate) fn from_ast(attrs: &[ast::Attribute]) -> Attributes {
|
||||
Attributes::from_ast_iter(attrs.iter().map(|attr| (attr, None)), false)
|
||||
pub(crate) fn from_hir(attrs: &[hir::Attribute]) -> Attributes {
|
||||
Attributes::from_hir_iter(attrs.iter().map(|attr| (attr, None)), false)
|
||||
}
|
||||
|
||||
pub(crate) fn from_ast_with_additional(
|
||||
attrs: &[ast::Attribute],
|
||||
(additional_attrs, def_id): (&[ast::Attribute], DefId),
|
||||
pub(crate) fn from_hir_with_additional(
|
||||
attrs: &[hir::Attribute],
|
||||
(additional_attrs, def_id): (&[hir::Attribute], DefId),
|
||||
) -> Attributes {
|
||||
// Additional documentation should be shown before the original documentation.
|
||||
let attrs1 = additional_attrs.iter().map(|attr| (attr, Some(def_id)));
|
||||
let attrs2 = attrs.iter().map(|attr| (attr, None));
|
||||
Attributes::from_ast_iter(attrs1.chain(attrs2), false)
|
||||
Attributes::from_hir_iter(attrs1.chain(attrs2), false)
|
||||
}
|
||||
|
||||
pub(crate) fn from_ast_iter<'a>(
|
||||
attrs: impl Iterator<Item = (&'a ast::Attribute, Option<DefId>)>,
|
||||
pub(crate) fn from_hir_iter<'a>(
|
||||
attrs: impl Iterator<Item = (&'a hir::Attribute, Option<DefId>)>,
|
||||
doc_only: bool,
|
||||
) -> Attributes {
|
||||
let (doc_strings, other_attrs) = attrs_to_doc_fragments(attrs, doc_only);
|
||||
|
|
|
|||
|
|
@ -578,7 +578,7 @@ pub(crate) fn has_doc_flag(tcx: TyCtxt<'_>, did: DefId, flag: Symbol) -> bool {
|
|||
}
|
||||
|
||||
pub(crate) fn attrs_have_doc_flag<'a>(
|
||||
mut attrs: impl Iterator<Item = &'a ast::Attribute>,
|
||||
mut attrs: impl Iterator<Item = &'a hir::Attribute>,
|
||||
flag: Symbol,
|
||||
) -> bool {
|
||||
attrs
|
||||
|
|
|
|||
|
|
@ -13,10 +13,10 @@ use std::{panic, str};
|
|||
|
||||
pub(crate) use make::DocTestBuilder;
|
||||
pub(crate) use markdown::test as test_markdown;
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
|
||||
use rustc_errors::emitter::HumanReadableErrorType;
|
||||
use rustc_errors::{ColorConfig, DiagCtxtHandle};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::CRATE_HIR_ID;
|
||||
use rustc_hir::def_id::LOCAL_CRATE;
|
||||
use rustc_interface::interface;
|
||||
|
|
@ -325,7 +325,7 @@ pub(crate) fn run_tests(
|
|||
// Look for `#![doc(test(no_crate_inject))]`, used by crates in the std facade.
|
||||
fn scrape_test_config(
|
||||
crate_name: String,
|
||||
attrs: &[ast::Attribute],
|
||||
attrs: &[hir::Attribute],
|
||||
args_file: PathBuf,
|
||||
) -> GlobalTestOptions {
|
||||
use rustc_ast_pretty::pprust;
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ impl HirCollector<'_> {
|
|||
|
||||
// The collapse-docs pass won't combine sugared/raw doc attributes, or included files with
|
||||
// anything else, this will combine them for us.
|
||||
let attrs = Attributes::from_ast(ast_attrs);
|
||||
let attrs = Attributes::from_hir(ast_attrs);
|
||||
if let Some(doc) = attrs.opt_doc_value() {
|
||||
let span = span_of_fragments(&attrs.doc_strings).unwrap_or(sp);
|
||||
self.collector.position = if span.edition().at_least_rust_2024() {
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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 { value: AttrArgsEq::Ast(_), .. } = &normal_attr.item.args {
|
||||
if let AttrArgs::Eq { .. } = &normal_attr.item.args {
|
||||
// `#[should_panic = ".."]` found, good
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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 { value: 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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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('!')
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 { value: 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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<MetaItem>) -> 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");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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 { 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 { eq_span: _, expr: le }, Eq { eq_span: _, expr: re }) => eq_expr(le, re),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Item = &'a ast::Attribute> {
|
||||
) -> impl Iterator<Item = &'a A> {
|
||||
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<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &'static str, mut f: F) {
|
||||
fn parse_attrs<F: FnMut(u64)>(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))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<RustcVersion> {
|
||||
fn parse_attr(sess: &Session, attrs: &[impl AttributeExt]) -> Option<RustcVersion> {
|
||||
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();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue