Add hir::Attribute

This commit is contained in:
Jonathan Dönszelmann 2024-10-17 01:14:01 +02:00
parent 53b2c7cc95
commit d50c0a5480
No known key found for this signature in database
89 changed files with 1144 additions and 659 deletions

View file

@ -3521,6 +3521,7 @@ dependencies = [
"rustc_fluent_macro",
"rustc_fs_util",
"rustc_hir",
"rustc_hir_pretty",
"rustc_incremental",
"rustc_index",
"rustc_macros",
@ -3786,6 +3787,7 @@ dependencies = [
"rustc_span",
"rustc_target",
"smallvec",
"thin-vec",
"tracing",
]
@ -4454,9 +4456,9 @@ version = "0.0.0"
dependencies = [
"rustc_abi",
"rustc_ast",
"rustc_ast_pretty",
"rustc_data_structures",
"rustc_hir",
"rustc_hir_pretty",
"rustc_middle",
"rustc_session",
"rustc_span",

View file

@ -1759,7 +1759,7 @@ pub enum AttrArgs {
/// Span of the `=` token.
eq_span: Span,
expr: AttrArgsEq,
expr: P<Expr>,
},
}
@ -1804,7 +1804,7 @@ impl AttrArgs {
match self {
AttrArgs::Empty => None,
AttrArgs::Delimited(args) => Some(args.dspan.entire()),
AttrArgs::Eq { eq_span, expr } => Some(eq_span.to(expr.span())),
AttrArgs::Eq { eq_span, expr } => Some(eq_span.to(expr.span)),
}
}
@ -1814,7 +1814,7 @@ impl AttrArgs {
match self {
AttrArgs::Empty => TokenStream::default(),
AttrArgs::Delimited(args) => args.tokens.clone(),
AttrArgs::Eq { expr, .. } => TokenStream::from_ast(expr.unwrap_ast()),
AttrArgs::Eq { expr, .. } => TokenStream::from_ast(expr),
}
}
}
@ -1828,13 +1828,9 @@ where
match self {
AttrArgs::Empty => {}
AttrArgs::Delimited(args) => args.hash_stable(ctx, hasher),
AttrArgs::Eq { expr: AttrArgsEq::Ast(expr), .. } => {
AttrArgs::Eq { expr, .. } => {
unreachable!("hash_stable {:?}", expr);
}
AttrArgs::Eq { eq_span, expr: AttrArgsEq::Hir(lit) } => {
eq_span.hash_stable(ctx, hasher);
lit.hash_stable(ctx, hasher);
}
}
}
}

View file

