Add hir::Attribute
This commit is contained in:
parent
53b2c7cc95
commit
d50c0a5480
89 changed files with 1144 additions and 659 deletions
|
@ -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",
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
|
|
|
@ -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>,
|
||||
) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
})
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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]);
|
||||
]);
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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>>,
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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| {
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
})
|
||||
|
|
|
@ -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()),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
|
|
@ -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 }
|
||||
})
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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))
|
||||
})
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::iter::once;
|
|||
use std::sync::Arc;
|
||||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::Mutability;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{DefId, DefIdSet, LocalDefId, LocalModDefId};
|
||||
|
@ -15,7 +16,6 @@ use rustc_span::hygiene::MacroKind;
|
|||
use rustc_span::symbol::{Symbol, sym};
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
use tracing::{debug, trace};
|
||||
use {rustc_ast as ast, rustc_hir as hir};
|
||||
|
||||
use super::Item;
|
||||
use crate::clean::{
|
||||
|
@ -43,7 +43,7 @@ pub(crate) fn try_inline(
|
|||
cx: &mut DocContext<'_>,
|
||||
res: Res,
|
||||
name: Symbol,
|
||||
attrs: Option<(&[ast::Attribute], Option<LocalDefId>)>,
|
||||
attrs: Option<(&[hir::Attribute], Option<LocalDefId>)>,
|
||||
visited: &mut DefIdSet,
|
||||
) -> Option<Vec<clean::Item>> {
|
||||
let did = res.opt_def_id()?;
|
||||
|
@ -206,7 +206,7 @@ pub(crate) fn try_inline_glob(
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn load_attrs<'hir>(cx: &DocContext<'hir>, did: DefId) -> &'hir [ast::Attribute] {
|
||||
pub(crate) fn load_attrs<'hir>(cx: &DocContext<'hir>, did: DefId) -> &'hir [hir::Attribute] {
|
||||
cx.tcx.get_attrs_unchecked(did)
|
||||
}
|
||||
|
||||
|
@ -360,7 +360,7 @@ fn build_type_alias(
|
|||
pub(crate) fn build_impls(
|
||||
cx: &mut DocContext<'_>,
|
||||
did: DefId,
|
||||
attrs: Option<(&[ast::Attribute], Option<LocalDefId>)>,
|
||||
attrs: Option<(&[hir::Attribute], Option<LocalDefId>)>,
|
||||
ret: &mut Vec<clean::Item>,
|
||||
) {
|
||||
let _prof_timer = cx.tcx.sess.prof.generic_activity("build_inherent_impls");
|
||||
|
@ -392,8 +392,8 @@ pub(crate) fn build_impls(
|
|||
|
||||
pub(crate) fn merge_attrs(
|
||||
cx: &mut DocContext<'_>,
|
||||
old_attrs: &[ast::Attribute],
|
||||
new_attrs: Option<(&[ast::Attribute], Option<LocalDefId>)>,
|
||||
old_attrs: &[hir::Attribute],
|
||||
new_attrs: Option<(&[hir::Attribute], Option<LocalDefId>)>,
|
||||
) -> (clean::Attributes, Option<Arc<clean::cfg::Cfg>>) {
|
||||
// NOTE: If we have additional attributes (from a re-export),
|
||||
// always insert them first. This ensure that re-export
|
||||
|
@ -404,14 +404,14 @@ pub(crate) fn merge_attrs(
|
|||
both.extend_from_slice(old_attrs);
|
||||
(
|
||||
if let Some(item_id) = item_id {
|
||||
Attributes::from_ast_with_additional(old_attrs, (inner, item_id.to_def_id()))
|
||||
Attributes::from_hir_with_additional(old_attrs, (inner, item_id.to_def_id()))
|
||||
} else {
|
||||
Attributes::from_ast(&both)
|
||||
Attributes::from_hir(&both)
|
||||
},
|
||||
both.cfg(cx.tcx, &cx.cache.hidden_cfg),
|
||||
)
|
||||
} else {
|
||||
(Attributes::from_ast(old_attrs), old_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg))
|
||||
(Attributes::from_hir(old_attrs), old_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -419,7 +419,7 @@ pub(crate) fn merge_attrs(
|
|||
pub(crate) fn build_impl(
|
||||
cx: &mut DocContext<'_>,
|
||||
did: DefId,
|
||||
attrs: Option<(&[ast::Attribute], Option<LocalDefId>)>,
|
||||
attrs: Option<(&[hir::Attribute], Option<LocalDefId>)>,
|
||||
ret: &mut Vec<clean::Item>,
|
||||
) {
|
||||
if !cx.inlined.insert(did.into()) {
|
||||
|
@ -629,7 +629,7 @@ fn build_module_items(
|
|||
visited: &mut DefIdSet,
|
||||
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
|
||||
allowed_def_ids: Option<&DefIdSet>,
|
||||
attrs: Option<(&[ast::Attribute], Option<LocalDefId>)>,
|
||||
attrs: Option<(&[hir::Attribute], Option<LocalDefId>)>,
|
||||
) -> Vec<clean::Item> {
|
||||
let mut items = Vec::new();
|
||||
|
||||
|
|
|
@ -201,7 +201,7 @@ fn generate_item_with_correct_attrs(
|
|||
};
|
||||
|
||||
let cfg = attrs.cfg(cx.tcx, &cx.cache.hidden_cfg);
|
||||
let attrs = Attributes::from_ast_iter(attrs.iter().map(|(attr, did)| (&**attr, *did)), false);
|
||||
let attrs = Attributes::from_hir_iter(attrs.iter().map(|(attr, did)| (&**attr, *did)), false);
|
||||
|
||||
let name = renamed.or(Some(name));
|
||||
let mut item = Item::from_def_id_and_attrs_and_parts(def_id, name, kind, attrs, cfg);
|
||||
|
@ -1036,7 +1036,7 @@ fn clean_fn_or_proc_macro<'tcx>(
|
|||
/// This is needed to make it more "readable" when documenting functions using
|
||||
/// `rustc_legacy_const_generics`. More information in
|
||||
/// <https://github.com/rust-lang/rust/issues/83167>.
|
||||
fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[ast::Attribute]) {
|
||||
fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[hir::Attribute]) {
|
||||
for meta_item_list in attrs
|
||||
.iter()
|
||||
.filter(|a| a.has_name(sym::rustc_legacy_const_generics))
|
||||
|
@ -2578,7 +2578,7 @@ fn get_all_import_attributes<'hir>(
|
|||
import_def_id: LocalDefId,
|
||||
target_def_id: DefId,
|
||||
is_inline: bool,
|
||||
) -> Vec<(Cow<'hir, ast::Attribute>, Option<DefId>)> {
|
||||
) -> Vec<(Cow<'hir, hir::Attribute>, Option<DefId>)> {
|
||||
let mut attrs = Vec::new();
|
||||
let mut first = true;
|
||||
for def_id in reexport_chain(cx.tcx, import_def_id, target_def_id)
|
||||
|
@ -2631,9 +2631,9 @@ fn filter_doc_attr_ident(ident: Symbol, is_inline: bool) -> bool {
|
|||
|
||||
/// Remove attributes from `normal` that should not be inherited by `use` re-export.
|
||||
/// Before calling this function, make sure `normal` is a `#[doc]` attribute.
|
||||
fn filter_doc_attr(normal: &mut ast::NormalAttr, is_inline: bool) {
|
||||
match normal.item.args {
|
||||
ast::AttrArgs::Delimited(ref mut args) => {
|
||||
fn filter_doc_attr(args: &mut hir::AttrArgs, is_inline: bool) {
|
||||
match args {
|
||||
hir::AttrArgs::Delimited(ref mut args) => {
|
||||
let tokens = filter_tokens_from_list(&args.tokens, |token| {
|
||||
!matches!(
|
||||
token,
|
||||
|
@ -2651,7 +2651,7 @@ fn filter_doc_attr(normal: &mut ast::NormalAttr, is_inline: bool) {
|
|||
});
|
||||
args.tokens = TokenStream::new(tokens);
|
||||
}
|
||||
ast::AttrArgs::Empty | ast::AttrArgs::Eq { .. } => {}
|
||||
hir::AttrArgs::Empty | hir::AttrArgs::Eq { .. } => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2676,23 +2676,23 @@ fn filter_doc_attr(normal: &mut ast::NormalAttr, is_inline: bool) {
|
|||
/// * `doc(no_inline)`
|
||||
/// * `doc(hidden)`
|
||||
fn add_without_unwanted_attributes<'hir>(
|
||||
attrs: &mut Vec<(Cow<'hir, ast::Attribute>, Option<DefId>)>,
|
||||
new_attrs: &'hir [ast::Attribute],
|
||||
attrs: &mut Vec<(Cow<'hir, hir::Attribute>, Option<DefId>)>,
|
||||
new_attrs: &'hir [hir::Attribute],
|
||||
is_inline: bool,
|
||||
import_parent: Option<DefId>,
|
||||
) {
|
||||
for attr in new_attrs {
|
||||
if matches!(attr.kind, ast::AttrKind::DocComment(..)) {
|
||||
if matches!(attr.kind, hir::AttrKind::DocComment(..)) {
|
||||
attrs.push((Cow::Borrowed(attr), import_parent));
|
||||
continue;
|
||||
}
|
||||
let mut attr = attr.clone();
|
||||
match attr.kind {
|
||||
ast::AttrKind::Normal(ref mut normal) => {
|
||||
if let [ident] = &*normal.item.path.segments {
|
||||
let ident = ident.ident.name;
|
||||
hir::AttrKind::Normal(ref mut normal) => {
|
||||
if let [ident] = &*normal.path.segments {
|
||||
let ident = ident.name;
|
||||
if ident == sym::doc {
|
||||
filter_doc_attr(normal, is_inline);
|
||||
filter_doc_attr(&mut normal.args, is_inline);
|
||||
attrs.push((Cow::Owned(attr), import_parent));
|
||||
} else if is_inline || ident != sym::cfg {
|
||||
// If it's not a `cfg()` attribute, we keep it.
|
||||
|
|
|
@ -6,8 +6,6 @@ use std::{fmt, iter};
|
|||
|
||||
use arrayvec::ArrayVec;
|
||||
use rustc_abi::{ExternAbi, VariantIdx};
|
||||
use rustc_ast::MetaItemInner;
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_attr::{ConstStability, Deprecation, Stability, StableSince};
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||
|
@ -454,14 +452,14 @@ impl Item {
|
|||
kind: ItemKind,
|
||||
cx: &mut DocContext<'_>,
|
||||
) -> Item {
|
||||
let ast_attrs = cx.tcx.get_attrs_unchecked(def_id);
|
||||
let hir_attrs = cx.tcx.get_attrs_unchecked(def_id);
|
||||
|
||||
Self::from_def_id_and_attrs_and_parts(
|
||||
def_id,
|
||||
name,
|
||||
kind,
|
||||
Attributes::from_ast(ast_attrs),
|
||||
ast_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
|
||||
Attributes::from_hir(hir_attrs),
|
||||
hir_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -742,10 +740,10 @@ impl Item {
|
|||
.iter()
|
||||
.filter_map(|attr| {
|
||||
if keep_as_is {
|
||||
Some(pprust::attribute_to_string(attr))
|
||||
Some(rustc_hir_pretty::attribute_to_string(&tcx, attr))
|
||||
} else if ALLOWED_ATTRIBUTES.contains(&attr.name_or_empty()) {
|
||||
Some(
|
||||
pprust::attribute_to_string(attr)
|
||||
rustc_hir_pretty::attribute_to_string(&tcx, attr)
|
||||
.replace("\\\n", "")
|
||||
.replace('\n', "")
|
||||
.replace(" ", " "),
|
||||
|
@ -955,7 +953,7 @@ pub(crate) trait AttributesExt {
|
|||
type AttributeIterator<'a>: Iterator<Item = ast::MetaItemInner>
|
||||
where
|
||||
Self: 'a;
|
||||
type Attributes<'a>: Iterator<Item = &'a ast::Attribute>
|
||||
type Attributes<'a>: Iterator<Item = &'a hir::Attribute>
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
|
@ -1009,7 +1007,7 @@ pub(crate) trait AttributesExt {
|
|||
// #[doc]
|
||||
if attr.doc_str().is_none() && attr.has_name(sym::doc) {
|
||||
// #[doc(...)]
|
||||
if let Some(list) = attr.meta().as_ref().and_then(|mi| mi.meta_item_list()) {
|
||||
if let Some(list) = attr.meta_item_list() {
|
||||
for item in list {
|
||||
// #[doc(hidden)]
|
||||
if !item.has_name(sym::cfg) {
|
||||
|
@ -1042,7 +1040,7 @@ pub(crate) trait AttributesExt {
|
|||
let mut meta = attr.meta_item().unwrap().clone();
|
||||
meta.path = ast::Path::from_ident(Ident::with_dummy_span(sym::target_feature));
|
||||
|
||||
if let Ok(feat_cfg) = Cfg::parse(&MetaItemInner::MetaItem(meta)) {
|
||||
if let Ok(feat_cfg) = Cfg::parse(&ast::MetaItemInner::MetaItem(meta)) {
|
||||
cfg &= feat_cfg;
|
||||
}
|
||||
}
|
||||
|
@ -1053,14 +1051,14 @@ pub(crate) trait AttributesExt {
|
|||
}
|
||||
}
|
||||
|
||||
impl AttributesExt for [ast::Attribute] {
|
||||
impl AttributesExt for [hir::Attribute] {
|
||||
type AttributeIterator<'a> = impl Iterator<Item = ast::MetaItemInner> + 'a;
|
||||
type Attributes<'a> = impl Iterator<Item = &'a ast::Attribute> + 'a;
|
||||
type Attributes<'a> = impl Iterator<Item = &'a hir::Attribute> + 'a;
|
||||
|
||||
fn lists(&self, name: Symbol) -> Self::AttributeIterator<'_> {
|
||||
self.iter()
|
||||
.filter(move |attr| attr.has_name(name))
|
||||
.filter_map(ast::Attribute::meta_item_list)
|
||||
.filter_map(ast::attr::AttributeExt::meta_item_list)
|
||||
.flatten()
|
||||
}
|
||||
|
||||
|
@ -1069,20 +1067,20 @@ impl AttributesExt for [ast::Attribute] {
|
|||
}
|
||||
}
|
||||
|
||||
impl AttributesExt for [(Cow<'_, ast::Attribute>, Option<DefId>)] {
|
||||
impl AttributesExt for [(Cow<'_, hir::Attribute>, Option<DefId>)] {
|
||||
type AttributeIterator<'a>
|
||||
= impl Iterator<Item = ast::MetaItemInner> + 'a
|
||||
where
|
||||
Self: 'a;
|
||||
type Attributes<'a>
|
||||
= impl Iterator<Item = &'a ast::Attribute> + 'a
|
||||
= impl Iterator<Item = &'a hir::Attribute> + 'a
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
fn lists(&self, name: Symbol) -> Self::AttributeIterator<'_> {
|
||||
AttributesExt::iter(self)
|
||||
.filter(move |attr| attr.has_name(name))
|
||||
.filter_map(ast::Attribute::meta_item_list)
|
||||
.filter_map(hir::Attribute::meta_item_list)
|
||||
.flatten()
|
||||
}
|
||||
|
||||
|
@ -1152,7 +1150,7 @@ pub struct RenderedLink {
|
|||
#[derive(Clone, Debug, Default)]
|
||||
pub(crate) struct Attributes {
|
||||
pub(crate) doc_strings: Vec<DocFragment>,
|
||||
pub(crate) other_attrs: ast::AttrVec,
|
||||
pub(crate) other_attrs: Vec<hir::Attribute>,
|
||||
}
|
||||
|
||||
impl Attributes {
|
||||
|
@ -1180,22 +1178,22 @@ impl Attributes {
|
|||
self.has_doc_flag(sym::hidden)
|
||||
}
|
||||
|
||||
pub(crate) fn from_ast(attrs: &[ast::Attribute]) -> Attributes {
|
||||
Attributes::from_ast_iter(attrs.iter().map(|attr| (attr, None)), false)
|
||||
pub(crate) fn from_hir(attrs: &[hir::Attribute]) -> Attributes {
|
||||
Attributes::from_hir_iter(attrs.iter().map(|attr| (attr, None)), false)
|
||||
}
|
||||
|
||||
pub(crate) fn from_ast_with_additional(
|
||||
attrs: &[ast::Attribute],
|
||||
(additional_attrs, def_id): (&[ast::Attribute], DefId),
|
||||
pub(crate) fn from_hir_with_additional(
|
||||
attrs: &[hir::Attribute],
|
||||
(additional_attrs, def_id): (&[hir::Attribute], DefId),
|
||||
) -> Attributes {
|
||||
// Additional documentation should be shown before the original documentation.
|
||||
let attrs1 = additional_attrs.iter().map(|attr| (attr, Some(def_id)));
|
||||
let attrs2 = attrs.iter().map(|attr| (attr, None));
|
||||
Attributes::from_ast_iter(attrs1.chain(attrs2), false)
|
||||
Attributes::from_hir_iter(attrs1.chain(attrs2), false)
|
||||
}
|
||||
|
||||
pub(crate) fn from_ast_iter<'a>(
|
||||
attrs: impl Iterator<Item = (&'a ast::Attribute, Option<DefId>)>,
|
||||
pub(crate) fn from_hir_iter<'a>(
|
||||
attrs: impl Iterator<Item = (&'a hir::Attribute, Option<DefId>)>,
|
||||
doc_only: bool,
|
||||
) -> Attributes {
|
||||
let (doc_strings, other_attrs) = attrs_to_doc_fragments(attrs, doc_only);
|
||||
|
|
|
@ -578,7 +578,7 @@ pub(crate) fn has_doc_flag(tcx: TyCtxt<'_>, did: DefId, flag: Symbol) -> bool {
|
|||
}
|
||||
|
||||
pub(crate) fn attrs_have_doc_flag<'a>(
|
||||
mut attrs: impl Iterator<Item = &'a ast::Attribute>,
|
||||
mut attrs: impl Iterator<Item = &'a hir::Attribute>,
|
||||
flag: Symbol,
|
||||
) -> bool {
|
||||
attrs
|
||||
|
|
|
@ -13,10 +13,10 @@ use std::{panic, str};
|
|||
|
||||
pub(crate) use make::DocTestBuilder;
|
||||
pub(crate) use markdown::test as test_markdown;
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
|
||||
use rustc_errors::emitter::HumanReadableErrorType;
|
||||
use rustc_errors::{ColorConfig, DiagCtxtHandle};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::CRATE_HIR_ID;
|
||||
use rustc_hir::def_id::LOCAL_CRATE;
|
||||
use rustc_interface::interface;
|
||||
|
@ -325,7 +325,7 @@ pub(crate) fn run_tests(
|
|||
// Look for `#![doc(test(no_crate_inject))]`, used by crates in the std facade.
|
||||
fn scrape_test_config(
|
||||
crate_name: String,
|
||||
attrs: &[ast::Attribute],
|
||||
attrs: &[hir::Attribute],
|
||||
args_file: PathBuf,
|
||||
) -> GlobalTestOptions {
|
||||
use rustc_ast_pretty::pprust;
|
||||
|
|
|
@ -110,7 +110,7 @@ impl HirCollector<'_> {
|
|||
|
||||
// The collapse-docs pass won't combine sugared/raw doc attributes, or included files with
|
||||
// anything else, this will combine them for us.
|
||||
let attrs = Attributes::from_ast(ast_attrs);
|
||||
let attrs = Attributes::from_hir(ast_attrs);
|
||||
if let Some(doc) = attrs.opt_doc_value() {
|
||||
let span = span_of_fragments(&attrs.doc_strings).unwrap_or(sp);
|
||||
self.collector.position = if span.edition().at_least_rust_2024() {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use super::INLINE_ALWAYS;
|
||||
use super::utils::is_word;
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use rustc_ast::Attribute;
|
||||
use rustc_hir::Attribute;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::{Span, sym};
|
||||
|
|
|
@ -2,14 +2,14 @@ use super::{Attribute, SHOULD_PANIC_WITHOUT_EXPECT};
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use rustc_ast::token::{Token, TokenKind};
|
||||
use rustc_ast::tokenstream::TokenTree;
|
||||
use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind};
|
||||
use rustc_ast::{AttrArgs, AttrKind};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::EarlyContext;
|
||||
use rustc_span::sym;
|
||||
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) {
|
||||
if let AttrKind::Normal(normal_attr) = &attr.kind {
|
||||
if let AttrArgs::Eq { expr: AttrArgsEq::Ast(_), .. } = &normal_attr.item.args {
|
||||
if let AttrArgs::Eq { .. } = &normal_attr.item.args {
|
||||
// `#[should_panic = ".."]` found, good
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -5,9 +5,8 @@ use clippy_utils::ty::is_type_diagnostic_item;
|
|||
use clippy_utils::visitors::for_each_expr_without_closures;
|
||||
use clippy_utils::{LimitStack, get_async_fn_body, is_async_fn};
|
||||
use core::ops::ControlFlow;
|
||||
use rustc_ast::ast::Attribute;
|
||||
use rustc_hir::intravisit::FnKind;
|
||||
use rustc_hir::{Body, Expr, ExprKind, FnDecl};
|
||||
use rustc_hir::{Attribute, Body, Expr, ExprKind, FnDecl};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
|
|
|
@ -2,10 +2,10 @@ use clippy_utils::diagnostics::span_lint_and_then;
|
|||
use clippy_utils::source::{SpanRangeExt, snippet_indent};
|
||||
use clippy_utils::tokenize_with_text;
|
||||
use itertools::Itertools;
|
||||
use rustc_ast::AttrStyle;
|
||||
use rustc_ast::token::CommentKind;
|
||||
use rustc_ast::{AttrKind, AttrStyle, Attribute};
|
||||
use rustc_errors::{Applicability, Diag, SuggestionStyle};
|
||||
use rustc_hir::{ItemKind, Node};
|
||||
use rustc_hir::{AttrKind, Attribute, ItemKind, Node};
|
||||
use rustc_lexer::TokenKind;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::{BytePos, ExpnKind, InnerSpan, Span, SpanData};
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind, AttrStyle, Attribute};
|
||||
use rustc_ast::{AttrStyle};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::sym;
|
||||
use rustc_hir::{Attribute, AttrKind, AttrArgs};
|
||||
|
||||
use super::DOC_INCLUDE_WITHOUT_CFG;
|
||||
|
||||
pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) {
|
||||
for attr in attrs {
|
||||
if !attr.span.from_expansion()
|
||||
&& let AttrKind::Normal(ref normal) = attr.kind
|
||||
&& normal.item.path == sym::doc
|
||||
&& let AttrArgs::Eq { 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.
|
||||
|
|
|
@ -16,10 +16,9 @@ use pulldown_cmark::Event::{
|
|||
};
|
||||
use pulldown_cmark::Tag::{BlockQuote, CodeBlock, FootnoteDefinition, Heading, Item, Link, Paragraph};
|
||||
use pulldown_cmark::{BrokenLink, CodeBlockKind, CowStr, Options, TagEnd};
|
||||
use rustc_ast::ast::Attribute;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::{AnonConst, Expr, ImplItemKind, ItemKind, Node, Safety, TraitItemKind};
|
||||
use rustc_hir::{AnonConst, Attribute, Expr, ImplItemKind, ItemKind, Node, Safety, TraitItemKind};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use rustc_ast::AttrStyle;
|
||||
use rustc_ast::token::CommentKind;
|
||||
use rustc_ast::{AttrKind, AttrStyle, Attribute};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::Attribute;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::Span;
|
||||
|
||||
|
@ -35,7 +36,7 @@ fn collect_doc_replacements(attrs: &[Attribute]) -> Vec<(Span, String)> {
|
|||
attrs
|
||||
.iter()
|
||||
.filter_map(|attr| {
|
||||
if let AttrKind::DocComment(com_kind, sym) = attr.kind
|
||||
if let Some((sym, com_kind)) = attr.doc_str_and_comment_kind()
|
||||
&& let AttrStyle::Outer = attr.style
|
||||
&& let Some(com) = sym.as_str().strip_prefix('!')
|
||||
{
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use rustc_ast::ast::Attribute;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Item, ItemKind};
|
||||
use rustc_hir::{Attribute, Item, ItemKind};
|
||||
use rustc_lint::LateContext;
|
||||
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
use hir::FnSig;
|
||||
use rustc_ast::ast::Attribute;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::def_id::DefIdSet;
|
||||
use rustc_hir::{self as hir, QPath};
|
||||
use rustc_hir::{self as hir, Attribute, QPath};
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
|
|
|
@ -2,8 +2,8 @@ use clippy_config::Conf;
|
|||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::macros::root_macro_call_first_node;
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind, Attribute, LitKind};
|
||||
use rustc_hir::{Expr, ExprKind};
|
||||
use rustc_ast::{LitKind};
|
||||
use rustc_hir::{Expr, ExprKind, Attribute, AttrArgs, AttrKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::{Span, sym};
|
||||
|
@ -93,10 +93,10 @@ impl LateLintPass<'_> for LargeIncludeFile {
|
|||
if !attr.span.from_expansion()
|
||||
// Currently, rustc limits the usage of macro at the top-level of attributes,
|
||||
// so we don't need to recurse into each level.
|
||||
&& let AttrKind::Normal(ref normal) = attr.kind
|
||||
&& let AttrKind::Normal(ref item) = attr.kind
|
||||
&& let Some(doc) = attr.doc_str()
|
||||
&& doc.as_str().len() as u64 > self.max_file_size
|
||||
&& let AttrArgs::Eq { 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.
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use clippy_utils::diagnostics::span_lint_hir_and_then;
|
||||
use clippy_utils::source::snippet;
|
||||
use hir::def::{DefKind, Res};
|
||||
use rustc_ast::ast;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
|
@ -104,7 +103,7 @@ impl LateLintPass<'_> for MacroUseImports {
|
|||
self.push_unique_macro_pat_ty(cx, item.span);
|
||||
}
|
||||
}
|
||||
fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) {
|
||||
fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &hir::Attribute) {
|
||||
if attr.span.from_expansion() {
|
||||
self.push_unique_macro(cx, attr.span);
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@ use super::REDUNDANT_PATTERN_MATCHING;
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use clippy_utils::{is_lint_allowed, is_wild, span_contains_comment};
|
||||
use rustc_ast::{Attribute, LitKind};
|
||||
use rustc_ast::LitKind;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Arm, BorrowKind, Expr, ExprKind, Pat, PatKind, QPath};
|
||||
use rustc_hir::{Arm, Attribute, BorrowKind, Expr, ExprKind, Pat, PatKind, QPath};
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_middle::ty;
|
||||
use rustc_span::source_map::Spanned;
|
||||
|
|
|
@ -10,8 +10,9 @@ use clippy_utils::attrs::is_doc_hidden;
|
|||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::is_from_proc_macro;
|
||||
use clippy_utils::source::SpanRangeExt;
|
||||
use rustc_ast::ast::{self, MetaItem, MetaItemKind};
|
||||
use rustc_ast::ast::MetaItemInner;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::Attribute;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
|
@ -67,9 +68,8 @@ impl MissingDoc {
|
|||
*self.doc_hidden_stack.last().expect("empty doc_hidden_stack")
|
||||
}
|
||||
|
||||
fn has_include(meta: Option<MetaItem>) -> bool {
|
||||
if let Some(meta) = meta
|
||||
&& let MetaItemKind::List(list) = meta.kind
|
||||
fn has_include(meta: Option<&[MetaItemInner]>) -> bool {
|
||||
if let Some(list) = meta
|
||||
&& let Some(meta) = list.first()
|
||||
&& let Some(name) = meta.ident()
|
||||
{
|
||||
|
@ -83,7 +83,7 @@ impl MissingDoc {
|
|||
&self,
|
||||
cx: &LateContext<'_>,
|
||||
def_id: LocalDefId,
|
||||
attrs: &[ast::Attribute],
|
||||
attrs: &[Attribute],
|
||||
sp: Span,
|
||||
article: &'static str,
|
||||
desc: &'static str,
|
||||
|
@ -129,7 +129,7 @@ impl MissingDoc {
|
|||
|
||||
let has_doc = attrs
|
||||
.iter()
|
||||
.any(|a| a.doc_str().is_some() || Self::has_include(a.meta()))
|
||||
.any(|a| a.doc_str().is_some() || Self::has_include(a.meta_item_list().as_deref()))
|
||||
|| matches!(self.search_span(sp), Some(span) if span_to_snippet_contains_docs(cx, span));
|
||||
|
||||
if !has_doc {
|
||||
|
@ -172,12 +172,12 @@ impl MissingDoc {
|
|||
impl_lint_pass!(MissingDoc => [MISSING_DOCS_IN_PRIVATE_ITEMS]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for MissingDoc {
|
||||
fn check_attributes(&mut self, _: &LateContext<'tcx>, attrs: &'tcx [ast::Attribute]) {
|
||||
fn check_attributes(&mut self, _: &LateContext<'tcx>, attrs: &'tcx [Attribute]) {
|
||||
let doc_hidden = self.doc_hidden() || is_doc_hidden(attrs);
|
||||
self.doc_hidden_stack.push(doc_hidden);
|
||||
}
|
||||
|
||||
fn check_attributes_post(&mut self, _: &LateContext<'tcx>, _: &'tcx [ast::Attribute]) {
|
||||
fn check_attributes_post(&mut self, _: &LateContext<'tcx>, _: &'tcx [Attribute]) {
|
||||
self.doc_hidden_stack.pop().expect("empty doc_hidden_stack");
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use clippy_utils::diagnostics::span_lint;
|
||||
use rustc_ast::ast;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::Attribute;
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_middle::ty::AssocItemContainer;
|
||||
use rustc_session::declare_lint_pass;
|
||||
|
@ -63,7 +63,7 @@ declare_clippy_lint! {
|
|||
"detects missing `#[inline]` attribute for public callables (functions, trait methods, methods...)"
|
||||
}
|
||||
|
||||
fn check_missing_inline_attrs(cx: &LateContext<'_>, attrs: &[ast::Attribute], sp: Span, desc: &'static str) {
|
||||
fn check_missing_inline_attrs(cx: &LateContext<'_>, attrs: &[Attribute], sp: Span, desc: &'static str) {
|
||||
let has_inline = attrs.iter().any(|a| a.has_name(sym::inline));
|
||||
if !has_inline {
|
||||
span_lint(
|
||||
|
|
|
@ -5,12 +5,11 @@ use clippy_utils::source::{SpanRangeExt, snippet};
|
|||
use clippy_utils::ty::{
|
||||
implements_trait, implements_trait_with_env_from_iter, is_copy, is_type_diagnostic_item, is_type_lang_item,
|
||||
};
|
||||
use rustc_ast::ast::Attribute;
|
||||
use rustc_errors::{Applicability, Diag};
|
||||
use rustc_hir::intravisit::FnKind;
|
||||
use rustc_hir::{
|
||||
BindingMode, Body, FnDecl, GenericArg, HirId, HirIdSet, Impl, ItemKind, LangItem, Mutability, Node, PatKind, QPath,
|
||||
TyKind,
|
||||
Attribute, BindingMode, Body, FnDecl, GenericArg, HirId, HirIdSet, Impl, ItemKind, LangItem, Mutability, Node,
|
||||
PatKind, QPath, TyKind,
|
||||
};
|
||||
use rustc_hir_typeck::expr_use_visitor as euv;
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
|
|
|
@ -872,8 +872,7 @@ pub fn eq_attr_args(l: &AttrArgs, r: &AttrArgs) -> bool {
|
|||
match (l, r) {
|
||||
(Empty, Empty) => true,
|
||||
(Delimited(la), Delimited(ra)) => eq_delim_args(la, ra),
|
||||
(Eq { 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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use rustc_ast::{ast, attr};
|
||||
use rustc_ast::attr;
|
||||
use rustc_ast::attr::AttributeExt;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lexer::TokenKind;
|
||||
use rustc_lint::LateContext;
|
||||
|
@ -51,33 +52,31 @@ impl LimitStack {
|
|||
pub fn limit(&self) -> u64 {
|
||||
*self.stack.last().expect("there should always be a value in the stack")
|
||||
}
|
||||
pub fn push_attrs(&mut self, sess: &Session, attrs: &[ast::Attribute], name: &'static str) {
|
||||
pub fn push_attrs(&mut self, sess: &Session, attrs: &[impl AttributeExt], name: &'static str) {
|
||||
let stack = &mut self.stack;
|
||||
parse_attrs(sess, attrs, name, |val| stack.push(val));
|
||||
}
|
||||
pub fn pop_attrs(&mut self, sess: &Session, attrs: &[ast::Attribute], name: &'static str) {
|
||||
pub fn pop_attrs(&mut self, sess: &Session, attrs: &[impl AttributeExt], name: &'static str) {
|
||||
let stack = &mut self.stack;
|
||||
parse_attrs(sess, attrs, name, |val| assert_eq!(stack.pop(), Some(val)));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_attr<'a>(
|
||||
pub fn get_attr<'a, A: AttributeExt + 'a>(
|
||||
sess: &'a Session,
|
||||
attrs: &'a [ast::Attribute],
|
||||
attrs: &'a [A],
|
||||
name: &'static str,
|
||||
) -> impl Iterator<Item = &'a ast::Attribute> {
|
||||
) -> impl Iterator<Item = &'a A> {
|
||||
attrs.iter().filter(move |attr| {
|
||||
let attr = if let ast::AttrKind::Normal(ref normal) = attr.kind {
|
||||
&normal.item
|
||||
} else {
|
||||
let Some(attr_segments) = attr.ident_path() else {
|
||||
return false;
|
||||
};
|
||||
let attr_segments = &attr.path.segments;
|
||||
if attr_segments.len() == 2 && attr_segments[0].ident.name == sym::clippy {
|
||||
|
||||
if attr_segments.len() == 2 && attr_segments[0].name == sym::clippy {
|
||||
BUILTIN_ATTRIBUTES
|
||||
.iter()
|
||||
.find_map(|&(builtin_name, ref deprecation_status)| {
|
||||
if attr_segments[1].ident.name.as_str() == builtin_name {
|
||||
if attr_segments[1].name.as_str() == builtin_name {
|
||||
Some(deprecation_status)
|
||||
} else {
|
||||
None
|
||||
|
@ -85,14 +84,13 @@ pub fn get_attr<'a>(
|
|||
})
|
||||
.map_or_else(
|
||||
|| {
|
||||
sess.dcx()
|
||||
.span_err(attr_segments[1].ident.span, "usage of unknown attribute");
|
||||
sess.dcx().span_err(attr_segments[1].span, "usage of unknown attribute");
|
||||
false
|
||||
},
|
||||
|deprecation_status| {
|
||||
let mut diag = sess
|
||||
.dcx()
|
||||
.struct_span_err(attr_segments[1].ident.span, "usage of deprecated attribute");
|
||||
.struct_span_err(attr_segments[1].span, "usage of deprecated attribute");
|
||||
match *deprecation_status {
|
||||
DeprecationStatus::Deprecated => {
|
||||
diag.emit();
|
||||
|
@ -100,7 +98,7 @@ pub fn get_attr<'a>(
|
|||
},
|
||||
DeprecationStatus::Replaced(new_name) => {
|
||||
diag.span_suggestion(
|
||||
attr_segments[1].ident.span,
|
||||
attr_segments[1].span,
|
||||
"consider using",
|
||||
new_name,
|
||||
Applicability::MachineApplicable,
|
||||
|
@ -110,7 +108,7 @@ pub fn get_attr<'a>(
|
|||
},
|
||||
DeprecationStatus::None => {
|
||||
diag.cancel();
|
||||
attr_segments[1].ident.name.as_str() == name
|
||||
attr_segments[1].as_str() == name
|
||||
},
|
||||
}
|
||||
},
|
||||
|
@ -121,31 +119,31 @@ pub fn get_attr<'a>(
|
|||
})
|
||||
}
|
||||
|
||||
fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &'static str, mut f: F) {
|
||||
fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[impl AttributeExt], name: &'static str, mut f: F) {
|
||||
for attr in get_attr(sess, attrs, name) {
|
||||
if let Some(ref value) = attr.value_str() {
|
||||
if let Ok(value) = FromStr::from_str(value.as_str()) {
|
||||
f(value);
|
||||
} else {
|
||||
sess.dcx().span_err(attr.span, "not a number");
|
||||
sess.dcx().span_err(attr.span(), "not a number");
|
||||
}
|
||||
} else {
|
||||
sess.dcx().span_err(attr.span, "bad clippy attribute");
|
||||
sess.dcx().span_err(attr.span(), "bad clippy attribute");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_unique_attr<'a>(
|
||||
pub fn get_unique_attr<'a, A: AttributeExt>(
|
||||
sess: &'a Session,
|
||||
attrs: &'a [ast::Attribute],
|
||||
attrs: &'a [A],
|
||||
name: &'static str,
|
||||
) -> Option<&'a ast::Attribute> {
|
||||
let mut unique_attr: Option<&ast::Attribute> = None;
|
||||
) -> Option<&'a A> {
|
||||
let mut unique_attr: Option<&A> = None;
|
||||
for attr in get_attr(sess, attrs, name) {
|
||||
if let Some(duplicate) = unique_attr {
|
||||
sess.dcx()
|
||||
.struct_span_err(attr.span, format!("`{name}` is defined multiple times"))
|
||||
.with_span_note(duplicate.span, "first definition found here")
|
||||
.struct_span_err(attr.span(), format!("`{name}` is defined multiple times"))
|
||||
.with_span_note(duplicate.span(), "first definition found here")
|
||||
.emit();
|
||||
} else {
|
||||
unique_attr = Some(attr);
|
||||
|
@ -156,16 +154,16 @@ pub fn get_unique_attr<'a>(
|
|||
|
||||
/// Returns true if the attributes contain any of `proc_macro`,
|
||||
/// `proc_macro_derive` or `proc_macro_attribute`, false otherwise
|
||||
pub fn is_proc_macro(attrs: &[ast::Attribute]) -> bool {
|
||||
attrs.iter().any(rustc_ast::Attribute::is_proc_macro_attr)
|
||||
pub fn is_proc_macro(attrs: &[impl AttributeExt]) -> bool {
|
||||
attrs.iter().any(AttributeExt::is_proc_macro_attr)
|
||||
}
|
||||
|
||||
/// Returns true if the attributes contain `#[doc(hidden)]`
|
||||
pub fn is_doc_hidden(attrs: &[ast::Attribute]) -> bool {
|
||||
pub fn is_doc_hidden(attrs: &[impl AttributeExt]) -> bool {
|
||||
attrs
|
||||
.iter()
|
||||
.filter(|attr| attr.has_name(sym::doc))
|
||||
.filter_map(ast::Attribute::meta_item_list)
|
||||
.filter_map(AttributeExt::meta_item_list)
|
||||
.any(|l| attr::list_contains_name(&l, sym::hidden))
|
||||
}
|
||||
|
||||
|
|
|
@ -135,13 +135,24 @@ use rustc_middle::hir::nested_filter;
|
|||
|
||||
#[macro_export]
|
||||
macro_rules! extract_msrv_attr {
|
||||
($context:ident) => {
|
||||
fn check_attributes(&mut self, cx: &rustc_lint::$context<'_>, attrs: &[rustc_ast::ast::Attribute]) {
|
||||
(LateContext) => {
|
||||
fn check_attributes(&mut self, cx: &rustc_lint::LateContext<'_>, attrs: &[rustc_hir::Attribute]) {
|
||||
let sess = rustc_lint::LintContext::sess(cx);
|
||||
self.msrv.check_attributes(sess, attrs);
|
||||
}
|
||||
|
||||
fn check_attributes_post(&mut self, cx: &rustc_lint::$context<'_>, attrs: &[rustc_ast::ast::Attribute]) {
|
||||
fn check_attributes_post(&mut self, cx: &rustc_lint::LateContext<'_>, attrs: &[rustc_hir::Attribute]) {
|
||||
let sess = rustc_lint::LintContext::sess(cx);
|
||||
self.msrv.check_attributes_post(sess, attrs);
|
||||
}
|
||||
};
|
||||
(EarlyContext) => {
|
||||
fn check_attributes(&mut self, cx: &rustc_lint::EarlyContext<'_>, attrs: &[rustc_ast::Attribute]) {
|
||||
let sess = rustc_lint::LintContext::sess(cx);
|
||||
self.msrv.check_attributes(sess, attrs);
|
||||
}
|
||||
|
||||
fn check_attributes_post(&mut self, cx: &rustc_lint::EarlyContext<'_>, attrs: &[rustc_ast::Attribute]) {
|
||||
let sess = rustc_lint::LintContext::sess(cx);
|
||||
self.msrv.check_attributes_post(sess, attrs);
|
||||
}
|
||||
|
@ -1912,7 +1923,7 @@ pub fn clip(tcx: TyCtxt<'_>, u: u128, ity: UintTy) -> u128 {
|
|||
(u << amt) >> amt
|
||||
}
|
||||
|
||||
pub fn has_attr(attrs: &[ast::Attribute], symbol: Symbol) -> bool {
|
||||
pub fn has_attr(attrs: &[hir::Attribute], symbol: Symbol) -> bool {
|
||||
attrs.iter().any(|attr| attr.has_name(symbol))
|
||||
}
|
||||
|
||||
|
@ -2263,21 +2274,13 @@ pub fn std_or_core(cx: &LateContext<'_>) -> Option<&'static str> {
|
|||
|
||||
pub fn is_no_std_crate(cx: &LateContext<'_>) -> bool {
|
||||
cx.tcx.hir().attrs(hir::CRATE_HIR_ID).iter().any(|attr| {
|
||||
if let ast::AttrKind::Normal(ref normal) = attr.kind {
|
||||
normal.item.path == sym::no_std
|
||||
} else {
|
||||
false
|
||||
}
|
||||
attr.name_or_empty() == sym::no_std
|
||||
})
|
||||
}
|
||||
|
||||
pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool {
|
||||
cx.tcx.hir().attrs(hir::CRATE_HIR_ID).iter().any(|attr| {
|
||||
if let ast::AttrKind::Normal(ref normal) = attr.kind {
|
||||
normal.item.path == sym::no_core
|
||||
} else {
|
||||
false
|
||||
}
|
||||
attr.name_or_empty() == sym::no_core
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use rustc_ast::Attribute;
|
||||
use rustc_attr::AttributeExt;
|
||||
use rustc_attr::parse_version;
|
||||
use rustc_session::{RustcVersion, Session};
|
||||
use rustc_span::{Symbol, sym};
|
||||
|
@ -124,15 +124,15 @@ impl Msrv {
|
|||
self.current().is_none_or(|msrv| msrv >= required)
|
||||
}
|
||||
|
||||
fn parse_attr(sess: &Session, attrs: &[Attribute]) -> Option<RustcVersion> {
|
||||
fn parse_attr(sess: &Session, attrs: &[impl AttributeExt]) -> Option<RustcVersion> {
|
||||
let sym_msrv = Symbol::intern("msrv");
|
||||
let mut msrv_attrs = attrs.iter().filter(|attr| attr.path_matches(&[sym::clippy, sym_msrv]));
|
||||
|
||||
if let Some(msrv_attr) = msrv_attrs.next() {
|
||||
if let Some(duplicate) = msrv_attrs.last() {
|
||||
sess.dcx()
|
||||
.struct_span_err(duplicate.span, "`clippy::msrv` is defined multiple times")
|
||||
.with_span_note(msrv_attr.span, "first definition found here")
|
||||
.struct_span_err(duplicate.span(), "`clippy::msrv` is defined multiple times")
|
||||
.with_span_note(msrv_attr.span(), "first definition found here")
|
||||
.emit();
|
||||
}
|
||||
|
||||
|
@ -142,22 +142,22 @@ impl Msrv {
|
|||
}
|
||||
|
||||
sess.dcx()
|
||||
.span_err(msrv_attr.span, format!("`{msrv}` is not a valid Rust version"));
|
||||
.span_err(msrv_attr.span(), format!("`{msrv}` is not a valid Rust version"));
|
||||
} else {
|
||||
sess.dcx().span_err(msrv_attr.span, "bad clippy attribute");
|
||||
sess.dcx().span_err(msrv_attr.span(), "bad clippy attribute");
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub fn check_attributes(&mut self, sess: &Session, attrs: &[Attribute]) {
|
||||
pub fn check_attributes(&mut self, sess: &Session, attrs: &[impl AttributeExt]) {
|
||||
if let Some(version) = Self::parse_attr(sess, attrs) {
|
||||
self.stack.push(version);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_attributes_post(&mut self, sess: &Session, attrs: &[Attribute]) {
|
||||
pub fn check_attributes_post(&mut self, sess: &Session, attrs: &[impl AttributeExt]) {
|
||||
if Self::parse_attr(sess, attrs).is_some() {
|
||||
self.stack.pop();
|
||||
}
|
||||
|
|
|
@ -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() { }
|
||||
|
|
Loading…
Add table
Reference in a new issue