@ -1,5 +1,6 @@
//! Functions dealing with attributes and meta items.
use std::fmt::Debug;
use std::iter;
use std::sync::atomic::{AtomicU32, Ordering};
@ -10,9 +11,9 @@ use smallvec::{SmallVec, smallvec};
use thin_vec::{ThinVec, thin_vec};
use crate::ast::{
AttrArgs, AttrArgsEq, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute, DUMMY_NODE_ID,
DelimArgs, Expr, ExprKind, LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit,
NormalAttr, Path, PathSegment, Safety,
AttrArgs, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute, DUMMY_NODE_ID, DelimArgs,
Expr, ExprKind, LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit, NormalAttr, Path,
PathSegment, Safety,
};
use crate::ptr::P;
use crate::token::{self, CommentKind, Delimiter, Token};
@ -66,11 +67,27 @@ impl Attribute {
AttrKind::DocComment(..) => panic!("unexpected doc comment"),
}
}
}
impl AttributeExt for Attribute {
fn id(&self) -> AttrId {
self.id
}
fn value_span(&self) -> Option<Span> {
match &self.kind {
AttrKind::Normal(normal) => match &normal.item.args {
AttrArgs::Eq { expr, .. } => Some(expr.span),
_ => None,
},
AttrKind::DocComment(..) => None,
}
}
/// Returns `true` if it is a sugared doc comment (`///` or `//!` for example).
/// So `#[doc = "doc"]` (which is a doc comment) and `#[doc(...)]` (which is not
/// a doc comment) will return `false`.
pub fn is_doc_comment(&self) -> bool {
fn is_doc_comment(&self) -> bool {
match self.kind {
AttrKind::Normal(..) => false,
AttrKind::DocComment(..) => true,
@ -78,7 +95,7 @@ impl Attribute {
}
/// For a single-segment attribute, returns its name; otherwise, returns `None`.
pub fn ident(&self) -> Option<Ident> {
fn ident(&self) -> Option<Ident> {
match &self.kind {
AttrKind::Normal(normal) => {
if let [ident] = &*normal.item.path.segments {
@ -91,28 +108,14 @@ impl Attribute {
}
}
pub fn name_or_empty(&self) -> Symbol {
self.ident().unwrap_or_else(Ident::empty).name
}
pub fn path(&self) -> SmallVec<[Symbol; 1]> {
fn ident_path(&self) -> Option<SmallVec<[Ident; 1]>> {
match &self.kind {
AttrKind::Normal(normal) => {
normal.item.path.segments.iter().map(|s| s.ident.name).collect()
}
AttrKind::DocComment(..) => smallvec![sym::doc],
AttrKind::Normal(p) => Some(p.item.path.segments.iter().map(|i| i.ident).collect()),
AttrKind::DocComment(_, _) => None,
}
}
#[inline]
pub fn has_name(&self, name: Symbol) -> bool {
match &self.kind {
AttrKind::Normal(normal) => normal.item.path == name,
AttrKind::DocComment(..) => false,
}
}
pub fn path_matches(&self, name: &[Symbol]) -> bool {
fn path_matches(&self, name: &[Symbol]) -> bool {
match &self.kind {
AttrKind::Normal(normal) => {
normal.item.path.segments.len() == name.len()
@ -128,7 +131,11 @@ impl Attribute {
}
}
pub fn is_word(&self) -> bool {
fn span(&self) -> Span {
self.span
}
fn is_word(&self) -> bool {
if let AttrKind::Normal(normal) = &self.kind {
matches!(normal.item.args, AttrArgs::Empty)
} else {
@ -143,7 +150,7 @@ impl Attribute {
/// #[attr = ""] // Returns `None`.
/// #[attr] // Returns `None`.
/// ```
pub fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>> {
fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>> {
match &self.kind {
AttrKind::Normal(normal) => normal.item.meta_item_list(),
AttrKind::DocComment(..) => None,
@ -165,7 +172,7 @@ impl Attribute {
/// ```text
/// #[attr("value")]
/// ```
pub fn value_str(&self) -> Option<Symbol> {
fn value_str(&self) -> Option<Symbol> {
match &self.kind {
AttrKind::Normal(normal) => normal.item.value_str(),
AttrKind::DocComment(..) => None,
@ -177,7 +184,7 @@ impl Attribute {
/// * `/** doc */` returns `Some(("doc", CommentKind::Block))`.
/// * `#[doc = "doc"]` returns `Some(("doc", CommentKind::Line))`.
/// * `#[doc(...)]` returns `None`.
pub fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
match &self.kind {
AttrKind::DocComment(kind, data) => Some((*data, *kind)),
AttrKind::Normal(normal) if normal.item.path == sym::doc => {
@ -191,7 +198,7 @@ impl Attribute {
/// * `///doc` returns `Some("doc")`.
/// * `#[doc = "doc"]` returns `Some("doc")`.
/// * `#[doc(...)]` returns `None`.
pub fn doc_str(&self) -> Option<Symbol> {
fn doc_str(&self) -> Option<Symbol> {
match &self.kind {
AttrKind::DocComment(.., data) => Some(*data),
AttrKind::Normal(normal) if normal.item.path == sym::doc => normal.item.value_str(),
@ -199,16 +206,16 @@ impl Attribute {
}
}
fn style(&self) -> AttrStyle {
self.style
}
}
impl Attribute {
pub fn may_have_doc_links(&self) -> bool {
self.doc_str().is_some_and(|s| comments::may_have_doc_links(s.as_str()))
}
pub fn is_proc_macro_attr(&self) -> bool {
[sym::proc_macro, sym::proc_macro_attribute, sym::proc_macro_derive]
.iter()
.any(|kind| self.has_name(*kind))
}
/// Extracts the MetaItem from inside this Attribute.
pub fn meta(&self) -> Option<MetaItem> {
match &self.kind {
@ -268,7 +275,12 @@ impl AttrItem {
/// ```
fn value_str(&self) -> Option<Symbol> {
match &self.args {
AttrArgs::Eq { expr, .. } => expr.value_str(),
AttrArgs::Eq { expr, .. } => match expr.kind {
ExprKind::Lit(token_lit) => {
LitKind::from_token_lit(token_lit).ok().and_then(|lit| lit.str())
}
_ => None,
},
AttrArgs::Delimited(_) | AttrArgs::Empty => None,
}
}
@ -287,20 +299,6 @@ impl AttrItem {
}
}
impl AttrArgsEq {
fn value_str(&self) -> Option<Symbol> {
match self {
AttrArgsEq::Ast(expr) => match expr.kind {
ExprKind::Lit(token_lit) => {
LitKind::from_token_lit(token_lit).ok().and_then(|lit| lit.str())
}
_ => None,
},
AttrArgsEq::Hir(lit) => lit.kind.str(),
}
}
}
impl MetaItem {
/// For a single-segment meta item, returns its name; otherwise, returns `None`.
pub fn ident(&self) -> Option<Ident> {
@ -439,7 +437,8 @@ impl MetaItem {
}
impl MetaItemKind {
fn list_from_tokens(tokens: TokenStream) -> Option<ThinVec<MetaItemInner>> {
// public because it can be called in the hir
pub fn list_from_tokens(tokens: TokenStream) -> Option<ThinVec<MetaItemInner>> {
let mut tokens = tokens.trees().peekable();
let mut result = ThinVec::new();
while tokens.peek().is_some() {
@ -492,7 +491,7 @@ impl MetaItemKind {
MetaItemKind::list_from_tokens(tokens.clone()).map(MetaItemKind::List)
}
AttrArgs::Delimited(..) => None,
AttrArgs::Eq { expr: AttrArgsEq::Ast(expr), .. } => match expr.kind {
AttrArgs::Eq { expr, .. } => match expr.kind {
ExprKind::Lit(token_lit) => {
// Turn failures to `None`, we'll get parse errors elsewhere.
MetaItemLit::from_token_lit(token_lit, expr.span)
@ -501,9 +500,6 @@ impl MetaItemKind {
}
_ => None,
},
AttrArgs::Eq { expr: AttrArgsEq::Hir(lit), .. } => {
Some(MetaItemKind::NameValue(lit.clone()))
}
}
}
}
@ -704,26 +700,175 @@ pub fn mk_attr_name_value_str(
tokens: None,
});
let path = Path::from_ident(Ident::new(name, span));
let args = AttrArgs::Eq { eq_span: span, expr: AttrArgsEq::Ast(expr) };
let args = AttrArgs::Eq { eq_span: span, expr };
mk_attr(g, style, unsafety, path, args, span)
}
pub fn filter_by_name(attrs: &[Attribute], name: Symbol) -> impl Iterator<Item = &Attribute> {
pub fn filter_by_name<A: AttributeExt>(attrs: &[A], name: Symbol) -> impl Iterator<Item = &A> {
attrs.iter().filter(move |attr| attr.has_name(name))
}
pub fn find_by_name(attrs: &[Attribute], name: Symbol) -> Option<&Attribute> {
pub fn find_by_name<A: AttributeExt>(attrs: &[A], name: Symbol) -> Option<&A> {
filter_by_name(attrs, name).next()
}
pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: Symbol) -> Option<Symbol> {
pub fn first_attr_value_str_by_name(attrs: &[impl AttributeExt], name: Symbol) -> Option<Symbol> {
find_by_name(attrs, name).and_then(|attr| attr.value_str())
}
pub fn contains_name(attrs: &[Attribute], name: Symbol) -> bool {
pub fn contains_name(attrs: &[impl AttributeExt], name: Symbol) -> bool {
find_by_name(attrs, name).is_some()
}
pub fn list_contains_name(items: &[MetaItemInner], name: Symbol) -> bool {
items.iter().any(|item| item.has_name(name))
}
impl MetaItemLit {
pub fn value_str(&self) -> Option<Symbol> {
LitKind::from_token_lit(self.as_token_lit()).ok().and_then(|lit| lit.str())
}
}
pub trait AttributeExt: Debug {
fn id(&self) -> AttrId;
fn name_or_empty(&self) -> Symbol {
self.ident().unwrap_or_else(Ident::empty).name
}
/// Get the meta item list, `#[attr(meta item list)]`
fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>>;
/// Gets the value literal, as string, when using `#[attr = value]`
fn value_str(&self) -> Option<Symbol>;
/// Gets the span of the value literal, as string, when using `#[attr = value]`
fn value_span(&self) -> Option<Span>;
/// For a single-segment attribute, returns its name; otherwise, returns `None`.
fn ident(&self) -> Option<Ident>;
/// Checks whether the path of this attribute matches the name.
///
/// Matches one segment of the path to each element in `name`
fn path_matches(&self, name: &[Symbol]) -> bool;
/// Returns `true` if it is a sugared doc comment (`///` or `//!` for example).
/// So `#[doc = "doc"]` (which is a doc comment) and `#[doc(...)]` (which is not
/// a doc comment) will return `false`.
fn is_doc_comment(&self) -> bool;
#[inline]
fn has_name(&self, name: Symbol) -> bool {
self.ident().map(|x| x.name == name).unwrap_or(false)
}
/// get the span of the entire attribute
fn span(&self) -> Span;
fn is_word(&self) -> bool;
fn path(&self) -> SmallVec<[Symbol; 1]> {
self.ident_path()
.map(|i| i.into_iter().map(|i| i.name).collect())
.unwrap_or(smallvec![sym::doc])
}
/// Returns None for doc comments
fn ident_path(&self) -> Option<SmallVec<[Ident; 1]>>;
/// Returns the documentation if this is a doc comment or a sugared doc comment.
/// * `///doc` returns `Some("doc")`.
/// * `#[doc = "doc"]` returns `Some("doc")`.
/// * `#[doc(...)]` returns `None`.
fn doc_str(&self) -> Option<Symbol>;
fn is_proc_macro_attr(&self) -> bool {
[sym::proc_macro, sym::proc_macro_attribute, sym::proc_macro_derive]
.iter()
.any(|kind| self.has_name(*kind))
}
/// Returns the documentation and its kind if this is a doc comment or a sugared doc comment.
/// * `///doc` returns `Some(("doc", CommentKind::Line))`.
/// * `/** doc */` returns `Some(("doc", CommentKind::Block))`.
/// * `#[doc = "doc"]` returns `Some(("doc", CommentKind::Line))`.
/// * `#[doc(...)]` returns `None`.
fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)>;
fn style(&self) -> AttrStyle;
}
// FIXME(fn_delegation): use function delegation instead of manually forwarding
impl Attribute {
pub fn id(&self) -> AttrId {
AttributeExt::id(self)
}
pub fn name_or_empty(&self) -> Symbol {
AttributeExt::name_or_empty(self)
}
pub fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>> {
AttributeExt::meta_item_list(self)
}
pub fn value_str(&self) -> Option<Symbol> {
AttributeExt::value_str(self)
}
pub fn value_span(&self) -> Option<Span> {
AttributeExt::value_span(self)
}
pub fn ident(&self) -> Option<Ident> {
AttributeExt::ident(self)
}
pub fn path_matches(&self, name: &[Symbol]) -> bool {
AttributeExt::path_matches(self, name)
}
pub fn is_doc_comment(&self) -> bool {
AttributeExt::is_doc_comment(self)
}
#[inline]
pub fn has_name(&self, name: Symbol) -> bool {
AttributeExt::has_name(self, name)
}
pub fn span(&self) -> Span {
AttributeExt::span(self)
}
pub fn is_word(&self) -> bool {
AttributeExt::is_word(self)
}
pub fn path(&self) -> SmallVec<[Symbol; 1]> {
AttributeExt::path(self)
}
pub fn ident_path(&self) -> Option<SmallVec<[Ident; 1]>> {
AttributeExt::ident_path(self)
}
pub fn doc_str(&self) -> Option<Symbol> {
AttributeExt::doc_str(self)
}
pub fn is_proc_macro_attr(&self) -> bool {
AttributeExt::is_proc_macro_attr(self)
}
pub fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
AttributeExt::doc_str_and_comment_kind(self)
}
pub fn style(&self) -> AttrStyle {
AttributeExt::style(self)
}
}

View file

@ -1,7 +1,7 @@
use rustc_span::Symbol;
use rustc_span::symbol::sym;
use crate::{Attribute, attr};
use crate::attr::{self, AttributeExt};
#[derive(Debug)]
pub enum EntryPointType {
@ -37,7 +37,7 @@ pub enum EntryPointType {
}
pub fn entry_point_type(
attrs: &[Attribute],
attrs: &[impl AttributeExt],
at_root: bool,
name: Option<Symbol>,
) -> EntryPointType {

View file

@ -44,20 +44,10 @@ pub mod token;
pub mod tokenstream;
pub mod visit;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
pub use self::ast::*;
pub use self::ast_traits::{AstDeref, AstNodeWrapper, HasAttrs, HasNodeId, HasTokens};
/// Requirements for a `StableHashingContext` to be used in this crate.
/// This is a hack to allow using the `HashStable_Generic` derive macro
/// instead of implementing everything in `rustc_middle`.
pub trait HashStableContext: rustc_span::HashStableContext {
fn hash_attr(&mut self, _: &ast::Attribute, hasher: &mut StableHasher);
}
impl<AstCtx: crate::HashStableContext> HashStable<AstCtx> for ast::Attribute {
fn hash_stable(&self, hcx: &mut AstCtx, hasher: &mut StableHasher) {
hcx.hash_attr(self, hasher)
}
}
pub trait HashStableContext: rustc_span::HashStableContext {}

View file

@ -452,7 +452,7 @@ fn visit_attr_args<T: MutVisitor>(vis: &mut T, args: &mut AttrArgs) {
AttrArgs::Empty => {}
AttrArgs::Delimited(args) => visit_delim_args(vis, args),
AttrArgs::Eq { eq_span, expr } => {
vis.visit_expr(expr.unwrap_ast_mut());
vis.visit_expr(expr);
vis.visit_span(eq_span);
}
}

View file

@ -1287,7 +1287,7 @@ pub fn walk_attr_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a AttrArgs) -
match args {
AttrArgs::Empty => {}
AttrArgs::Delimited(_args) => {}
AttrArgs::Eq { expr, .. } => try_visit!(visitor.visit_expr(expr.unwrap_ast())),
AttrArgs::Eq { expr, .. } => try_visit!(visitor.visit_expr(expr)),
}
V::Result::output()
}

View file

@ -176,7 +176,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
id: NodeId,
hir_id: hir::HirId,
ident: &mut Ident,
attrs: &'hir [Attribute],
attrs: &'hir [hir::Attribute],
vis_span: Span,
i: &ItemKind,
) -> hir::ItemKind<'hir> {
@ -467,7 +467,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
id: NodeId,
vis_span: Span,
ident: &mut Ident,
attrs: &'hir [Attribute],
attrs: &'hir [hir::Attribute],
) -> hir::ItemKind<'hir> {
let path = &tree.prefix;
let segments = prefix.segments.iter().chain(path.segments.iter()).cloned().collect();
@ -1392,7 +1392,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}
pub(super) fn lower_safety(&mut self, s: Safety, default: hir::Safety) -> hir::Safety {
pub(super) fn lower_safety(&self, s: Safety, default: hir::Safety) -> hir::Safety {
match s {
Safety::Unsafe(_) => hir::Safety::Unsafe,
Safety::Default => default,

View file

@ -41,7 +41,6 @@
// tidy-alphabetical-end
use rustc_ast::node_id::NodeMap;
use rustc_ast::ptr::P;
use rustc_ast::{self as ast, *};
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fingerprint::Fingerprint;
@ -96,7 +95,7 @@ struct LoweringContext<'a, 'hir> {
/// Bodies inside the owner being lowered.
bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>,
/// Attributes inside the owner being lowered.
attrs: SortedMap<hir::ItemLocalId, &'hir [Attribute]>,
attrs: SortedMap<hir::ItemLocalId, &'hir [hir::Attribute]>,
/// Collect items that were created by lowering the current owner.
children: Vec<(LocalDefId, hir::MaybeOwner<'hir>)>,
@ -847,7 +846,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
ret
}
fn lower_attrs(&mut self, id: HirId, attrs: &[Attribute]) -> &'hir [Attribute] {
fn lower_attrs(&mut self, id: HirId, attrs: &[Attribute]) -> &'hir [hir::Attribute] {
if attrs.is_empty() {
&[]
} else {
@ -859,25 +858,33 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}
fn lower_attr(&self, attr: &Attribute) -> Attribute {
fn lower_attr(&self, attr: &Attribute) -> hir::Attribute {
// Note that we explicitly do not walk the path. Since we don't really
// lower attributes (we use the AST version) there is nowhere to keep
// the `HirId`s. We don't actually need HIR version of attributes anyway.
// Tokens are also not needed after macro expansion and parsing.
let kind = match attr.kind {
AttrKind::Normal(ref normal) => AttrKind::Normal(P(NormalAttr {
item: AttrItem {
unsafety: normal.item.unsafety,
path: normal.item.path.clone(),
args: self.lower_attr_args(&normal.item.args),
tokens: None,
AttrKind::Normal(ref normal) => hir::AttrKind::Normal(Box::new(hir::AttrItem {
unsafety: self.lower_safety(normal.item.unsafety, hir::Safety::Safe),
path: hir::AttrPath {
segments: normal
.item
.path
.segments
.iter()
.map(|i| i.ident)
.collect::<Vec<_>>()
.into_boxed_slice(),
span: normal.item.path.span,
},
tokens: None,
args: self.lower_attr_args(&normal.item.args),
})),
AttrKind::DocComment(comment_kind, data) => AttrKind::DocComment(comment_kind, data),
AttrKind::DocComment(comment_kind, data) => {
hir::AttrKind::DocComment(comment_kind, data)
}
};
Attribute { kind, id: attr.id, style: attr.style, span: self.lower_span(attr.span) }
hir::Attribute { kind, id: attr.id, style: attr.style, span: self.lower_span(attr.span) }
}
fn alias_attrs(&mut self, id: HirId, target_id: HirId) {
@ -889,15 +896,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}
fn lower_attr_args(&self, args: &AttrArgs) -> AttrArgs {
fn lower_attr_args(&self, args: &AttrArgs) -> hir::AttrArgs {
match args {
AttrArgs::Empty => AttrArgs::Empty,
AttrArgs::Delimited(args) => AttrArgs::Delimited(self.lower_delim_args(args)),
AttrArgs::Empty => hir::AttrArgs::Empty,
AttrArgs::Delimited(args) => hir::AttrArgs::Delimited(self.lower_delim_args(args)),
// This is an inert key-value attribute - it will never be visible to macros
// after it gets lowered to HIR. Therefore, we can extract literals to handle
// nonterminals in `#[doc]` (e.g. `#[doc = $e]`).
&AttrArgs::Eq { eq_span, ref expr } => {
let expr = expr.unwrap_ast();
// In valid code the value always ends up as a single literal. Otherwise, a dummy
// literal suffices because the error is handled elsewhere.
let lit = if let ExprKind::Lit(token_lit) = expr.kind
@ -913,7 +919,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
span: DUMMY_SP,
}
};
AttrArgs::Eq { eq_span, expr: AttrArgsEq::Hir(lit) }
hir::AttrArgs::Eq { eq_span, expr: lit }
}
}
}
@ -2201,7 +2207,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn stmt_let_pat(
&mut self,
attrs: Option<&'hir [Attribute]>,
attrs: Option<&'hir [hir::Attribute]>,
span: Span,
init: Option<&'hir hir::Expr<'hir>>,
pat: &'hir hir::Pat<'hir>,

View file

@ -342,7 +342,7 @@ impl<'a> AstValidator<'a> {
sym::forbid,
sym::warn,
];
!arr.contains(&attr.name_or_empty()) && rustc_attr::is_builtin_attr(attr)
!arr.contains(&attr.name_or_empty()) && rustc_attr::is_builtin_attr(*attr)
})
.for_each(|attr| {
if attr.is_doc_comment() {

View file

@ -17,9 +17,9 @@ use rustc_ast::tokenstream::{Spacing, TokenStream, TokenTree};
use rustc_ast::util::classify;
use rustc_ast::util::comments::{Comment, CommentStyle};
use rustc_ast::{
self as ast, AttrArgs, AttrArgsEq, BindingMode, BlockCheckMode, ByRef, DelimArgs, GenericArg,
GenericBound, InlineAsmOperand, InlineAsmOptions, InlineAsmRegOrRegClass,
InlineAsmTemplatePiece, PatKind, RangeEnd, RangeSyntax, Safety, SelfKind, Term, attr,
self as ast, AttrArgs, BindingMode, BlockCheckMode, ByRef, DelimArgs, GenericArg, GenericBound,
InlineAsmOperand, InlineAsmOptions, InlineAsmRegOrRegClass, InlineAsmTemplatePiece, PatKind,
RangeEnd, RangeSyntax, Safety, SelfKind, Term, attr,
};
use rustc_data_structures::sync::Lrc;
use rustc_span::edition::Edition;
@ -359,7 +359,7 @@ fn binop_to_string(op: BinOpToken) -> &'static str {
}
}
fn doc_comment_to_string(
pub fn doc_comment_to_string(
comment_kind: CommentKind,
attr_style: ast::AttrStyle,
data: Symbol,
@ -648,20 +648,13 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
AttrArgs::Empty => {
self.print_path(&item.path, false, 0);
}
AttrArgs::Eq { expr: AttrArgsEq::Ast(expr), .. } => {
AttrArgs::Eq { expr, .. } => {
self.print_path(&item.path, false, 0);
self.space();
self.word_space("=");
let token_str = self.expr_to_string(expr);
self.word(token_str);
}
AttrArgs::Eq { expr: AttrArgsEq::Hir(lit), .. } => {
self.print_path(&item.path, false, 0);
self.space();
self.word_space("=");
let token_str = self.meta_item_lit_to_string(lit);
self.word(token_str);
}
}
match item.unsafety {
ast::Safety::Unsafe(_) => self.pclose(),

View file

@ -3,10 +3,8 @@
use std::num::NonZero;
use rustc_abi::Align;
use rustc_ast::{
self as ast, Attribute, LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit, NodeId,
attr,
};
use rustc_ast::attr::AttributeExt;
use rustc_ast::{self as ast, LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit, NodeId};
use rustc_ast_pretty::pprust;
use rustc_errors::ErrorGuaranteed;
use rustc_feature::{Features, GatedCfg, find_gated_cfg, is_builtin_attr_name};
@ -20,8 +18,8 @@ use rustc_span::Span;
use rustc_span::hygiene::Transparency;
use rustc_span::symbol::{Symbol, kw, sym};
use crate::fluent_generated;
use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
use crate::{filter_by_name, first_attr_value_str_by_name, fluent_generated};
/// The version placeholder that recently stabilized features contain inside the
/// `since` field of the `#[stable]` attribute.
@ -29,7 +27,7 @@ use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
/// For more, see [this pull request](https://github.com/rust-lang/rust/pull/100591).
pub const VERSION_PLACEHOLDER: &str = "CURRENT_RUSTC_VERSION";
pub fn is_builtin_attr(attr: &Attribute) -> bool {
pub fn is_builtin_attr(attr: &impl AttributeExt) -> bool {
attr.is_doc_comment() || attr.ident().is_some_and(|ident| is_builtin_attr_name(ident.name))
}
@ -215,7 +213,7 @@ impl UnstableReason {
/// attributes in `attrs`. Returns `None` if no stability attributes are found.
pub fn find_stability(
sess: &Session,
attrs: &[Attribute],
attrs: &[impl AttributeExt],
item_sp: Span,
) -> Option<(Stability, Span)> {
let mut stab: Option<(Stability, Span)> = None;
@ -226,23 +224,25 @@ pub fn find_stability(
sym::rustc_allowed_through_unstable_modules => allowed_through_unstable_modules = true,
sym::unstable => {
if stab.is_some() {
sess.dcx()
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
sess.dcx().emit_err(session_diagnostics::MultipleStabilityLevels {
span: attr.span(),
});
break;
}
if let Some((feature, level)) = parse_unstability(sess, attr) {
stab = Some((Stability { level, feature }, attr.span));
stab = Some((Stability { level, feature }, attr.span()));
}
}
sym::stable => {
if stab.is_some() {
sess.dcx()
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
sess.dcx().emit_err(session_diagnostics::MultipleStabilityLevels {
span: attr.span(),
});
break;
}
if let Some((feature, level)) = parse_stability(sess, attr) {
stab = Some((Stability { level, feature }, attr.span));
stab = Some((Stability { level, feature }, attr.span()));
}
}
_ => {}
@ -272,7 +272,7 @@ pub fn find_stability(
/// attributes in `attrs`. Returns `None` if no stability attributes are found.
pub fn find_const_stability(
sess: &Session,
attrs: &[Attribute],
attrs: &[impl AttributeExt],
item_sp: Span,
) -> Option<(ConstStability, Span)> {
let mut const_stab: Option<(ConstStability, Span)> = None;
@ -285,8 +285,9 @@ pub fn find_const_stability(
sym::rustc_const_stable_indirect => const_stable_indirect = true,
sym::rustc_const_unstable => {
if const_stab.is_some() {
sess.dcx()
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
sess.dcx().emit_err(session_diagnostics::MultipleStabilityLevels {
span: attr.span(),
});
break;
}
@ -298,14 +299,15 @@ pub fn find_const_stability(
const_stable_indirect: false,
promotable: false,
},
attr.span,
attr.span(),
));
}
}
sym::rustc_const_stable => {
if const_stab.is_some() {
sess.dcx()
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
sess.dcx().emit_err(session_diagnostics::MultipleStabilityLevels {
span: attr.span(),
});
break;
}
if let Some((feature, level)) = parse_stability(sess, attr) {
@ -316,7 +318,7 @@ pub fn find_const_stability(
const_stable_indirect: false,
promotable: false,
},
attr.span,
attr.span(),
));
}
}
@ -361,7 +363,7 @@ pub fn find_const_stability(
/// without the `staged_api` feature.
pub fn unmarked_crate_const_stab(
_sess: &Session,
attrs: &[Attribute],
attrs: &[impl AttributeExt],
regular_stab: Stability,
) -> ConstStability {
assert!(regular_stab.level.is_unstable());
@ -381,7 +383,7 @@ pub fn unmarked_crate_const_stab(
/// Returns `None` if no stability attributes are found.
pub fn find_body_stability(
sess: &Session,
attrs: &[Attribute],
attrs: &[impl AttributeExt],
) -> Option<(DefaultBodyStability, Span)> {
let mut body_stab: Option<(DefaultBodyStability, Span)> = None;
@ -389,12 +391,12 @@ pub fn find_body_stability(
if attr.has_name(sym::rustc_default_body_unstable) {
if body_stab.is_some() {
sess.dcx()
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span() });
break;
}
if let Some((feature, level)) = parse_unstability(sess, attr) {
body_stab = Some((DefaultBodyStability { level, feature }, attr.span));
body_stab = Some((DefaultBodyStability { level, feature }, attr.span()));
}
}
}
@ -420,9 +422,8 @@ fn insert_or_error(sess: &Session, meta: &MetaItem, item: &mut Option<Symbol>) -
/// Read the content of a `stable`/`rustc_const_stable` attribute, and return the feature name and
/// its stability information.
fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, StabilityLevel)> {
let meta = attr.meta()?;
let MetaItem { kind: MetaItemKind::List(ref metas), .. } = meta else { return None };
fn parse_stability(sess: &Session, attr: &impl AttributeExt) -> Option<(Symbol, StabilityLevel)> {
let metas = attr.meta_item_list()?;
let mut feature = None;
let mut since = None;
@ -454,9 +455,9 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit
let feature = match feature {
Some(feature) if rustc_lexer::is_ident(feature.as_str()) => Ok(feature),
Some(_bad_feature) => {
Err(sess.dcx().emit_err(session_diagnostics::NonIdentFeature { span: attr.span }))
Err(sess.dcx().emit_err(session_diagnostics::NonIdentFeature { span: attr.span() }))
}
None => Err(sess.dcx().emit_err(session_diagnostics::MissingFeature { span: attr.span })),
None => Err(sess.dcx().emit_err(session_diagnostics::MissingFeature { span: attr.span() })),
};
let since = if let Some(since) = since {
@ -465,11 +466,11 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit
} else if let Some(version) = parse_version(since) {
StableSince::Version(version)
} else {
sess.dcx().emit_err(session_diagnostics::InvalidSince { span: attr.span });
sess.dcx().emit_err(session_diagnostics::InvalidSince { span: attr.span() });
StableSince::Err
}
} else {
sess.dcx().emit_err(session_diagnostics::MissingSince { span: attr.span });
sess.dcx().emit_err(session_diagnostics::MissingSince { span: attr.span() });
StableSince::Err
};
@ -484,9 +485,8 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit
/// Read the content of a `unstable`/`rustc_const_unstable`/`rustc_default_body_unstable`
/// attribute, and return the feature name and its stability information.
fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, StabilityLevel)> {
let meta = attr.meta()?;
let MetaItem { kind: MetaItemKind::List(ref metas), .. } = meta else { return None };
fn parse_unstability(sess: &Session, attr: &impl AttributeExt) -> Option<(Symbol, StabilityLevel)> {
let metas = attr.meta_item_list()?;
let mut feature = None;
let mut reason = None;
@ -553,13 +553,14 @@ fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabil
let feature = match feature {
Some(feature) if rustc_lexer::is_ident(feature.as_str()) => Ok(feature),
Some(_bad_feature) => {
Err(sess.dcx().emit_err(session_diagnostics::NonIdentFeature { span: attr.span }))
Err(sess.dcx().emit_err(session_diagnostics::NonIdentFeature { span: attr.span() }))
}
None => Err(sess.dcx().emit_err(session_diagnostics::MissingFeature { span: attr.span })),
None => Err(sess.dcx().emit_err(session_diagnostics::MissingFeature { span: attr.span() })),
};
let issue = issue
.ok_or_else(|| sess.dcx().emit_err(session_diagnostics::MissingIssue { span: attr.span }));
let issue = issue.ok_or_else(|| {
sess.dcx().emit_err(session_diagnostics::MissingIssue { span: attr.span() })
});
match (feature, issue) {
(Ok(feature), Ok(_)) => {
@ -575,8 +576,8 @@ fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabil
}
}
pub fn find_crate_name(attrs: &[Attribute]) -> Option<Symbol> {
attr::first_attr_value_str_by_name(attrs, sym::crate_name)
pub fn find_crate_name(attrs: &[impl AttributeExt]) -> Option<Symbol> {
first_attr_value_str_by_name(attrs, sym::crate_name)
}
#[derive(Clone, Debug)]
@ -884,7 +885,7 @@ impl Deprecation {
pub fn find_deprecation(
sess: &Session,
features: &Features,
attrs: &[Attribute],
attrs: &[impl AttributeExt],
) -> Option<(Deprecation, Span)> {
let mut depr: Option<(Deprecation, Span)> = None;
let is_rustc = features.staged_api();
@ -894,98 +895,97 @@ pub fn find_deprecation(
continue;
}
let Some(meta) = attr.meta() else {
continue;
};
let mut since = None;
let mut note = None;
let mut suggestion = None;
match &meta.kind {
MetaItemKind::Word => {}
MetaItemKind::NameValue(..) => note = meta.value_str(),
MetaItemKind::List(list) => {
let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
if item.is_some() {
sess.dcx().emit_err(session_diagnostics::MultipleItem {
span: meta.span,
item: pprust::path_to_string(&meta.path),
if attr.is_doc_comment() {
continue;
} else if attr.is_word() {
} else if let Some(value) = attr.value_str() {
note = Some(value)
} else if let Some(list) = attr.meta_item_list() {
let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
if item.is_some() {
sess.dcx().emit_err(session_diagnostics::MultipleItem {
span: meta.span,
item: pprust::path_to_string(&meta.path),
});
return false;
}
if let Some(v) = meta.value_str() {
*item = Some(v);
true
} else {
if let Some(lit) = meta.name_value_literal() {
sess.dcx().emit_err(session_diagnostics::UnsupportedLiteral {
span: lit.span,
reason: UnsupportedLiteralReason::DeprecatedString,
is_bytestr: lit.kind.is_bytestr(),
start_point_span: sess.source_map().start_point(lit.span),
});
return false;
}
if let Some(v) = meta.value_str() {
*item = Some(v);
true
} else {
if let Some(lit) = meta.name_value_literal() {
sess.dcx().emit_err(session_diagnostics::UnsupportedLiteral {
span: lit.span,
reason: UnsupportedLiteralReason::DeprecatedString,
is_bytestr: lit.kind.is_bytestr(),
start_point_span: sess.source_map().start_point(lit.span),
});
} else {
sess.dcx().emit_err(session_diagnostics::IncorrectMetaItem {
span: meta.span,
});
}
false
sess.dcx()
.emit_err(session_diagnostics::IncorrectMetaItem { span: meta.span });
}
};
false
}
};
for meta in list {
match meta {
MetaItemInner::MetaItem(mi) => match mi.name_or_empty() {
sym::since => {
if !get(mi, &mut since) {
continue 'outer;
}
}
sym::note => {
if !get(mi, &mut note) {
continue 'outer;
}
}
sym::suggestion => {
if !features.deprecated_suggestion() {
sess.dcx().emit_err(
session_diagnostics::DeprecatedItemSuggestion {
span: mi.span,
is_nightly: sess.is_nightly_build(),
details: (),
},
);
}
if !get(mi, &mut suggestion) {
continue 'outer;
}
}
_ => {
sess.dcx().emit_err(session_diagnostics::UnknownMetaItem {
span: meta.span(),
item: pprust::path_to_string(&mi.path),
expected: if features.deprecated_suggestion() {
&["since", "note", "suggestion"]
} else {
&["since", "note"]
},
});
for meta in &list {
match meta {
MetaItemInner::MetaItem(mi) => match mi.name_or_empty() {
sym::since => {
if !get(mi, &mut since) {
continue 'outer;
}
},
MetaItemInner::Lit(lit) => {
sess.dcx().emit_err(session_diagnostics::UnsupportedLiteral {
span: lit.span,
reason: UnsupportedLiteralReason::DeprecatedKvPair,
is_bytestr: false,
start_point_span: sess.source_map().start_point(lit.span),
}
sym::note => {
if !get(mi, &mut note) {
continue 'outer;
}
}
sym::suggestion => {
if !features.deprecated_suggestion() {
sess.dcx().emit_err(
session_diagnostics::DeprecatedItemSuggestion {
span: mi.span,
is_nightly: sess.is_nightly_build(),
details: (),
},
);
}
if !get(mi, &mut suggestion) {
continue 'outer;
}
}
_ => {
sess.dcx().emit_err(session_diagnostics::UnknownMetaItem {
span: meta.span(),
item: pprust::path_to_string(&mi.path),
expected: if features.deprecated_suggestion() {
&["since", "note", "suggestion"]
} else {
&["since", "note"]
},
});
continue 'outer;
}
},
MetaItemInner::Lit(lit) => {
sess.dcx().emit_err(session_diagnostics::UnsupportedLiteral {
span: lit.span,
reason: UnsupportedLiteralReason::DeprecatedKvPair,
is_bytestr: false,
start_point_span: sess.source_map().start_point(lit.span),
});
continue 'outer;
}
}
}
} else {
continue;
}
let since = if let Some(since) = since {
@ -996,22 +996,22 @@ pub fn find_deprecation(
} else if let Some(version) = parse_version(since) {
DeprecatedSince::RustcVersion(version)
} else {
sess.dcx().emit_err(session_diagnostics::InvalidSince { span: attr.span });
sess.dcx().emit_err(session_diagnostics::InvalidSince { span: attr.span() });
DeprecatedSince::Err
}
} else if is_rustc {
sess.dcx().emit_err(session_diagnostics::MissingSince { span: attr.span });
sess.dcx().emit_err(session_diagnostics::MissingSince { span: attr.span() });
DeprecatedSince::Err
} else {
DeprecatedSince::Unspecified
};
if is_rustc && note.is_none() {
sess.dcx().emit_err(session_diagnostics::MissingNote { span: attr.span });
sess.dcx().emit_err(session_diagnostics::MissingNote { span: attr.span() });
continue;
}
depr = Some((Deprecation { since, note, suggestion }, attr.span));
depr = Some((Deprecation { since, note, suggestion }, attr.span()));
}
depr
@ -1054,11 +1054,11 @@ impl IntType {
/// the same discriminant size that the corresponding C enum would or C
/// structure layout, `packed` to remove padding, and `transparent` to delegate representation
/// concerns to the only non-ZST field.
pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
pub fn find_repr_attrs(sess: &Session, attr: &impl AttributeExt) -> Vec<ReprAttr> {
if attr.has_name(sym::repr) { parse_repr_attr(sess, attr) } else { Vec::new() }
}
pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
pub fn parse_repr_attr(sess: &Session, attr: &impl AttributeExt) -> Vec<ReprAttr> {
assert!(attr.has_name(sym::repr), "expected `#[repr(..)]`, found: {attr:?}");
use ReprAttr::*;
let mut acc = Vec::new();
@ -1238,7 +1238,7 @@ pub enum TransparencyError {
}
pub fn find_transparency(
attrs: &[Attribute],
attrs: &[impl AttributeExt],
macro_rules: bool,
) -> (Transparency, Option<TransparencyError>) {
let mut transparency = None;
@ -1246,7 +1246,7 @@ pub fn find_transparency(
for attr in attrs {
if attr.has_name(sym::rustc_macro_transparency) {
if let Some((_, old_span)) = transparency {
error = Some(TransparencyError::MultipleTransparencyAttrs(old_span, attr.span));
error = Some(TransparencyError::MultipleTransparencyAttrs(old_span, attr.span()));
break;
} else if let Some(value) = attr.value_str() {
transparency = Some((
@ -1255,11 +1255,12 @@ pub fn find_transparency(
sym::semitransparent => Transparency::SemiTransparent,
sym::opaque => Transparency::Opaque,
_ => {
error = Some(TransparencyError::UnknownTransparency(value, attr.span));
error =
Some(TransparencyError::UnknownTransparency(value, attr.span()));
continue;
}
},
attr.span,
attr.span(),
));
}
}
@ -1270,29 +1271,29 @@ pub fn find_transparency(
pub fn allow_internal_unstable<'a>(
sess: &'a Session,
attrs: &'a [Attribute],
attrs: &'a [impl AttributeExt],
) -> impl Iterator<Item = Symbol> + 'a {
allow_unstable(sess, attrs, sym::allow_internal_unstable)
}
pub fn rustc_allow_const_fn_unstable<'a>(
sess: &'a Session,
attrs: &'a [Attribute],
attrs: &'a [impl AttributeExt],
) -> impl Iterator<Item = Symbol> + 'a {
allow_unstable(sess, attrs, sym::rustc_allow_const_fn_unstable)
}
fn allow_unstable<'a>(
sess: &'a Session,
attrs: &'a [Attribute],
attrs: &'a [impl AttributeExt],
symbol: Symbol,
) -> impl Iterator<Item = Symbol> + 'a {
let attrs = attr::filter_by_name(attrs, symbol);
let attrs = filter_by_name(attrs, symbol);
let list = attrs
.filter_map(move |attr| {
attr.meta_item_list().or_else(|| {
sess.dcx().emit_err(session_diagnostics::ExpectsFeatureList {
span: attr.span,
span: attr.span(),
name: symbol.to_ident_string(),
});
None
@ -1332,9 +1333,8 @@ pub fn parse_alignment(node: &ast::LitKind) -> Result<Align, &'static str> {
}
/// Read the content of a `rustc_confusables` attribute, and return the list of candidate names.
pub fn parse_confusables(attr: &Attribute) -> Option<Vec<Symbol>> {
let meta = attr.meta()?;
let MetaItem { kind: MetaItemKind::List(ref metas), .. } = meta else { return None };
pub fn parse_confusables(attr: &impl AttributeExt) -> Option<Vec<Symbol>> {
let metas = attr.meta_item_list()?;
let mut candidates = Vec::new();

View file

@ -23,6 +23,7 @@ rustc_errors = { path = "../rustc_errors" }
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_fs_util = { path = "../rustc_fs_util" }
rustc_hir = { path = "../rustc_hir" }
rustc_hir_pretty = { path = "../rustc_hir_pretty" }
rustc_incremental = { path = "../rustc_incremental" }
rustc_index = { path = "../rustc_index" }
rustc_macros = { path = "../rustc_macros" }

View file

@ -26,9 +26,9 @@
use std::borrow::Cow;
use std::fmt;
use rustc_ast as ast;
use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_errors::{DiagArgValue, IntoDiagArg};
use rustc_hir as hir;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::mir::mono::CodegenUnitNameBuilder;
use rustc_middle::ty::TyCtxt;
@ -77,7 +77,7 @@ struct AssertModuleSource<'tcx> {
}
impl<'tcx> AssertModuleSource<'tcx> {
fn check_attr(&mut self, attr: &ast::Attribute) {
fn check_attr(&mut self, attr: &hir::Attribute) {
let (expected_reuse, comp_kind) = if attr.has_name(sym::rustc_partition_reused) {
(CguReuse::PreLto, ComparisonKind::AtLeast)
} else if attr.has_name(sym::rustc_partition_codegened) {
@ -158,7 +158,7 @@ impl<'tcx> AssertModuleSource<'tcx> {
);
}
fn field(&self, attr: &ast::Attribute, name: Symbol) -> Symbol {
fn field(&self, attr: &hir::Attribute, name: Symbol) -> Symbol {
for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) {
if item.has_name(name) {
if let Some(value) = item.value_str() {
@ -177,7 +177,7 @@ impl<'tcx> AssertModuleSource<'tcx> {
/// Scan for a `cfg="foo"` attribute and check whether we have a
/// cfg flag called `foo`.
fn check_config(&self, attr: &ast::Attribute) -> bool {
fn check_config(&self, attr: &hir::Attribute) -> bool {
let config = &self.tcx.sess.psess.config;
let value = self.field(attr, sym::cfg);
debug!("check_config(config={:?}, value={:?})", config, value);

View file

@ -1,4 +1,4 @@
use rustc_ast::{MetaItemInner, MetaItemKind, ast, attr};
use rustc_ast::{MetaItemInner, attr};
use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr, list_contains_name};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::codes::*;
@ -6,7 +6,7 @@ use rustc_errors::{DiagMessage, SubdiagMessage, struct_span_code_err};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
use rustc_hir::{HirId, LangItem, lang_items};
use rustc_hir::{self as hir, HirId, LangItem, lang_items};
use rustc_middle::middle::codegen_fn_attrs::{
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry,
};
@ -525,28 +525,26 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
if !attr.has_name(sym::inline) {
return ia;
}
match attr.meta_kind() {
Some(MetaItemKind::Word) => InlineAttr::Hint,
Some(MetaItemKind::List(ref items)) => {
inline_span = Some(attr.span);
if items.len() != 1 {
struct_span_code_err!(tcx.dcx(), attr.span, E0534, "expected one argument")
.emit();
InlineAttr::None
} else if list_contains_name(items, sym::always) {
InlineAttr::Always
} else if list_contains_name(items, sym::never) {
InlineAttr::Never
} else {
struct_span_code_err!(tcx.dcx(), items[0].span(), E0535, "invalid argument")
.with_help("valid inline arguments are `always` and `never`")
.emit();
if attr.is_word() {
InlineAttr::Hint
} else if let Some(ref items) = attr.meta_item_list() {
inline_span = Some(attr.span);
if items.len() != 1 {
struct_span_code_err!(tcx.dcx(), attr.span, E0534, "expected one argument").emit();
InlineAttr::None
} else if list_contains_name(items, sym::always) {
InlineAttr::Always
} else if list_contains_name(items, sym::never) {
InlineAttr::Never
} else {
struct_span_code_err!(tcx.dcx(), items[0].span(), E0535, "invalid argument")
.with_help("valid inline arguments are `always` and `never`")
.emit();
InlineAttr::None
}
InlineAttr::None
}
Some(MetaItemKind::NameValue(_)) => ia,
None => ia,
} else {
ia
}
});
@ -562,27 +560,24 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
return ia;
}
let err = |sp, s| struct_span_code_err!(tcx.dcx(), sp, E0722, "{}", s).emit();
match attr.meta_kind() {
Some(MetaItemKind::Word) => {
if attr.is_word() {
err(attr.span, "expected one argument");
ia
} else if let Some(ref items) = attr.meta_item_list() {
inline_span = Some(attr.span);
if items.len() != 1 {
err(attr.span, "expected one argument");
ia
OptimizeAttr::None
} else if list_contains_name(items, sym::size) {
OptimizeAttr::Size
} else if list_contains_name(items, sym::speed) {
OptimizeAttr::Speed
} else {
err(items[0].span(), "invalid argument");
OptimizeAttr::None
}
Some(MetaItemKind::List(ref items)) => {
inline_span = Some(attr.span);
if items.len() != 1 {
err(attr.span, "expected one argument");
OptimizeAttr::None
} else if list_contains_name(items, sym::size) {
OptimizeAttr::Size
} else if list_contains_name(items, sym::speed) {
OptimizeAttr::Speed
} else {
err(items[0].span(), "invalid argument");
OptimizeAttr::None
}
}
Some(MetaItemKind::NameValue(_)) => ia,
None => ia,
} else {
OptimizeAttr::None
}
});
@ -730,7 +725,7 @@ fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
false
}
fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> {
fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &hir::Attribute) -> Option<u16> {
use rustc_ast::{LitIntType, LitKind, MetaItemLit};
let meta_item_list = attr.meta_item_list();
let meta_item_list = meta_item_list.as_deref();
@ -795,7 +790,7 @@ struct MixedExportNameAndNoMangleState<'a> {
export_name: Option<Span>,
hir_id: Option<HirId>,
no_mangle: Option<Span>,
no_mangle_attr: Option<&'a ast::Attribute>,
no_mangle_attr: Option<&'a hir::Attribute>,
}
impl<'a> MixedExportNameAndNoMangleState<'a> {
@ -803,7 +798,7 @@ impl<'a> MixedExportNameAndNoMangleState<'a> {
self.export_name = Some(span);
}
fn track_no_mangle(&mut self, span: Span, hir_id: HirId, attr_name: &'a ast::Attribute) {
fn track_no_mangle(&mut self, span: Span, hir_id: HirId, attr_name: &'a hir::Attribute) {
self.no_mangle = Some(span);
self.hir_id = Some(hir_id);
self.no_mangle_attr = Some(attr_name);
@ -824,7 +819,7 @@ impl<'a> MixedExportNameAndNoMangleState<'a> {
no_mangle,
errors::MixedExportNameAndNoMangle {
no_mangle,
no_mangle_attr: rustc_ast_pretty::pprust::attribute_to_string(no_mangle_attr),
no_mangle_attr: rustc_hir_pretty::attribute_to_string(&tcx, no_mangle_attr),
export_name,
removal_span: no_mangle,
},

View file

@ -1,8 +1,8 @@
use rustc_ast::ast;
use rustc_attr::InstructionSetAttr;
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
use rustc_middle::middle::codegen_fn_attrs::TargetFeature;
@ -19,7 +19,7 @@ use crate::errors;
/// Enabled target features are added to `target_features`.
pub(crate) fn from_target_feature_attr(
tcx: TyCtxt<'_>,
attr: &ast::Attribute,
attr: &hir::Attribute,
rust_target_features: &UnordMap<String, target_features::StabilityComputed>,
target_features: &mut Vec<TargetFeature>,
) {

View file

@ -4,7 +4,7 @@ use std::path::Component::Prefix;
use std::path::{Path, PathBuf};
use std::rc::Rc;
use rustc_ast::attr::MarkedAttrs;
use rustc_ast::attr::{AttributeExt, MarkedAttrs};
use rustc_ast::ptr::P;
use rustc_ast::token::Nonterminal;
use rustc_ast::tokenstream::TokenStream;
@ -782,10 +782,12 @@ impl SyntaxExtension {
}
}
fn collapse_debuginfo_by_name(attr: &Attribute) -> Result<CollapseMacroDebuginfo, Span> {
fn collapse_debuginfo_by_name(
attr: &impl AttributeExt,
) -> Result<CollapseMacroDebuginfo, Span> {
let list = attr.meta_item_list();
let Some([MetaItemInner::MetaItem(item)]) = list.as_deref() else {
return Err(attr.span);
return Err(attr.span());
};
if !item.is_word() {
return Err(item.span);
@ -805,7 +807,7 @@ impl SyntaxExtension {
/// | (unspecified) | no | if-ext | if-ext | yes |
/// | external | no | if-ext | if-ext | yes |
/// | yes | yes | yes | yes | yes |
fn get_collapse_debuginfo(sess: &Session, attrs: &[ast::Attribute], ext: bool) -> bool {
fn get_collapse_debuginfo(sess: &Session, attrs: &[impl AttributeExt], ext: bool) -> bool {
let flag = sess.opts.cg.collapse_macro_debuginfo;
let attr = attr::find_by_name(attrs, sym::collapse_debuginfo)
.and_then(|attr| {
@ -842,11 +844,11 @@ impl SyntaxExtension {
helper_attrs: Vec<Symbol>,
edition: Edition,
name: Symbol,
attrs: &[ast::Attribute],
attrs: &[impl AttributeExt],
is_local: bool,
) -> SyntaxExtension {
let allow_internal_unstable =
attr::allow_internal_unstable(sess, attrs).collect::<Vec<Symbol>>();
rustc_attr::allow_internal_unstable(sess, attrs).collect::<Vec<Symbol>>();
let allow_internal_unsafe = attr::contains_name(attrs, sym::allow_internal_unsafe);
let local_inner_macros = attr::find_by_name(attrs, sym::macro_export)
@ -1305,7 +1307,7 @@ pub fn resolve_path(sess: &Session, path: impl Into<PathBuf>, span: Span) -> PRe
pub fn parse_macro_name_and_helper_attrs(
dcx: DiagCtxtHandle<'_>,
attr: &Attribute,
attr: &impl AttributeExt,
macro_type: &str,
) -> Option<(Symbol, Vec<Symbol>)> {
// Once we've located the `#[proc_macro_derive]` attribute, verify
@ -1313,7 +1315,7 @@ pub fn parse_macro_name_and_helper_attrs(
// `#[proc_macro_derive(Foo, attributes(A, ..))]`
let list = attr.meta_item_list()?;
let ([trait_attr] | [trait_attr, _]) = list.as_slice() else {
dcx.emit_err(errors::AttrNoArguments { span: attr.span });
dcx.emit_err(errors::AttrNoArguments { span: attr.span() });
return None;
};
let Some(trait_attr) = trait_attr.meta_item() else {

View file

@ -9,7 +9,7 @@ use rustc_ast::token::{self, Delimiter, NonterminalKind, Token, TokenKind};
use rustc_ast::tokenstream::{DelimSpan, TokenStream};
use rustc_ast::{self as ast, DUMMY_NODE_ID, NodeId};
use rustc_ast_pretty::pprust;
use rustc_attr::{self as attr, TransparencyError};
use rustc_attr::{self as attr, AttributeExt, TransparencyError};
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_errors::{Applicability, ErrorGuaranteed};
use rustc_feature::Features;
@ -371,7 +371,7 @@ pub fn compile_declarative_macro(
features: &Features,
macro_def: &ast::MacroDef,
ident: Ident,
attrs: &[ast::Attribute],
attrs: &[impl AttributeExt],
span: Span,
node_id: NodeId,
edition: Edition,

View file

@ -16,5 +16,6 @@ rustc_serialize = { path = "../rustc_serialize" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
thin-vec = "0.2.12"
tracing = "0.1"
# tidy-alphabetical-end

View file

@ -6,7 +6,7 @@ macro_rules! arena_types {
$macro!([
// HIR types
[] asm_template: rustc_ast::InlineAsmTemplatePiece,
[] attribute: rustc_ast::Attribute,
[] attribute: rustc_hir::Attribute,
[] owner_info: rustc_hir::OwnerInfo<'tcx>,
[] use_path: rustc_hir::UsePath<'tcx>,
[] lit: rustc_hir::Lit,

View file

@ -1,10 +1,13 @@
use std::fmt;
use rustc_abi::ExternAbi;
// ignore-tidy-filelength
use rustc_ast::attr::AttributeExt;
use rustc_ast::token::CommentKind;
use rustc_ast::util::parser::{AssocOp, ExprPrecedence};
use rustc_ast::{
self as ast, Attribute, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece, IntTy, Label,
LitKind, TraitObjectSyntax, UintTy,
self as ast, AttrId, AttrStyle, DelimArgs, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece,
IntTy, Label, LitKind, MetaItemInner, MetaItemLit, TraitObjectSyntax, UintTy,
};
pub use rustc_ast::{
BinOp, BinOpKind, BindingMode, BorrowKind, BoundConstness, BoundPolarity, ByRef, CaptureBy,
@ -21,6 +24,7 @@ use rustc_span::symbol::{Ident, Symbol, kw, sym};
use rustc_span::{BytePos, DUMMY_SP, ErrorGuaranteed, Span};
use rustc_target::asm::InlineAsmRegOrRegClass;
use smallvec::SmallVec;
use thin_vec::ThinVec;
use tracing::debug;
use crate::LangItem;
@ -937,6 +941,250 @@ pub struct ParentedNode<'tcx> {
pub node: Node<'tcx>,
}
/// Arguments passed to an attribute macro.
#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable)]
pub enum AttrArgs {
/// No arguments: `#[attr]`.
Empty,
/// Delimited arguments: `#[attr()/[]/{}]`.
Delimited(DelimArgs),
/// Arguments of a key-value attribute: `#[attr = "value"]`.
Eq {
/// Span of the `=` token.
eq_span: Span,
/// The "value".
expr: MetaItemLit,
},
}
#[derive(Clone, Debug, Encodable, Decodable)]
pub enum AttrKind {
/// A normal attribute.
Normal(Box<AttrItem>),
/// A doc comment (e.g. `/// ...`, `//! ...`, `/** ... */`, `/*! ... */`).
/// Doc attributes (e.g. `#[doc="..."]`) are represented with the `Normal`
/// variant (which is much less compact and thus more expensive).
DocComment(CommentKind, Symbol),
}
#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable)]
pub struct AttrPath {
pub segments: Box<[Ident]>,
pub span: Span,
}
#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable)]
pub struct AttrItem {
pub unsafety: Safety,
// Not lowered to hir::Path because we have no NodeId to resolve to.
pub path: AttrPath,
pub args: AttrArgs,
}
#[derive(Clone, Debug, Encodable, Decodable)]
pub struct Attribute {
pub kind: AttrKind,
pub id: AttrId,
/// Denotes if the attribute decorates the following construct (outer)
/// or the construct this attribute is contained within (inner).
pub style: AttrStyle,
pub span: Span,
}
impl Attribute {
pub fn get_normal_item(&self) -> &AttrItem {
match &self.kind {
AttrKind::Normal(normal) => &normal,
AttrKind::DocComment(..) => panic!("unexpected doc comment"),
}
}
pub fn unwrap_normal_item(self) -> AttrItem {
match self.kind {
AttrKind::Normal(normal) => *normal,
AttrKind::DocComment(..) => panic!("unexpected doc comment"),
}
}
pub fn value_lit(&self) -> Option<&MetaItemLit> {
match &self.kind {
AttrKind::Normal(n) => match n.as_ref() {
AttrItem { args: AttrArgs::Eq { expr, .. }, .. } => Some(expr),
_ => None,
},
_ => None,
}
}
}
impl AttributeExt for Attribute {
fn id(&self) -> AttrId {
self.id
}
fn meta_item_list(&self) -> Option<ThinVec<ast::MetaItemInner>> {
match &self.kind {
AttrKind::Normal(n) => match n.as_ref() {
AttrItem { args: AttrArgs::Delimited(d), .. } => {
ast::MetaItemKind::list_from_tokens(d.tokens.clone())
}
_ => None,
},
_ => None,
}
}
fn value_str(&self) -> Option<Symbol> {
self.value_lit().and_then(|x| x.value_str())
}
fn value_span(&self) -> Option<Span> {
self.value_lit().map(|i| i.span)
}
/// For a single-segment attribute, returns its name; otherwise, returns `None`.
fn ident(&self) -> Option<Ident> {
match &self.kind {
AttrKind::Normal(n) => {
if let [ident] = n.path.segments.as_ref() {
Some(*ident)
} else {
None
}
}
AttrKind::DocComment(..) => None,
}
}
fn path_matches(&self, name: &[Symbol]) -> bool {
match &self.kind {
AttrKind::Normal(n) => {
n.path.segments.len() == name.len()
&& n.path.segments.iter().zip(name).all(|(s, n)| s.name == *n)
}
AttrKind::DocComment(..) => false,
}
}
fn is_doc_comment(&self) -> bool {
matches!(self.kind, AttrKind::DocComment(..))
}
fn span(&self) -> Span {
self.span
}
fn is_word(&self) -> bool {
match &self.kind {
AttrKind::Normal(n) => {
matches!(n.args, AttrArgs::Empty)
}
AttrKind::DocComment(..) => false,
}
}
fn ident_path(&self) -> Option<SmallVec<[Ident; 1]>> {
match &self.kind {
AttrKind::Normal(n) => Some(n.path.segments.iter().copied().collect()),
AttrKind::DocComment(..) => None,
}
}
fn doc_str(&self) -> Option<Symbol> {
match &self.kind {
AttrKind::DocComment(.., data) => Some(*data),
AttrKind::Normal(_) if self.has_name(sym::doc) => self.value_str(),
_ => None,
}
}
fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
match &self.kind {
AttrKind::DocComment(kind, data) => Some((*data, *kind)),
AttrKind::Normal(_) if self.name_or_empty() == sym::doc => {
self.value_str().map(|s| (s, CommentKind::Line))
}
_ => None,
}
}
fn style(&self) -> AttrStyle {
self.style
}
}
// FIXME(fn_delegation): use function delegation instead of manually forwarding
impl Attribute {
pub fn id(&self) -> AttrId {
AttributeExt::id(self)
}
pub fn name_or_empty(&self) -> Symbol {
AttributeExt::name_or_empty(self)
}
pub fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>> {
AttributeExt::meta_item_list(self)
}
pub fn value_str(&self) -> Option<Symbol> {
AttributeExt::value_str(self)
}
pub fn value_span(&self) -> Option<Span> {
AttributeExt::value_span(self)
}
pub fn ident(&self) -> Option<Ident> {
AttributeExt::ident(self)
}
pub fn path_matches(&self, name: &[Symbol]) -> bool {
AttributeExt::path_matches(self, name)
}
pub fn is_doc_comment(&self) -> bool {
AttributeExt::is_doc_comment(self)
}
#[inline]
pub fn has_name(&self, name: Symbol) -> bool {
AttributeExt::has_name(self, name)
}
pub fn span(&self) -> Span {
AttributeExt::span(self)
}
pub fn is_word(&self) -> bool {
AttributeExt::is_word(self)
}
pub fn path(&self) -> SmallVec<[Symbol; 1]> {
AttributeExt::path(self)
}
pub fn ident_path(&self) -> Option<SmallVec<[Ident; 1]>> {
AttributeExt::ident_path(self)
}
pub fn doc_str(&self) -> Option<Symbol> {
AttributeExt::doc_str(self)
}
pub fn is_proc_macro_attr(&self) -> bool {
AttributeExt::is_proc_macro_attr(self)
}
pub fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
AttributeExt::doc_str_and_comment_kind(self)
}
pub fn style(&self) -> AttrStyle {
AttributeExt::style(self)
}
}
/// Attributes owned by a HIR owner.
#[derive(Debug)]
pub struct AttributeMap<'tcx> {

View file

@ -64,8 +64,8 @@
//! This order consistency is required in a few places in rustc, for
//! example coroutine inference, and possibly also HIR borrowck.
use rustc_ast::Label;
use rustc_ast::visit::{VisitorResult, try_visit, visit_opt, walk_list};
use rustc_ast::{Attribute, Label};
use rustc_span::Span;
use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::{Ident, Symbol};

View file

@ -7,7 +7,7 @@
//! * Traits that represent operators; e.g., `Add`, `Sub`, `Index`.
//! * Functions called by the compiler itself.
use rustc_ast as ast;
use rustc_ast::attr::AttributeExt;
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
@ -153,11 +153,11 @@ impl<CTX> HashStable<CTX> for LangItem {
/// Extracts the first `lang = "$name"` out of a list of attributes.
/// The `#[panic_handler]` attribute is also extracted out when found.
pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> {
pub fn extract(attrs: &[impl AttributeExt]) -> Option<(Symbol, Span)> {
attrs.iter().find_map(|attr| {
Some(match attr {
_ if attr.has_name(sym::lang) => (attr.value_str()?, attr.span),
_ if attr.has_name(sym::panic_handler) => (sym::panic_impl, attr.span),
_ if attr.has_name(sym::lang) => (attr.value_str()?, attr.span()),
_ if attr.has_name(sym::panic_handler) => (sym::panic_impl, attr.span()),
_ => return None,
})
})

View file

@ -2,7 +2,8 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHas
use rustc_span::def_id::DefPathHash;
use crate::hir::{
AttributeMap, BodyId, Crate, ForeignItemId, ImplItemId, ItemId, OwnerNodes, TraitItemId,
Attribute, AttributeMap, BodyId, Crate, ForeignItemId, ImplItemId, ItemId, OwnerNodes,
TraitItemId,
};
use crate::hir_id::{HirId, ItemLocalId};
@ -12,6 +13,7 @@ use crate::hir_id::{HirId, ItemLocalId};
pub trait HashStableContext:
rustc_ast::HashStableContext + rustc_target::HashStableContext
{
fn hash_attr(&mut self, _: &Attribute, hasher: &mut StableHasher);
}
impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for HirId {
@ -113,3 +115,9 @@ impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Crate<'_> {
opt_hir_hash.unwrap().hash_stable(hcx, hasher)
}
}
impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Attribute {
fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
hcx.hash_attr(self, hasher)
}
}

View file

@ -11,16 +11,18 @@ use std::vec;
use rustc_abi::ExternAbi;
use rustc_ast::util::parser::{self, AssocOp, ExprPrecedence, Fixity};
use rustc_ast::{DUMMY_NODE_ID, DelimArgs};
use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent};
use rustc_ast_pretty::pp::{self, Breaks};
use rustc_ast_pretty::pprust::state::MacHeader;
use rustc_ast_pretty::pprust::{Comments, PrintState};
use rustc_hir::{
BindingMode, ByRef, ConstArgKind, GenericArg, GenericBound, GenericParam, GenericParamKind,
HirId, LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term,
};
use rustc_span::FileName;
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{Ident, Symbol, kw};
use rustc_span::{FileName, Span};
use {rustc_ast as ast, rustc_hir as hir};
pub fn id_to_string(map: &dyn rustc_hir::intravisit::Map<'_>, hir_id: HirId) -> String {
@ -68,15 +70,109 @@ impl PpAnn for &dyn rustc_hir::intravisit::Map<'_> {
pub struct State<'a> {
pub s: pp::Printer,
comments: Option<Comments<'a>>,
attrs: &'a dyn Fn(HirId) -> &'a [ast::Attribute],
attrs: &'a dyn Fn(HirId) -> &'a [hir::Attribute],
ann: &'a (dyn PpAnn + 'a),
}
impl<'a> State<'a> {
fn attrs(&self, id: HirId) -> &'a [ast::Attribute] {
fn attrs(&self, id: HirId) -> &'a [hir::Attribute] {
(self.attrs)(id)
}
fn print_inner_attributes(&mut self, attrs: &[hir::Attribute]) -> bool {
self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, true)
}
fn print_outer_attributes(&mut self, attrs: &[hir::Attribute]) -> bool {
self.print_either_attributes(attrs, ast::AttrStyle::Outer, false, true)
}
fn print_either_attributes(
&mut self,
attrs: &[hir::Attribute],
kind: ast::AttrStyle,
is_inline: bool,
trailing_hardbreak: bool,
) -> bool {
let mut printed = false;
for attr in attrs {
if attr.style == kind {
self.print_attribute_inline(attr, is_inline);
if is_inline {
self.nbsp();
}
printed = true;
}
}
if printed && trailing_hardbreak && !is_inline {
self.hardbreak_if_not_bol();
}
printed
}
fn print_attribute_inline(&mut self, attr: &hir::Attribute, is_inline: bool) {
if !is_inline {
self.hardbreak_if_not_bol();
}
self.maybe_print_comment(attr.span.lo());
match &attr.kind {
hir::AttrKind::Normal(normal) => {
match attr.style {
ast::AttrStyle::Inner => self.word("#!["),
ast::AttrStyle::Outer => self.word("#["),
}
self.print_attr_item(&normal, attr.span);
self.word("]");
}
hir::AttrKind::DocComment(comment_kind, data) => {
self.word(rustc_ast_pretty::pprust::state::doc_comment_to_string(
*comment_kind,
attr.style,
*data,
));
self.hardbreak()
}
}
}
fn print_attr_item(&mut self, item: &hir::AttrItem, span: Span) {
self.ibox(0);
let path = ast::Path {
span,
segments: item
.path
.segments
.iter()
.map(|i| ast::PathSegment { ident: *i, args: None, id: DUMMY_NODE_ID })
.collect(),
tokens: None,
};
match &item.args {
hir::AttrArgs::Delimited(DelimArgs { dspan: _, delim, tokens }) => self
.print_mac_common(
Some(MacHeader::Path(&path)),
false,
None,
*delim,
tokens,
true,
span,
),
hir::AttrArgs::Empty => {
PrintState::print_path(self, &path, false, 0);
}
hir::AttrArgs::Eq { eq_span: _, expr } => {
PrintState::print_path(self, &path, false, 0);
self.space();
self.word_space("=");
let token_str = self.meta_item_lit_to_string(expr);
self.word(token_str);
}
}
self.end();
}
fn print_node(&mut self, node: Node<'_>) {
match node {
Node::Param(a) => self.print_param(a),
@ -164,7 +260,7 @@ pub fn print_crate<'a>(
krate: &hir::Mod<'_>,
filename: FileName,
input: String,
attrs: &'a dyn Fn(HirId) -> &'a [ast::Attribute],
attrs: &'a dyn Fn(HirId) -> &'a [hir::Attribute],
ann: &'a dyn PpAnn,
) -> String {
let mut s = State {
@ -191,6 +287,10 @@ where
printer.s.eof()
}
pub fn attribute_to_string(ann: &dyn PpAnn, attr: &hir::Attribute) -> String {
to_string(ann, |s| s.print_attribute_inline(attr, false))
}
pub fn ty_to_string(ann: &dyn PpAnn, ty: &hir::Ty<'_>) -> String {
to_string(ann, |s| s.print_type(ty))
}
@ -242,7 +342,7 @@ impl<'a> State<'a> {
self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e), |e| e.span);
}
fn print_mod(&mut self, _mod: &hir::Mod<'_>, attrs: &[ast::Attribute]) {
fn print_mod(&mut self, _mod: &hir::Mod<'_>, attrs: &[hir::Attribute]) {
self.print_inner_attributes(attrs);
for &item_id in _mod.item_ids {
self.ann.nested(self, Nested::Item(item_id));
@ -926,14 +1026,14 @@ impl<'a> State<'a> {
self.print_block_maybe_unclosed(blk, &[], false)
}
fn print_block_with_attrs(&mut self, blk: &hir::Block<'_>, attrs: &[ast::Attribute]) {
fn print_block_with_attrs(&mut self, blk: &hir::Block<'_>, attrs: &[hir::Attribute]) {
self.print_block_maybe_unclosed(blk, attrs, true)
}
fn print_block_maybe_unclosed(
&mut self,
blk: &hir::Block<'_>,
attrs: &[ast::Attribute],
attrs: &[hir::Attribute],
close_box: bool,
) {
match blk.rules {

View file

@ -50,7 +50,7 @@ use rustc_middle::{bug, span_bug};
use rustc_span::Span;
use rustc_span::symbol::{Symbol, sym};
use tracing::debug;
use {rustc_ast as ast, rustc_graphviz as dot, rustc_hir as hir};
use {rustc_graphviz as dot, rustc_hir as hir};
use crate::errors;
@ -106,7 +106,7 @@ struct IfThisChanged<'tcx> {
}
impl<'tcx> IfThisChanged<'tcx> {
fn argument(&self, attr: &ast::Attribute) -> Option<Symbol> {
fn argument(&self, attr: &hir::Attribute) -> Option<Symbol> {
let mut value = None;
for list_item in attr.meta_item_list().unwrap_or_default() {
match list_item.ident() {

View file

@ -19,11 +19,13 @@
//! Errors are reported if we are in the suitable configuration but
//! the required condition is not met.
use rustc_ast::{self as ast, Attribute, MetaItemInner};
use rustc_ast::{self as ast, MetaItemInner};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::unord::UnordSet;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::{ImplItemKind, ItemKind as HirItem, Node as HirNode, TraitItemKind, intravisit};
use rustc_hir::{
Attribute, ImplItemKind, ItemKind as HirItem, Node as HirNode, TraitItemKind, intravisit,
};
use rustc_middle::dep_graph::{DepNode, DepNodeExt, label_strs};
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::TyCtxt;

View file

@ -387,7 +387,7 @@ pub struct MissingDoc;
impl_lint_pass!(MissingDoc => [MISSING_DOCS]);
fn has_doc(attr: &ast::Attribute) -> bool {
fn has_doc(attr: &hir::Attribute) -> bool {
if attr.is_doc_comment() {
return true;
}
@ -1012,7 +1012,7 @@ declare_lint_pass!(InvalidNoMangleItems => [NO_MANGLE_CONST_ITEMS, NO_MANGLE_GEN
impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
let attrs = cx.tcx.hir().attrs(it.hir_id());
let check_no_mangle_on_generic_fn = |no_mangle_attr: &ast::Attribute,
let check_no_mangle_on_generic_fn = |no_mangle_attr: &hir::Attribute,
impl_generics: Option<&hir::Generics<'_>>,
generics: &hir::Generics<'_>,
span| {
@ -1176,7 +1176,7 @@ declare_lint_pass!(
);
impl<'tcx> LateLintPass<'tcx> for UnstableFeatures {
fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) {
fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &hir::Attribute) {
if attr.has_name(sym::feature)
&& let Some(items) = attr.meta_item_list()
{

View file

@ -1,4 +1,5 @@
use rustc_ast_pretty::pprust;
use rustc_attr::AttributeExt;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_errors::{Diag, LintDiagnostic, MultiSpan};
use rustc_feature::{Features, GateIssue};
@ -371,7 +372,7 @@ impl<'tcx> Visitor<'tcx> for LintLevelMaximum<'tcx> {
/// FIXME(blyxyas): In a future revision, we should also graph #![allow]s,
/// but that is handled with more care
fn visit_attribute(&mut self, attribute: &'tcx ast::Attribute) {
fn visit_attribute(&mut self, attribute: &'tcx hir::Attribute) {
if matches!(
Level::from_attr(attribute),
Some(
@ -383,10 +384,9 @@ impl<'tcx> Visitor<'tcx> for LintLevelMaximum<'tcx> {
)
) {
let store = unerased_lint_store(self.tcx.sess);
let Some(meta) = attribute.meta() else { return };
// Lint attributes are always a metalist inside a
// metalist (even with just one lint).
let Some(meta_item_list) = meta.meta_item_list() else { return };
let Some(meta_item_list) = attribute.meta_item_list() else { return };
for meta_list in meta_item_list {
// Convert Path to String
@ -686,7 +686,12 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
};
}
fn add(&mut self, attrs: &[ast::Attribute], is_crate_node: bool, source_hir_id: Option<HirId>) {
fn add(
&mut self,
attrs: &[impl AttributeExt],
is_crate_node: bool,
source_hir_id: Option<HirId>,
) {
let sess = self.sess;
for (attr_index, attr) in attrs.iter().enumerate() {
if attr.has_name(sym::automatically_derived) {
@ -910,7 +915,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
let src = LintLevelSource::Node { name, span: sp, reason };
for &id in ids {
if self.check_gated_lint(id, attr.span, false) {
if self.check_gated_lint(id, attr.span(), false) {
self.insert_spec(id, (level, src));
}
}

View file

@ -1,7 +1,7 @@
use rustc_abi::ExternAbi;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::FnKind;
use rustc_hir::{GenericParamKind, PatKind};
use rustc_hir::{AttrArgs, AttrItem, AttrKind, GenericParamKind, PatKind};
use rustc_middle::ty;
use rustc_session::config::CrateType;
use rustc_session::{declare_lint, declare_lint_pass};
@ -342,36 +342,37 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
let crate_ident = if let Some(name) = &cx.tcx.sess.opts.crate_name {
Some(Ident::from_str(name))
} else {
attr::find_by_name(cx.tcx.hir().attrs(hir::CRATE_HIR_ID), sym::crate_name)
.and_then(|attr| attr.meta())
.and_then(|meta| {
meta.name_value_literal().and_then(|lit| {
if let ast::LitKind::Str(name, ..) = lit.kind {
// Discard the double quotes surrounding the literal.
let sp = cx
.sess()
.source_map()
.span_to_snippet(lit.span)
.ok()
.and_then(|snippet| {
let left = snippet.find('"')?;
let right =
snippet.rfind('"').map(|pos| snippet.len() - pos)?;
attr::find_by_name(cx.tcx.hir().attrs(hir::CRATE_HIR_ID), sym::crate_name).and_then(
|attr| {
if let AttrKind::Normal(n) = &attr.kind
&& let AttrItem { args: AttrArgs::Eq { eq_span: _, expr: ref lit }, .. } =
n.as_ref()
&& let ast::LitKind::Str(name, ..) = lit.kind
{
// Discard the double quotes surrounding the literal.
let sp = cx
.sess()
.source_map()
.span_to_snippet(lit.span)
.ok()
.and_then(|snippet| {
let left = snippet.find('"')?;
let right = snippet.rfind('"').map(|pos| snippet.len() - pos)?;
Some(
lit.span
.with_lo(lit.span.lo() + BytePos(left as u32 + 1))
.with_hi(lit.span.hi() - BytePos(right as u32)),
)
})
.unwrap_or(lit.span);
Some(
lit.span
.with_lo(lit.span.lo() + BytePos(left as u32 + 1))
.with_hi(lit.span.hi() - BytePos(right as u32)),
)
})
.unwrap_or(lit.span);
Some(Ident::new(name, sp))
} else {
None
}
})
})
Some(Ident::new(name, sp))
} else {
None
}
},
)
};
if let Some(ident) = &crate_ident {

View file

@ -42,9 +42,9 @@ macro_rules! late_lint_methods {
fn check_field_def(a: &'tcx rustc_hir::FieldDef<'tcx>);
fn check_variant(a: &'tcx rustc_hir::Variant<'tcx>);
fn check_path(a: &rustc_hir::Path<'tcx>, b: rustc_hir::HirId);
fn check_attribute(a: &'tcx rustc_ast::Attribute);
fn check_attributes(a: &'tcx [rustc_ast::Attribute]);
fn check_attributes_post(a: &'tcx [rustc_ast::Attribute]);
fn check_attribute(a: &'tcx rustc_hir::Attribute);
fn check_attributes(a: &'tcx [rustc_hir::Attribute]);
fn check_attributes_post(a: &'tcx [rustc_hir::Attribute]);
]);
)
}

View file

@ -3,8 +3,9 @@
// tidy-alphabetical-end
use rustc_abi::ExternAbi;
use rustc_ast::AttrId;
use rustc_ast::attr::AttributeExt;
use rustc_ast::node_id::NodeId;
use rustc_ast::{AttrId, Attribute};
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::stable_hasher::{
HashStable, StableCompare, StableHasher, ToStableHashKey,
@ -221,8 +222,8 @@ impl Level {
}
/// Converts an `Attribute` to a level.
pub fn from_attr(attr: &Attribute) -> Option<Self> {
Self::from_symbol(attr.name_or_empty(), Some(attr.id))
pub fn from_attr(attr: &impl AttributeExt) -> Option<Self> {
Self::from_symbol(attr.name_or_empty(), Some(attr.id()))
}
/// Converts a `Symbol` to a level.

View file

@ -17,6 +17,7 @@ use rustc_data_structures::sync::{self, FreezeReadGuard, FreezeWriteGuard};
use rustc_errors::DiagCtxtHandle;
use rustc_expand::base::SyntaxExtension;
use rustc_fs_util::try_canonicalize;
use rustc_hir as hir;
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE, LocalDefId, StableCrateId};
use rustc_hir::definitions::Definitions;
use rustc_index::IndexVec;
@ -97,7 +98,13 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
}
pub enum LoadedMacro {
MacroDef { def: MacroDef, ident: Ident, attrs: AttrVec, span: Span, edition: Edition },
MacroDef {
def: MacroDef,
ident: Ident,
attrs: Vec<hir::Attribute>,
span: Span,
edition: Edition,
},
ProcMacro(SyntaxExtension),
}

View file

@ -1369,7 +1369,7 @@ impl<'a> CrateMetadataRef<'a> {
self,
id: DefIndex,
sess: &'a Session,
) -> impl Iterator<Item = ast::Attribute> + 'a {
) -> impl Iterator<Item = hir::Attribute> + 'a {
self.root
.tables
.attributes

View file

@ -344,7 +344,7 @@ provide! { tcx, def_id, other, cdata,
}
associated_item => { cdata.get_associated_item(def_id.index, tcx.sess) }
inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) }
item_attrs => { tcx.arena.alloc_from_iter(cdata.get_item_attrs(def_id.index, tcx.sess)) }
attrs_for_def => { tcx.arena.alloc_from_iter(cdata.get_item_attrs(def_id.index, tcx.sess)) }
is_mir_available => { cdata.is_item_mir_available(def_id.index) }
is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) }
cross_crate_inlinable => { table_direct }

View file

@ -4,7 +4,7 @@ use std::fs::File;
use std::io::{Read, Seek, Write};
use std::path::{Path, PathBuf};
use rustc_ast::Attribute;
use rustc_ast::attr::AttributeExt;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::memmap::{Mmap, MmapMut};
use rustc_data_structures::sync::{Lrc, join, par_for_each_in};
@ -814,7 +814,7 @@ struct AnalyzeAttrState<'a> {
/// visibility: this is a piece of data that can be computed once per defid, and not once per
/// attribute. Some attributes would only be usable downstream if they are public.
#[inline]
fn analyze_attr(attr: &Attribute, state: &mut AnalyzeAttrState<'_>) -> bool {
fn analyze_attr(attr: &impl AttributeExt, state: &mut AnalyzeAttrState<'_>) -> bool {
let mut should_encode = false;
if !rustc_feature::encode_cross_crate(attr.name_or_empty()) {
// Attributes not marked encode-cross-crate don't need to be encoded for downstream crates.
@ -1354,7 +1354,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
.hir()
.attrs(tcx.local_def_id_to_hir_id(def_id))
.iter()
.filter(|attr| analyze_attr(attr, &mut state));
.filter(|attr| analyze_attr(*attr, &mut state));
record_array!(self.tables.attributes[def_id.to_def_id()] <- attr_iter);

View file

@ -403,7 +403,7 @@ define_tables! {
cross_crate_inlinable: Table<DefIndex, bool>,
- optional:
attributes: Table<DefIndex, LazyArray<ast::Attribute>>,
attributes: Table<DefIndex, LazyArray<hir::Attribute>>,
// For non-reexported names in a module every name is associated with a separate `DefId`,
// so we can take their names, visibilities etc from other encoded tables.
module_children_non_reexports: Table<DefIndex, LazyArray<DefIndex>>,

View file

@ -85,7 +85,7 @@ macro_rules! arena_types {
[] upvars_mentioned: rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>,
[] dyn_compatibility_violations: rustc_middle::traits::DynCompatibilityViolation,
[] codegen_unit: rustc_middle::mir::mono::CodegenUnit<'tcx>,
[decode] attribute: rustc_ast::Attribute,
[decode] attribute: rustc_hir::Attribute,
[] name_set: rustc_data_structures::unord::UnordSet<rustc_span::symbol::Symbol>,
[] ordered_name_set: rustc_data_structures::fx::FxIndexSet<rustc_span::symbol::Symbol>,
[] pats: rustc_middle::ty::PatternKind<'tcx>,

View file

@ -9,11 +9,11 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId, LocalModDefId};
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
use rustc_hir::intravisit::Visitor;
use rustc_hir::*;
use rustc_hir_pretty as pprust_hir;
use rustc_middle::hir::nested_filter;
use rustc_span::def_id::StableCrateId;
use rustc_span::symbol::{Ident, Symbol, kw, sym};
use rustc_span::{ErrorGuaranteed, Span};
use {rustc_ast as ast, rustc_hir_pretty as pprust_hir};
use crate::hir::ModuleItems;
use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
@ -381,7 +381,7 @@ impl<'hir> Map<'hir> {
/// Gets the attributes on the crate. This is preferable to
/// invoking `krate.attrs` because it registers a tighter
/// dep-graph access.
pub fn krate_attrs(self) -> &'hir [ast::Attribute] {
pub fn krate_attrs(self) -> &'hir [Attribute] {
self.attrs(CRATE_HIR_ID)
}
@ -792,7 +792,7 @@ impl<'hir> Map<'hir> {
/// Given a node ID, gets a list of attributes associated with the AST
/// corresponding to the node-ID.
pub fn attrs(self, id: HirId) -> &'hir [ast::Attribute] {
pub fn attrs(self, id: HirId) -> &'hir [Attribute] {
self.tcx.hir_attrs(id.owner).get(id.local_id)
}

View file

@ -151,7 +151,7 @@ impl<'tcx> TyCtxt<'tcx> {
self,
node: OwnerNode<'_>,
bodies: &SortedMap<ItemLocalId, &Body<'_>>,
attrs: &SortedMap<ItemLocalId, &[rustc_ast::Attribute]>,
attrs: &SortedMap<ItemLocalId, &[Attribute]>,
) -> (Option<Fingerprint>, Option<Fingerprint>) {
if self.needs_crate_hash() {
self.with_stable_hashing_context(|mut hcx| {

View file

@ -10,7 +10,7 @@
use std::num::IntErrorKind;
use rustc_ast::Attribute;
use rustc_ast::attr::AttributeExt;
use rustc_session::{Limit, Limits, Session};
use rustc_span::symbol::{Symbol, sym};
@ -35,32 +35,36 @@ pub fn provide(providers: &mut Providers) {
}
}
pub fn get_recursion_limit(krate_attrs: &[Attribute], sess: &Session) -> Limit {
pub fn get_recursion_limit(krate_attrs: &[impl AttributeExt], sess: &Session) -> Limit {
get_limit(krate_attrs, sess, sym::recursion_limit, 128)
}
fn get_limit(krate_attrs: &[Attribute], sess: &Session, name: Symbol, default: usize) -> Limit {
fn get_limit(
krate_attrs: &[impl AttributeExt],
sess: &Session,
name: Symbol,
default: usize,
) -> Limit {
match get_limit_size(krate_attrs, sess, name) {
Some(size) => Limit::new(size),
None => Limit::new(default),
}
}
pub fn get_limit_size(krate_attrs: &[Attribute], sess: &Session, name: Symbol) -> Option<usize> {
pub fn get_limit_size(
krate_attrs: &[impl AttributeExt],
sess: &Session,
name: Symbol,
) -> Option<usize> {
for attr in krate_attrs {
if !attr.has_name(name) {
continue;
}
if let Some(s) = attr.value_str() {
match s.as_str().parse() {
if let Some(sym) = attr.value_str() {
match sym.as_str().parse() {
Ok(n) => return Some(n),
Err(e) => {
let value_span = attr
.meta()
.and_then(|meta| meta.name_value_literal_span())
.unwrap_or(attr.span);
let error_str = match e.kind() {
IntErrorKind::PosOverflow => "`limit` is too large",
IntErrorKind::Empty => "`limit` must be a non-negative integer",
@ -71,7 +75,11 @@ pub fn get_limit_size(krate_attrs: &[Attribute], sess: &Session, name: Symbol) -
IntErrorKind::Zero => bug!("zero is a valid `limit`"),
kind => bug!("unimplemented IntErrorKind variant: {:?}", kind),
};
sess.dcx().emit_err(LimitInvalid { span: attr.span, value_span, error_str });
sess.dcx().emit_err(LimitInvalid {
span: attr.span(),
value_span: attr.value_span().unwrap(),
error_str,
});
}
}
}

View file

@ -1267,7 +1267,7 @@ rustc_queries! {
/// Returns the attributes on the item at `def_id`.
///
/// Do not use this directly, use `tcx.get_attrs` instead.
query item_attrs(def_id: DefId) -> &'tcx [ast::Attribute] {
query attrs_for_def(def_id: DefId) -> &'tcx [hir::Attribute] {
desc { |tcx| "collecting attributes of `{}`", tcx.def_path_str(def_id) }
separate_provide_extern
}

View file

@ -798,7 +798,7 @@ macro_rules! impl_ref_decoder {
impl_ref_decoder! {<'tcx>
Span,
rustc_ast::Attribute,
rustc_hir::Attribute,
rustc_span::symbol::Ident,
ty::Variance,
rustc_span::def_id::DefId,

View file

@ -13,7 +13,7 @@ use std::ops::{Bound, Deref};
use std::{fmt, iter, mem};
use rustc_abi::{ExternAbi, FieldIdx, Layout, LayoutData, TargetDataLayout, VariantIdx};
use rustc_ast::{self as ast, attr};
use rustc_ast as ast;
use rustc_data_structures::defer;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
@ -29,13 +29,12 @@ use rustc_data_structures::unord::UnordSet;
use rustc_errors::{
Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, LintDiagnostic, MultiSpan,
};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind};
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
use rustc_hir::definitions::Definitions;
use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{HirId, Node, TraitCandidate};
use rustc_hir::{self as hir, Attribute, HirId, Node, TraitCandidate};
use rustc_index::IndexVec;
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
use rustc_query_system::cache::WithDepNode;
@ -3239,12 +3238,16 @@ pub fn provide(providers: &mut Providers) {
providers.extern_mod_stmt_cnum =
|tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned();
providers.is_panic_runtime =
|tcx, LocalCrate| attr::contains_name(tcx.hir().krate_attrs(), sym::panic_runtime);
|tcx, LocalCrate| contains_name(tcx.hir().krate_attrs(), sym::panic_runtime);
providers.is_compiler_builtins =
|tcx, LocalCrate| attr::contains_name(tcx.hir().krate_attrs(), sym::compiler_builtins);
|tcx, LocalCrate| contains_name(tcx.hir().krate_attrs(), sym::compiler_builtins);
providers.has_panic_handler = |tcx, LocalCrate| {
// We want to check if the panic handler was defined in this crate
tcx.lang_items().panic_impl().is_some_and(|did| did.is_local())
};
providers.source_span = |tcx, def_id| tcx.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP);
}
pub fn contains_name(attrs: &[Attribute], name: Symbol) -> bool {
attrs.iter().any(|x| x.has_name(name))
}

View file

@ -277,7 +277,7 @@ impl<'tcx> InstanceKind<'tcx> {
&self,
tcx: TyCtxt<'tcx>,
attr: Symbol,
) -> impl Iterator<Item = &'tcx rustc_ast::Attribute> {
) -> impl Iterator<Item = &'tcx hir::Attribute> {
tcx.get_attrs(self.def_id(), attr)
}

View file

@ -1745,11 +1745,11 @@ impl<'tcx> TyCtxt<'tcx> {
}
// FIXME(@lcnr): Remove this function.
pub fn get_attrs_unchecked(self, did: DefId) -> &'tcx [ast::Attribute] {
pub fn get_attrs_unchecked(self, did: DefId) -> &'tcx [hir::Attribute] {
if let Some(did) = did.as_local() {
self.hir().attrs(self.local_def_id_to_hir_id(did))
} else {
self.item_attrs(did)
self.attrs_for_def(did)
}
}
@ -1758,14 +1758,14 @@ impl<'tcx> TyCtxt<'tcx> {
self,
did: impl Into<DefId>,
attr: Symbol,
) -> impl Iterator<Item = &'tcx ast::Attribute> {
) -> impl Iterator<Item = &'tcx hir::Attribute> {
let did: DefId = did.into();
let filter_fn = move |a: &&ast::Attribute| a.has_name(attr);
let filter_fn = move |a: &&hir::Attribute| a.has_name(attr);
if let Some(did) = did.as_local() {
self.hir().attrs(self.local_def_id_to_hir_id(did)).iter().filter(filter_fn)
} else {
debug_assert!(rustc_feature::encode_cross_crate(attr));
self.item_attrs(did).iter().filter(filter_fn)
self.attrs_for_def(did).iter().filter(filter_fn)
}
}
@ -1781,7 +1781,7 @@ impl<'tcx> TyCtxt<'tcx> {
self,
did: impl Into<DefId>,
attr: Symbol,
) -> Option<&'tcx ast::Attribute> {
) -> Option<&'tcx hir::Attribute> {
let did: DefId = did.into();
if did.as_local().is_some() {
// it's a crate local item, we need to check feature flags
@ -1794,7 +1794,7 @@ impl<'tcx> TyCtxt<'tcx> {
// we filter out unstable diagnostic attributes before
// encoding attributes
debug_assert!(rustc_feature::encode_cross_crate(attr));
self.item_attrs(did)
self.attrs_for_def(did)
.iter()
.find(|a| matches!(a.path().as_ref(), [sym::diagnostic, a] if *a == attr))
}
@ -1804,19 +1804,19 @@ impl<'tcx> TyCtxt<'tcx> {
self,
did: DefId,
attr: &'attr [Symbol],
) -> impl Iterator<Item = &'tcx ast::Attribute> + 'attr
) -> impl Iterator<Item = &'tcx hir::Attribute> + 'attr
where
'tcx: 'attr,
{
let filter_fn = move |a: &&ast::Attribute| a.path_matches(attr);
let filter_fn = move |a: &&hir::Attribute| a.path_matches(attr);
if let Some(did) = did.as_local() {
self.hir().attrs(self.local_def_id_to_hir_id(did)).iter().filter(filter_fn)
} else {
self.item_attrs(did).iter().filter(filter_fn)
self.attrs_for_def(did).iter().filter(filter_fn)
}
}
pub fn get_attr(self, did: impl Into<DefId>, attr: Symbol) -> Option<&'tcx ast::Attribute> {
pub fn get_attr(self, did: impl Into<DefId>, attr: Symbol) -> Option<&'tcx hir::Attribute> {
if cfg!(debug_assertions) && !rustc_feature::is_valid_for_get_attr(attr) {
let did: DefId = did.into();
bug!("get_attr: unexpected called with DefId `{:?}`, attr `{:?}`", did, attr);

View file

@ -111,6 +111,7 @@ trivially_parameterized_over_tcx! {
rustc_span::hygiene::SyntaxContextData,
rustc_span::symbol::Ident,
rustc_type_ir::Variance,
rustc_hir::Attribute,
}
// HACK(compiler-errors): This macro rule can only take a fake path,
@ -140,5 +141,5 @@ parameterized_over_tcx! {
ty::Predicate,
ty::Clause,
ty::ClauseKind,
ty::ImplTraitHeader
ty::ImplTraitHeader,
}

View file

@ -17,10 +17,9 @@
//! terminators, and everything below can be found in the `parse::instruction` submodule.
//!
use rustc_ast::Attribute;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::HirId;
use rustc_hir::def_id::DefId;
use rustc_hir::{Attribute, HirId};
use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::mir::*;
use rustc_middle::span_bug;

View file

@ -1,6 +1,5 @@
use rustc_ast as ast;
use rustc_ast::attr;
use rustc_ast::token::{self, Delimiter};
use rustc_ast::{self as ast, Attribute, attr};
use rustc_errors::codes::*;
use rustc_errors::{Diag, PResult};
use rustc_span::symbol::kw;
@ -48,7 +47,7 @@ impl<'a> Parser<'a> {
let start_pos = self.num_bump_calls;
loop {
let attr = if self.check(&token::Pound) {
let prev_outer_attr_sp = outer_attrs.last().map(|attr| attr.span);
let prev_outer_attr_sp = outer_attrs.last().map(|attr: &Attribute| attr.span);
let inner_error_reason = if just_parsed_doc_comment {
Some(InnerAttrForbiddenReason::AfterOuterDocComment {

View file

@ -29,9 +29,9 @@ use rustc_ast::tokenstream::{
};
use rustc_ast::util::case::Case;
use rustc_ast::{
self as ast, AnonConst, AttrArgs, AttrArgsEq, AttrId, ByRef, Const, CoroutineKind,
DUMMY_NODE_ID, DelimArgs, Expr, ExprKind, Extern, HasAttrs, HasTokens, Mutability, Recovered,
Safety, StrLit, Visibility, VisibilityKind,
self as ast, AnonConst, AttrArgs, AttrId, ByRef, Const, CoroutineKind, DUMMY_NODE_ID,
DelimArgs, Expr, ExprKind, Extern, HasAttrs, HasTokens, Mutability, Recovered, Safety, StrLit,
Visibility, VisibilityKind,
};
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashMap;
@ -1376,7 +1376,7 @@ impl<'a> Parser<'a> {
AttrArgs::Delimited(args)
} else if self.eat(&token::Eq) {
let eq_span = self.prev_token.span;
AttrArgs::Eq { eq_span, expr: AttrArgsEq::Ast(self.parse_expr_force_collect()?) }
AttrArgs::Eq { eq_span, expr: self.parse_expr_force_collect()? }
} else {
AttrArgs::Empty
})

View file

@ -3,8 +3,7 @@
use rustc_ast::token::Delimiter;
use rustc_ast::tokenstream::DelimSpan;
use rustc_ast::{
self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem, MetaItemInner, MetaItemKind,
Safety,
self as ast, AttrArgs, Attribute, DelimArgs, MetaItem, MetaItemInner, MetaItemKind, Safety,
};
use rustc_errors::{Applicability, FatalError, PResult};
use rustc_feature::{AttributeSafety, AttributeTemplate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute};
@ -70,7 +69,7 @@ pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Met
parse_in(psess, tokens.clone(), "meta list", |p| p.parse_meta_seq_top())?;
MetaItemKind::List(nmis)
}
AttrArgs::Eq { expr: AttrArgsEq::Ast(expr), .. } => {
AttrArgs::Eq { expr, .. } => {
if let ast::ExprKind::Lit(token_lit) = expr.kind {
let res = ast::MetaItemLit::from_token_lit(token_lit, expr.span);
let res = match res {
@ -116,7 +115,6 @@ pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Met
return Err(err);
}
}
AttrArgs::Eq { expr: AttrArgsEq::Hir(lit), .. } => MetaItemKind::NameValue(lit.clone()),
},
})
}

View file

@ -1,4 +1,4 @@
use rustc_ast::Attribute;
use rustc_hir::Attribute;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::span_bug;

View file

@ -7,17 +7,15 @@
use std::cell::Cell;
use std::collections::hash_map::Entry;
use rustc_ast::{
AttrKind, AttrStyle, Attribute, LitKind, MetaItemInner, MetaItemKind, MetaItemLit, ast,
};
use rustc_ast::{AttrStyle, LitKind, MetaItemInner, MetaItemKind, MetaItemLit, ast};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{Applicability, DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey};
use rustc_feature::{AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute};
use rustc_hir::def_id::LocalModDefId;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{
self as hir, self, AssocItemKind, CRATE_HIR_ID, CRATE_OWNER_ID, FnSig, ForeignItem, HirId,
Item, ItemKind, MethodKind, Safety, Target, TraitItem,
self as hir, self, AssocItemKind, AttrKind, Attribute, CRATE_HIR_ID, CRATE_OWNER_ID, FnSig,
ForeignItem, HirId, Item, ItemKind, MethodKind, Safety, Target, TraitItem,
};
use rustc_macros::LintDiagnostic;
use rustc_middle::hir::nested_filter;
@ -1176,10 +1174,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
specified_inline: &mut Option<(bool, Span)>,
aliases: &mut FxHashMap<String, Span>,
) {
if let Some(mi) = attr.meta()
&& let Some(list) = mi.meta_item_list()
{
for meta in list {
if let Some(list) = attr.meta_item_list() {
for meta in &list {
if let Some(i_meta) = meta.meta_item() {
match i_meta.name_or_empty() {
sym::alias => {
@ -1279,7 +1275,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
AttrStyle::Inner => "!",
AttrStyle::Outer => "",
},
sugg: (attr.meta().unwrap().span, applicability),
sugg: (attr.span, applicability),
},
);
} else if i_meta.has_name(sym::passes)
@ -2141,10 +2137,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
fn check_confusables(&self, attr: &Attribute, target: Target) {
match target {
Target::Method(MethodKind::Inherent) => {
let Some(meta) = attr.meta() else {
return;
};
let ast::MetaItem { kind: MetaItemKind::List(ref metas), .. } = meta else {
let Some(metas) = attr.meta_item_list() else {
return;
};
@ -2602,7 +2595,7 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
if let AttrKind::Normal(ref p) = attr.kind {
tcx.dcx().try_steal_replace_and_emit_err(
p.item.path.span,
p.path.span,
StashKey::UndeterminedMacroResolution,
err,
);

View file

@ -9,9 +9,8 @@
//!
//! * Compiler internal types like `Ty` and `TyCtxt`
use rustc_ast as ast;
use rustc_hir::OwnerId;
use rustc_hir::diagnostic_items::DiagnosticItems;
use rustc_hir::{Attribute, OwnerId};
use rustc_middle::query::{LocalCrate, Providers};
use rustc_middle::ty::TyCtxt;
use rustc_span::def_id::{DefId, LOCAL_CRATE};
@ -55,7 +54,7 @@ fn report_duplicate_item(
}
/// Extract the first `rustc_diagnostic_item = "$name"` out of a list of attributes.
fn extract(attrs: &[ast::Attribute]) -> Option<Symbol> {
fn extract(attrs: &[Attribute]) -> Option<Symbol> {
attrs.iter().find_map(|attr| {
if attr.has_name(sym::rustc_diagnostic_item) { attr.value_str() } else { None }
})

View file

@ -500,7 +500,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
hir_visit::walk_assoc_item_constraint(self, constraint)
}
fn visit_attribute(&mut self, attr: &'v ast::Attribute) {
fn visit_attribute(&mut self, attr: &'v hir::Attribute) {
self.record("Attribute", None, attr);
}

View file

@ -1,5 +1,5 @@
use rustc_abi::{HasDataLayout, TargetDataLayout};
use rustc_ast::Attribute;
use rustc_hir::Attribute;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::span_bug;

View file

@ -4,8 +4,8 @@
//! but are not declared in one single location (unlike lang features), which means we need to
//! collect them instead.
use rustc_ast::Attribute;
use rustc_attr::VERSION_PLACEHOLDER;
use rustc_hir::Attribute;
use rustc_hir::intravisit::Visitor;
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures};

View file

@ -1,18 +1,17 @@
//! This module contains `HashStable` implementations for various data types
//! from `rustc_ast` in no particular order.
//! from various crates in no particular order.
use std::assert_matches::assert_matches;
use rustc_ast as ast;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_hir as hir;
use rustc_span::SourceFile;
use smallvec::SmallVec;
use crate::ich::StableHashingContext;
impl<'ctx> rustc_target::HashStableContext for StableHashingContext<'ctx> {}
impl<'ctx> rustc_ast::HashStableContext for StableHashingContext<'ctx> {}
impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] {
impl<'a> HashStable<StableHashingContext<'a>> for [hir::Attribute] {
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
if self.is_empty() {
self.len().hash_stable(hcx, hasher);
@ -20,7 +19,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] {
}
// Some attributes are always ignored during hashing.
let filtered: SmallVec<[&ast::Attribute; 8]> = self
let filtered: SmallVec<[&hir::Attribute; 8]> = self
.iter()
.filter(|attr| {
!attr.is_doc_comment()
@ -35,30 +34,23 @@ impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] {
}
}
impl<'ctx> rustc_ast::HashStableContext for StableHashingContext<'ctx> {
fn hash_attr(&mut self, attr: &ast::Attribute, hasher: &mut StableHasher) {
impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> {
fn hash_attr(&mut self, attr: &hir::Attribute, hasher: &mut StableHasher) {
// Make sure that these have been filtered out.
debug_assert!(!attr.ident().is_some_and(|ident| self.is_ignored_attr(ident.name)));
debug_assert!(!attr.is_doc_comment());
let ast::Attribute { kind, id: _, style, span } = attr;
if let ast::AttrKind::Normal(normal) = kind {
normal.item.hash_stable(self, hasher);
let hir::Attribute { kind, id: _, style, span } = attr;
if let hir::AttrKind::Normal(item) = kind {
item.hash_stable(self, hasher);
style.hash_stable(self, hasher);
span.hash_stable(self, hasher);
assert_matches!(
normal.tokens.as_ref(),
None,
"Tokens should have been removed during lowering!"
);
} else {
unreachable!();
}
}
}
impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> {}
impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
let SourceFile {

View file

@ -7,7 +7,7 @@ use std::mem;
use rustc_ast::expand::StrippedCfgItem;
use rustc_ast::{self as ast, Crate, Inline, ItemKind, ModKind, NodeId, attr};
use rustc_ast_pretty::pprust;
use rustc_attr::StabilityLevel;
use rustc_attr::{AttributeExt, StabilityLevel};
use rustc_data_structures::intern::Interned;
use rustc_data_structures::sync::Lrc;
use rustc_errors::{Applicability, StashKey};
@ -1126,7 +1126,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
&mut self,
macro_def: &ast::MacroDef,
ident: Ident,
attrs: &[ast::Attribute],
attrs: &[impl AttributeExt],
span: Span,
node_id: NodeId,
edition: Edition,

View file

@ -6,6 +6,7 @@ use pulldown_cmark::{
};
use rustc_ast as ast;
use rustc_ast::util::comments::beautify_doc_string;
use rustc_attr::AttributeExt;
use rustc_data_structures::fx::FxIndexMap;
use rustc_middle::ty::TyCtxt;
use rustc_span::def_id::DefId;
@ -192,19 +193,24 @@ pub fn add_doc_fragment(out: &mut String, frag: &DocFragment) {
}
}
pub fn attrs_to_doc_fragments<'a>(
attrs: impl Iterator<Item = (&'a ast::Attribute, Option<DefId>)>,
pub fn attrs_to_doc_fragments<'a, A: AttributeExt + Clone + 'a>(
attrs: impl Iterator<Item = (&'a A, Option<DefId>)>,
doc_only: bool,
) -> (Vec<DocFragment>, ast::AttrVec) {
) -> (Vec<DocFragment>, Vec<A>) {
let mut doc_fragments = Vec::new();
let mut other_attrs = ast::AttrVec::new();
let mut other_attrs = Vec::<A>::new();
for (attr, item_id) in attrs {
if let Some((doc_str, comment_kind)) = attr.doc_str_and_comment_kind() {
let doc = beautify_doc_string(doc_str, comment_kind);
let (span, kind) = if attr.is_doc_comment() {
(attr.span, DocFragmentKind::SugaredDoc)
(attr.span(), DocFragmentKind::SugaredDoc)
} else {
(span_for_value(attr), DocFragmentKind::RawDoc)
(
attr.value_span()
.map(|i| i.with_ctxt(attr.span().ctxt()))
.unwrap_or(attr.span()),
DocFragmentKind::RawDoc,
)
};
let fragment = DocFragment { span, doc, kind, item_id, indent: 0 };
doc_fragments.push(fragment);
@ -218,16 +224,6 @@ pub fn attrs_to_doc_fragments<'a>(
(doc_fragments, other_attrs)
}
fn span_for_value(attr: &ast::Attribute) -> Span {
if let ast::AttrKind::Normal(normal) = &attr.kind
&& let ast::AttrArgs::Eq { expr, .. } = &normal.item.args
{
expr.span().with_ctxt(attr.span.ctxt())
} else {
attr.span
}
}
/// Return the doc-comments on this item, grouped by the module they came from.
/// The module can be different if this is a re-export with added documentation.
///
@ -353,12 +349,15 @@ pub fn strip_generics_from_path(path_str: &str) -> Result<Box<str>, MalformedGen
///
//// If there are no doc-comments, return true.
/// FIXME(#78591): Support both inner and outer attributes on the same item.
pub fn inner_docs(attrs: &[ast::Attribute]) -> bool {
attrs.iter().find(|a| a.doc_str().is_some()).map_or(true, |a| a.style == ast::AttrStyle::Inner)
pub fn inner_docs(attrs: &[impl AttributeExt]) -> bool {
attrs
.iter()
.find(|a| a.doc_str().is_some())
.map_or(true, |a| a.style() == ast::AttrStyle::Inner)
}
/// Has `#[rustc_doc_primitive]` or `#[doc(keyword)]`.
pub fn has_primitive_or_keyword_docs(attrs: &[ast::Attribute]) -> bool {
pub fn has_primitive_or_keyword_docs(attrs: &[impl AttributeExt]) -> bool {
for attr in attrs {
if attr.has_name(sym::rustc_doc_primitive) {
return true;
@ -408,7 +407,7 @@ pub fn may_be_doc_link(link_type: LinkType) -> bool {
/// Simplified version of `preprocessed_markdown_links` from rustdoc.
/// Must return at least the same links as it, but may add some more links on top of that.
pub(crate) fn attrs_to_preprocessed_links(attrs: &[ast::Attribute]) -> Vec<Box<str>> {
pub(crate) fn attrs_to_preprocessed_links<A: AttributeExt + Clone>(attrs: &[A]) -> Vec<Box<str>> {
let (doc_fragments, _) = attrs_to_doc_fragments(attrs.iter().map(|attr| (attr, None)), true);
let doc = prepare_to_doc_link_resolution(&doc_fragments).into_values().next().unwrap();

View file

@ -7,9 +7,9 @@ edition = "2021"
# tidy-alphabetical-start
rustc_abi = { path = "../rustc_abi" }
rustc_ast = { path = "../rustc_ast" }
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_hir = { path = "../rustc_hir" }
rustc_hir_pretty = { path = "../rustc_hir_pretty" }
rustc_middle = { path = "../rustc_middle" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }

View file

@ -255,7 +255,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
attr.iter().map(|seg| rustc_span::symbol::Symbol::intern(&seg)).collect();
tcx.get_attrs_by_path(did, &attr_name)
.map(|attribute| {
let attr_str = rustc_ast_pretty::pprust::attribute_to_string(attribute);
let attr_str = rustc_hir_pretty::attribute_to_string(&tcx, attribute);
let span = attribute.span;
stable_mir::crate_def::Attribute::new(attr_str, span.stable(&mut *tables))
})
@ -266,17 +266,16 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
let mut tables = self.0.borrow_mut();
let tcx = tables.tcx;
let did = tables[def_id];
let filter_fn = move |a: &&rustc_ast::ast::Attribute| {
matches!(a.kind, rustc_ast::ast::AttrKind::Normal(_))
};
let filter_fn =
move |a: &&rustc_hir::Attribute| matches!(a.kind, rustc_hir::AttrKind::Normal(_));
let attrs_iter = if let Some(did) = did.as_local() {
tcx.hir().attrs(tcx.local_def_id_to_hir_id(did)).iter().filter(filter_fn)
} else {
tcx.item_attrs(did).iter().filter(filter_fn)
tcx.attrs_for_def(did).iter().filter(filter_fn)
};
attrs_iter
.map(|attribute| {
let attr_str = rustc_ast_pretty::pprust::attribute_to_string(attribute);
let attr_str = rustc_hir_pretty::attribute_to_string(&tcx, attribute);
let span = attribute.span;
stable_mir::crate_def::Attribute::new(attr_str, span.stable(&mut *tables))
})

View file

@ -1,11 +1,12 @@
use std::iter;
use std::path::PathBuf;
use rustc_ast::{AttrArgs, AttrKind, Attribute, MetaItemInner};
use rustc_ast::MetaItemInner;
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::codes::*;
use rustc_errors::{ErrorGuaranteed, struct_span_code_err};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{AttrArgs, AttrKind, Attribute};
use rustc_macros::LintDiagnostic;
use rustc_middle::bug;
use rustc_middle::ty::print::PrintTraitRefExt as _;
@ -639,7 +640,7 @@ impl<'tcx> OnUnimplementedDirective {
let report_span = match &item.args {
AttrArgs::Empty => item.path.span,
AttrArgs::Delimited(args) => args.dspan.entire(),
AttrArgs::Eq { eq_span, expr } => eq_span.to(expr.span()),
AttrArgs::Eq { eq_span, expr } => eq_span.to(expr.span),
};
if let Some(item_def_id) = item_def_id.as_local() {
@ -654,7 +655,7 @@ impl<'tcx> OnUnimplementedDirective {
}
} else if is_diagnostic_namespace_variant {
match &attr.kind {
AttrKind::Normal(p) if !matches!(p.item.args, AttrArgs::Empty) => {
AttrKind::Normal(p) if !matches!(p.args, AttrArgs::Empty) => {
if let Some(item_def_id) = item_def_id.as_local() {
tcx.emit_node_span_lint(
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -2,14 +2,14 @@ use super::{Attribute, SHOULD_PANIC_WITHOUT_EXPECT};
use clippy_utils::diagnostics::span_lint_and_sugg;
use rustc_ast::token::{Token, TokenKind};
use rustc_ast::tokenstream::TokenTree;
use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind};
use rustc_ast::{AttrArgs, AttrKind};
use rustc_errors::Applicability;
use rustc_lint::EarlyContext;
use rustc_span::sym;
pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) {
if let AttrKind::Normal(normal_attr) = &attr.kind {
if let AttrArgs::Eq { expr: AttrArgsEq::Ast(_), .. } = &normal_attr.item.args {
if let AttrArgs::Eq { .. } = &normal_attr.item.args {
// `#[should_panic = ".."]` found, good
return;
}

View file

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

View file

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

View file

@ -1,18 +1,18 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_opt;
use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind, AttrStyle, Attribute};
use rustc_ast::{AttrStyle};
use rustc_errors::Applicability;
use rustc_lint::LateContext;
use rustc_span::sym;
use rustc_hir::{Attribute, AttrKind, AttrArgs};
use super::DOC_INCLUDE_WITHOUT_CFG;
pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) {
for attr in attrs {
if !attr.span.from_expansion()
&& let AttrKind::Normal(ref normal) = attr.kind
&& normal.item.path == sym::doc
&& let AttrArgs::Eq { expr: AttrArgsEq::Hir(ref meta), .. } = normal.item.args
&& let AttrKind::Normal(ref item) = attr.kind
&& attr.doc_str().is_some()
&& let AttrArgs::Eq { expr: meta, .. } = &item.args
&& !attr.span.contains(meta.span)
// Since the `include_str` is already expanded at this point, we can only take the
// whole attribute snippet and then modify for our suggestion.

View file

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

View file

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

View file

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

View file

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

View file

@ -2,8 +2,8 @@ use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::root_macro_call_first_node;
use clippy_utils::source::snippet_opt;
use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind, Attribute, LitKind};
use rustc_hir::{Expr, ExprKind};
use rustc_ast::{LitKind};
use rustc_hir::{Expr, ExprKind, Attribute, AttrArgs, AttrKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::impl_lint_pass;
use rustc_span::{Span, sym};
@ -93,10 +93,10 @@ impl LateLintPass<'_> for LargeIncludeFile {
if !attr.span.from_expansion()
// Currently, rustc limits the usage of macro at the top-level of attributes,
// so we don't need to recurse into each level.
&& let AttrKind::Normal(ref normal) = attr.kind
&& let AttrKind::Normal(ref item) = attr.kind
&& let Some(doc) = attr.doc_str()
&& doc.as_str().len() as u64 > self.max_file_size
&& let AttrArgs::Eq { expr: AttrArgsEq::Hir(ref meta), .. } = normal.item.args
&& let AttrArgs::Eq { expr: meta, .. } = &item.args
&& !attr.span.contains(meta.span)
// Since the `include_str` is already expanded at this point, we can only take the
// whole attribute snippet and then modify for our suggestion.

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -872,8 +872,7 @@ pub fn eq_attr_args(l: &AttrArgs, r: &AttrArgs) -> bool {
match (l, r) {
(Empty, Empty) => true,
(Delimited(la), Delimited(ra)) => eq_delim_args(la, ra),
(Eq { expr: AttrArgsEq::Ast(le), .. }, Eq{ expr: AttrArgsEq::Ast(re), .. }) => eq_expr(le, re),
(Eq { expr: AttrArgsEq::Hir(ll), .. }, Eq{ expr: AttrArgsEq::Hir(rl), .. }) => ll.kind == rl.kind,
(Eq { eq_span: _, expr: le }, Eq { eq_span: _, expr: re }) => eq_expr(le, re),
_ => false,
}
}

View file

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

View file

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

View file

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

View file

@ -7,9 +7,7 @@ extern crate std;
// issue#97006
macro_rules! m { ($attr_path: path) => { #[$attr_path] fn f() {} } }
#[
inline]
#[inline]
fn f() { }
fn main() { }