Auto merge of #131808 - jdonszelmann:hir-attributes, r=oli-obk,petrochenkov
Hir attributes This PR needs some explanation, it's somewhat large. - This is step one as described in https://github.com/rust-lang/compiler-team/issues/796. I've added a new `hir::Attribute` which is a lowered version of `ast::Attribute`. Right now, this has few concrete effects, however every place that after this PR parses a `hir::Attribute` should later get a pre-parsed attribute as described in https://github.com/rust-lang/compiler-team/issues/796 and transitively https://github.com/rust-lang/rust/issues/131229. - an extension trait `AttributeExt` is added, which is implemented for both `ast::Attribute` and `hir::Atribute`. This makes `hir::Attributes` mostly compatible with code that used to parse `ast::Attribute`. All its methods are also added as inherent methods to avoid having to import the trait everywhere in the compiler. - Incremental can not not hash `ast::Attribute` at all.
This commit is contained in:
commit
f2b91ccbc2
89 changed files with 1153 additions and 717 deletions
|
@ -3521,6 +3521,7 @@ dependencies = [
|
||||||
"rustc_fluent_macro",
|
"rustc_fluent_macro",
|
||||||
"rustc_fs_util",
|
"rustc_fs_util",
|
||||||
"rustc_hir",
|
"rustc_hir",
|
||||||
|
"rustc_hir_pretty",
|
||||||
"rustc_incremental",
|
"rustc_incremental",
|
||||||
"rustc_index",
|
"rustc_index",
|
||||||
"rustc_macros",
|
"rustc_macros",
|
||||||
|
@ -3786,6 +3787,7 @@ dependencies = [
|
||||||
"rustc_span",
|
"rustc_span",
|
||||||
"rustc_target",
|
"rustc_target",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
|
"thin-vec",
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -4454,9 +4456,9 @@ version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustc_abi",
|
"rustc_abi",
|
||||||
"rustc_ast",
|
"rustc_ast",
|
||||||
"rustc_ast_pretty",
|
|
||||||
"rustc_data_structures",
|
"rustc_data_structures",
|
||||||
"rustc_hir",
|
"rustc_hir",
|
||||||
|
"rustc_hir_pretty",
|
||||||
"rustc_middle",
|
"rustc_middle",
|
||||||
"rustc_session",
|
"rustc_session",
|
||||||
"rustc_span",
|
"rustc_span",
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
//! - [`UnOp`], [`BinOp`], and [`BinOpKind`]: Unary and binary operators.
|
//! - [`UnOp`], [`BinOp`], and [`BinOpKind`]: Unary and binary operators.
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::{cmp, fmt, mem};
|
use std::{cmp, fmt};
|
||||||
|
|
||||||
pub use GenericArgs::*;
|
pub use GenericArgs::*;
|
||||||
pub use UnsafeSource::*;
|
pub use UnsafeSource::*;
|
||||||
|
@ -1758,53 +1758,16 @@ pub enum AttrArgs {
|
||||||
Eq {
|
Eq {
|
||||||
/// Span of the `=` token.
|
/// Span of the `=` token.
|
||||||
eq_span: Span,
|
eq_span: Span,
|
||||||
|
expr: P<Expr>,
|
||||||
value: AttrArgsEq,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// The RHS of an `AttrArgs::Eq` starts out as an expression. Once macro
|
|
||||||
// expansion is completed, all cases end up either as a meta item literal,
|
|
||||||
// which is the form used after lowering to HIR, or as an error.
|
|
||||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
|
||||||
pub enum AttrArgsEq {
|
|
||||||
Ast(P<Expr>),
|
|
||||||
Hir(MetaItemLit),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AttrArgsEq {
|
|
||||||
pub fn span(&self) -> Span {
|
|
||||||
match self {
|
|
||||||
AttrArgsEq::Ast(p) => p.span,
|
|
||||||
AttrArgsEq::Hir(lit) => lit.span,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn unwrap_ast(&self) -> &Expr {
|
|
||||||
match self {
|
|
||||||
AttrArgsEq::Ast(p) => p,
|
|
||||||
AttrArgsEq::Hir(lit) => {
|
|
||||||
unreachable!("in literal form when getting inner tokens: {lit:?}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn unwrap_ast_mut(&mut self) -> &mut P<Expr> {
|
|
||||||
match self {
|
|
||||||
AttrArgsEq::Ast(p) => p,
|
|
||||||
AttrArgsEq::Hir(lit) => {
|
|
||||||
unreachable!("in literal form when getting inner tokens: {lit:?}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AttrArgs {
|
impl AttrArgs {
|
||||||
pub fn span(&self) -> Option<Span> {
|
pub fn span(&self) -> Option<Span> {
|
||||||
match self {
|
match self {
|
||||||
AttrArgs::Empty => None,
|
AttrArgs::Empty => None,
|
||||||
AttrArgs::Delimited(args) => Some(args.dspan.entire()),
|
AttrArgs::Delimited(args) => Some(args.dspan.entire()),
|
||||||
AttrArgs::Eq { eq_span, value } => Some(eq_span.to(value.span())),
|
AttrArgs::Eq { eq_span, expr } => Some(eq_span.to(expr.span)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1814,27 +1777,7 @@ impl AttrArgs {
|
||||||
match self {
|
match self {
|
||||||
AttrArgs::Empty => TokenStream::default(),
|
AttrArgs::Empty => TokenStream::default(),
|
||||||
AttrArgs::Delimited(args) => args.tokens.clone(),
|
AttrArgs::Delimited(args) => args.tokens.clone(),
|
||||||
AttrArgs::Eq { value, .. } => TokenStream::from_ast(value.unwrap_ast()),
|
AttrArgs::Eq { expr, .. } => TokenStream::from_ast(expr),
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<CTX> HashStable<CTX> for AttrArgs
|
|
||||||
where
|
|
||||||
CTX: crate::HashStableContext,
|
|
||||||
{
|
|
||||||
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
|
|
||||||
mem::discriminant(self).hash_stable(ctx, hasher);
|
|
||||||
match self {
|
|
||||||
AttrArgs::Empty => {}
|
|
||||||
AttrArgs::Delimited(args) => args.hash_stable(ctx, hasher),
|
|
||||||
AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => {
|
|
||||||
unreachable!("hash_stable {:?}", expr);
|
|
||||||
}
|
|
||||||
AttrArgs::Eq { eq_span, value: AttrArgsEq::Hir(lit) } => {
|
|
||||||
eq_span.hash_stable(ctx, hasher);
|
|
||||||
lit.hash_stable(ctx, hasher);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3051,7 +2994,7 @@ impl NormalAttr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
|
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||||
pub struct AttrItem {
|
pub struct AttrItem {
|
||||||
pub unsafety: Safety,
|
pub unsafety: Safety,
|
||||||
pub path: Path,
|
pub path: Path,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
//! Functions dealing with attributes and meta items.
|
//! Functions dealing with attributes and meta items.
|
||||||
|
|
||||||
|
use std::fmt::Debug;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::sync::atomic::{AtomicU32, Ordering};
|
use std::sync::atomic::{AtomicU32, Ordering};
|
||||||
|
|
||||||
|
@ -10,9 +11,9 @@ use smallvec::{SmallVec, smallvec};
|
||||||
use thin_vec::{ThinVec, thin_vec};
|
use thin_vec::{ThinVec, thin_vec};
|
||||||
|
|
||||||
use crate::ast::{
|
use crate::ast::{
|
||||||
AttrArgs, AttrArgsEq, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute, DUMMY_NODE_ID,
|
AttrArgs, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute, DUMMY_NODE_ID, DelimArgs,
|
||||||
DelimArgs, Expr, ExprKind, LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit,
|
Expr, ExprKind, LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit, NormalAttr, Path,
|
||||||
NormalAttr, Path, PathSegment, Safety,
|
PathSegment, Safety,
|
||||||
};
|
};
|
||||||
use crate::ptr::P;
|
use crate::ptr::P;
|
||||||
use crate::token::{self, CommentKind, Delimiter, Token};
|
use crate::token::{self, CommentKind, Delimiter, Token};
|
||||||
|
@ -66,11 +67,27 @@ impl Attribute {
|
||||||
AttrKind::DocComment(..) => panic!("unexpected doc comment"),
|
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).
|
/// 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
|
/// So `#[doc = "doc"]` (which is a doc comment) and `#[doc(...)]` (which is not
|
||||||
/// a doc comment) will return `false`.
|
/// a doc comment) will return `false`.
|
||||||
pub fn is_doc_comment(&self) -> bool {
|
fn is_doc_comment(&self) -> bool {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
AttrKind::Normal(..) => false,
|
AttrKind::Normal(..) => false,
|
||||||
AttrKind::DocComment(..) => true,
|
AttrKind::DocComment(..) => true,
|
||||||
|
@ -78,7 +95,7 @@ impl Attribute {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For a single-segment attribute, returns its name; otherwise, returns `None`.
|
/// 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 {
|
match &self.kind {
|
||||||
AttrKind::Normal(normal) => {
|
AttrKind::Normal(normal) => {
|
||||||
if let [ident] = &*normal.item.path.segments {
|
if let [ident] = &*normal.item.path.segments {
|
||||||
|
@ -91,28 +108,14 @@ impl Attribute {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name_or_empty(&self) -> Symbol {
|
fn ident_path(&self) -> Option<SmallVec<[Ident; 1]>> {
|
||||||
self.ident().unwrap_or_else(Ident::empty).name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn path(&self) -> SmallVec<[Symbol; 1]> {
|
|
||||||
match &self.kind {
|
match &self.kind {
|
||||||
AttrKind::Normal(normal) => {
|
AttrKind::Normal(p) => Some(p.item.path.segments.iter().map(|i| i.ident).collect()),
|
||||||
normal.item.path.segments.iter().map(|s| s.ident.name).collect()
|
AttrKind::DocComment(_, _) => None,
|
||||||
}
|
|
||||||
AttrKind::DocComment(..) => smallvec![sym::doc],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
fn path_matches(&self, name: &[Symbol]) -> bool {
|
||||||
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 {
|
|
||||||
match &self.kind {
|
match &self.kind {
|
||||||
AttrKind::Normal(normal) => {
|
AttrKind::Normal(normal) => {
|
||||||
normal.item.path.segments.len() == name.len()
|
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 {
|
if let AttrKind::Normal(normal) = &self.kind {
|
||||||
matches!(normal.item.args, AttrArgs::Empty)
|
matches!(normal.item.args, AttrArgs::Empty)
|
||||||
} else {
|
} else {
|
||||||
|
@ -143,7 +150,7 @@ impl Attribute {
|
||||||
/// #[attr = ""] // Returns `None`.
|
/// #[attr = ""] // Returns `None`.
|
||||||
/// #[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 {
|
match &self.kind {
|
||||||
AttrKind::Normal(normal) => normal.item.meta_item_list(),
|
AttrKind::Normal(normal) => normal.item.meta_item_list(),
|
||||||
AttrKind::DocComment(..) => None,
|
AttrKind::DocComment(..) => None,
|
||||||
|
@ -165,7 +172,7 @@ impl Attribute {
|
||||||
/// ```text
|
/// ```text
|
||||||
/// #[attr("value")]
|
/// #[attr("value")]
|
||||||
/// ```
|
/// ```
|
||||||
pub fn value_str(&self) -> Option<Symbol> {
|
fn value_str(&self) -> Option<Symbol> {
|
||||||
match &self.kind {
|
match &self.kind {
|
||||||
AttrKind::Normal(normal) => normal.item.value_str(),
|
AttrKind::Normal(normal) => normal.item.value_str(),
|
||||||
AttrKind::DocComment(..) => None,
|
AttrKind::DocComment(..) => None,
|
||||||
|
@ -177,7 +184,7 @@ impl Attribute {
|
||||||
/// * `/** doc */` returns `Some(("doc", CommentKind::Block))`.
|
/// * `/** doc */` returns `Some(("doc", CommentKind::Block))`.
|
||||||
/// * `#[doc = "doc"]` returns `Some(("doc", CommentKind::Line))`.
|
/// * `#[doc = "doc"]` returns `Some(("doc", CommentKind::Line))`.
|
||||||
/// * `#[doc(...)]` returns `None`.
|
/// * `#[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 {
|
match &self.kind {
|
||||||
AttrKind::DocComment(kind, data) => Some((*data, *kind)),
|
AttrKind::DocComment(kind, data) => Some((*data, *kind)),
|
||||||
AttrKind::Normal(normal) if normal.item.path == sym::doc => {
|
AttrKind::Normal(normal) if normal.item.path == sym::doc => {
|
||||||
|
@ -191,7 +198,7 @@ impl Attribute {
|
||||||
/// * `///doc` returns `Some("doc")`.
|
/// * `///doc` returns `Some("doc")`.
|
||||||
/// * `#[doc = "doc"]` returns `Some("doc")`.
|
/// * `#[doc = "doc"]` returns `Some("doc")`.
|
||||||
/// * `#[doc(...)]` returns `None`.
|
/// * `#[doc(...)]` returns `None`.
|
||||||
pub fn doc_str(&self) -> Option<Symbol> {
|
fn doc_str(&self) -> Option<Symbol> {
|
||||||
match &self.kind {
|
match &self.kind {
|
||||||
AttrKind::DocComment(.., data) => Some(*data),
|
AttrKind::DocComment(.., data) => Some(*data),
|
||||||
AttrKind::Normal(normal) if normal.item.path == sym::doc => normal.item.value_str(),
|
AttrKind::Normal(normal) if normal.item.path == sym::doc => normal.item.value_str(),
|
||||||
|
@ -199,14 +206,14 @@ impl Attribute {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn may_have_doc_links(&self) -> bool {
|
fn style(&self) -> AttrStyle {
|
||||||
self.doc_str().is_some_and(|s| comments::may_have_doc_links(s.as_str()))
|
self.style
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_proc_macro_attr(&self) -> bool {
|
impl Attribute {
|
||||||
[sym::proc_macro, sym::proc_macro_attribute, sym::proc_macro_derive]
|
pub fn may_have_doc_links(&self) -> bool {
|
||||||
.iter()
|
self.doc_str().is_some_and(|s| comments::may_have_doc_links(s.as_str()))
|
||||||
.any(|kind| self.has_name(*kind))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extracts the MetaItem from inside this Attribute.
|
/// Extracts the MetaItem from inside this Attribute.
|
||||||
|
@ -268,7 +275,12 @@ impl AttrItem {
|
||||||
/// ```
|
/// ```
|
||||||
fn value_str(&self) -> Option<Symbol> {
|
fn value_str(&self) -> Option<Symbol> {
|
||||||
match &self.args {
|
match &self.args {
|
||||||
AttrArgs::Eq { value, .. } => value.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,
|
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 {
|
impl MetaItem {
|
||||||
/// For a single-segment meta item, returns its name; otherwise, returns `None`.
|
/// For a single-segment meta item, returns its name; otherwise, returns `None`.
|
||||||
pub fn ident(&self) -> Option<Ident> {
|
pub fn ident(&self) -> Option<Ident> {
|
||||||
|
@ -439,7 +437,8 @@ impl MetaItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MetaItemKind {
|
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 tokens = tokens.trees().peekable();
|
||||||
let mut result = ThinVec::new();
|
let mut result = ThinVec::new();
|
||||||
while tokens.peek().is_some() {
|
while tokens.peek().is_some() {
|
||||||
|
@ -492,7 +491,7 @@ impl MetaItemKind {
|
||||||
MetaItemKind::list_from_tokens(tokens.clone()).map(MetaItemKind::List)
|
MetaItemKind::list_from_tokens(tokens.clone()).map(MetaItemKind::List)
|
||||||
}
|
}
|
||||||
AttrArgs::Delimited(..) => None,
|
AttrArgs::Delimited(..) => None,
|
||||||
AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => match expr.kind {
|
AttrArgs::Eq { expr, .. } => match expr.kind {
|
||||||
ExprKind::Lit(token_lit) => {
|
ExprKind::Lit(token_lit) => {
|
||||||
// Turn failures to `None`, we'll get parse errors elsewhere.
|
// Turn failures to `None`, we'll get parse errors elsewhere.
|
||||||
MetaItemLit::from_token_lit(token_lit, expr.span)
|
MetaItemLit::from_token_lit(token_lit, expr.span)
|
||||||
|
@ -501,9 +500,6 @@ impl MetaItemKind {
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => {
|
|
||||||
Some(MetaItemKind::NameValue(lit.clone()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -704,26 +700,175 @@ pub fn mk_attr_name_value_str(
|
||||||
tokens: None,
|
tokens: None,
|
||||||
});
|
});
|
||||||
let path = Path::from_ident(Ident::new(name, span));
|
let path = Path::from_ident(Ident::new(name, span));
|
||||||
let args = AttrArgs::Eq { eq_span: span, value: AttrArgsEq::Ast(expr) };
|
let args = AttrArgs::Eq { eq_span: span, expr };
|
||||||
mk_attr(g, style, unsafety, path, args, span)
|
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))
|
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()
|
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())
|
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()
|
find_by_name(attrs, name).is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_contains_name(items: &[MetaItemInner], name: Symbol) -> bool {
|
pub fn list_contains_name(items: &[MetaItemInner], name: Symbol) -> bool {
|
||||||
items.iter().any(|item| item.has_name(name))
|
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;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
|
|
||||||
use crate::{Attribute, attr};
|
use crate::attr::{self, AttributeExt};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum EntryPointType {
|
pub enum EntryPointType {
|
||||||
|
@ -37,7 +37,7 @@ pub enum EntryPointType {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn entry_point_type(
|
pub fn entry_point_type(
|
||||||
attrs: &[Attribute],
|
attrs: &[impl AttributeExt],
|
||||||
at_root: bool,
|
at_root: bool,
|
||||||
name: Option<Symbol>,
|
name: Option<Symbol>,
|
||||||
) -> EntryPointType {
|
) -> EntryPointType {
|
||||||
|
|
|
@ -44,20 +44,10 @@ pub mod token;
|
||||||
pub mod tokenstream;
|
pub mod tokenstream;
|
||||||
pub mod visit;
|
pub mod visit;
|
||||||
|
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
|
||||||
|
|
||||||
pub use self::ast::*;
|
pub use self::ast::*;
|
||||||
pub use self::ast_traits::{AstDeref, AstNodeWrapper, HasAttrs, HasNodeId, HasTokens};
|
pub use self::ast_traits::{AstDeref, AstNodeWrapper, HasAttrs, HasNodeId, HasTokens};
|
||||||
|
|
||||||
/// Requirements for a `StableHashingContext` to be used in this crate.
|
/// Requirements for a `StableHashingContext` to be used in this crate.
|
||||||
/// This is a hack to allow using the `HashStable_Generic` derive macro
|
/// This is a hack to allow using the `HashStable_Generic` derive macro
|
||||||
/// instead of implementing everything in `rustc_middle`.
|
/// instead of implementing everything in `rustc_middle`.
|
||||||
pub trait HashStableContext: rustc_span::HashStableContext {
|
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -451,8 +451,8 @@ fn visit_attr_args<T: MutVisitor>(vis: &mut T, args: &mut AttrArgs) {
|
||||||
match args {
|
match args {
|
||||||
AttrArgs::Empty => {}
|
AttrArgs::Empty => {}
|
||||||
AttrArgs::Delimited(args) => visit_delim_args(vis, args),
|
AttrArgs::Delimited(args) => visit_delim_args(vis, args),
|
||||||
AttrArgs::Eq { eq_span, value } => {
|
AttrArgs::Eq { eq_span, expr } => {
|
||||||
vis.visit_expr(value.unwrap_ast_mut());
|
vis.visit_expr(expr);
|
||||||
vis.visit_span(eq_span);
|
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 {
|
match args {
|
||||||
AttrArgs::Empty => {}
|
AttrArgs::Empty => {}
|
||||||
AttrArgs::Delimited(_args) => {}
|
AttrArgs::Delimited(_args) => {}
|
||||||
AttrArgs::Eq { value, .. } => try_visit!(visitor.visit_expr(value.unwrap_ast())),
|
AttrArgs::Eq { expr, .. } => try_visit!(visitor.visit_expr(expr)),
|
||||||
}
|
}
|
||||||
V::Result::output()
|
V::Result::output()
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,7 +176,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
id: NodeId,
|
id: NodeId,
|
||||||
hir_id: hir::HirId,
|
hir_id: hir::HirId,
|
||||||
ident: &mut Ident,
|
ident: &mut Ident,
|
||||||
attrs: &'hir [Attribute],
|
attrs: &'hir [hir::Attribute],
|
||||||
vis_span: Span,
|
vis_span: Span,
|
||||||
i: &ItemKind,
|
i: &ItemKind,
|
||||||
) -> hir::ItemKind<'hir> {
|
) -> hir::ItemKind<'hir> {
|
||||||
|
@ -467,7 +467,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
id: NodeId,
|
id: NodeId,
|
||||||
vis_span: Span,
|
vis_span: Span,
|
||||||
ident: &mut Ident,
|
ident: &mut Ident,
|
||||||
attrs: &'hir [Attribute],
|
attrs: &'hir [hir::Attribute],
|
||||||
) -> hir::ItemKind<'hir> {
|
) -> hir::ItemKind<'hir> {
|
||||||
let path = &tree.prefix;
|
let path = &tree.prefix;
|
||||||
let segments = prefix.segments.iter().chain(path.segments.iter()).cloned().collect();
|
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 {
|
match s {
|
||||||
Safety::Unsafe(_) => hir::Safety::Unsafe,
|
Safety::Unsafe(_) => hir::Safety::Unsafe,
|
||||||
Safety::Default => default,
|
Safety::Default => default,
|
||||||
|
|
|
@ -41,7 +41,6 @@
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
|
|
||||||
use rustc_ast::node_id::NodeMap;
|
use rustc_ast::node_id::NodeMap;
|
||||||
use rustc_ast::ptr::P;
|
|
||||||
use rustc_ast::{self as ast, *};
|
use rustc_ast::{self as ast, *};
|
||||||
use rustc_data_structures::captures::Captures;
|
use rustc_data_structures::captures::Captures;
|
||||||
use rustc_data_structures::fingerprint::Fingerprint;
|
use rustc_data_structures::fingerprint::Fingerprint;
|
||||||
|
@ -96,7 +95,7 @@ struct LoweringContext<'a, 'hir> {
|
||||||
/// Bodies inside the owner being lowered.
|
/// Bodies inside the owner being lowered.
|
||||||
bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>,
|
bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>,
|
||||||
/// Attributes inside the owner being lowered.
|
/// 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.
|
/// Collect items that were created by lowering the current owner.
|
||||||
children: Vec<(LocalDefId, hir::MaybeOwner<'hir>)>,
|
children: Vec<(LocalDefId, hir::MaybeOwner<'hir>)>,
|
||||||
|
|
||||||
|
@ -847,7 +846,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
ret
|
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() {
|
if attrs.is_empty() {
|
||||||
&[]
|
&[]
|
||||||
} else {
|
} 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
|
// 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
|
// 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.
|
// the `HirId`s. We don't actually need HIR version of attributes anyway.
|
||||||
// Tokens are also not needed after macro expansion and parsing.
|
// Tokens are also not needed after macro expansion and parsing.
|
||||||
let kind = match attr.kind {
|
let kind = match attr.kind {
|
||||||
AttrKind::Normal(ref normal) => AttrKind::Normal(P(NormalAttr {
|
AttrKind::Normal(ref normal) => hir::AttrKind::Normal(Box::new(hir::AttrItem {
|
||||||
item: AttrItem {
|
unsafety: self.lower_safety(normal.item.unsafety, hir::Safety::Safe),
|
||||||
unsafety: normal.item.unsafety,
|
path: hir::AttrPath {
|
||||||
path: normal.item.path.clone(),
|
segments: normal
|
||||||
args: self.lower_attr_args(&normal.item.args),
|
.item
|
||||||
tokens: None,
|
.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) {
|
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 {
|
match args {
|
||||||
AttrArgs::Empty => AttrArgs::Empty,
|
AttrArgs::Empty => hir::AttrArgs::Empty,
|
||||||
AttrArgs::Delimited(args) => AttrArgs::Delimited(self.lower_delim_args(args)),
|
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
|
// 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
|
// after it gets lowered to HIR. Therefore, we can extract literals to handle
|
||||||
// nonterminals in `#[doc]` (e.g. `#[doc = $e]`).
|
// nonterminals in `#[doc]` (e.g. `#[doc = $e]`).
|
||||||
&AttrArgs::Eq { eq_span, ref value } => {
|
&AttrArgs::Eq { eq_span, ref expr } => {
|
||||||
let expr = value.unwrap_ast();
|
|
||||||
// In valid code the value always ends up as a single literal. Otherwise, a dummy
|
// In valid code the value always ends up as a single literal. Otherwise, a dummy
|
||||||
// literal suffices because the error is handled elsewhere.
|
// literal suffices because the error is handled elsewhere.
|
||||||
let lit = if let ExprKind::Lit(token_lit) = expr.kind
|
let lit = if let ExprKind::Lit(token_lit) = expr.kind
|
||||||
|
@ -913,7 +919,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
span: DUMMY_SP,
|
span: DUMMY_SP,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
AttrArgs::Eq { eq_span, value: AttrArgsEq::Hir(lit) }
|
hir::AttrArgs::Eq { eq_span, expr: lit }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2201,7 +2207,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
|
|
||||||
fn stmt_let_pat(
|
fn stmt_let_pat(
|
||||||
&mut self,
|
&mut self,
|
||||||
attrs: Option<&'hir [Attribute]>,
|
attrs: Option<&'hir [hir::Attribute]>,
|
||||||
span: Span,
|
span: Span,
|
||||||
init: Option<&'hir hir::Expr<'hir>>,
|
init: Option<&'hir hir::Expr<'hir>>,
|
||||||
pat: &'hir hir::Pat<'hir>,
|
pat: &'hir hir::Pat<'hir>,
|
||||||
|
|
|
@ -342,7 +342,7 @@ impl<'a> AstValidator<'a> {
|
||||||
sym::forbid,
|
sym::forbid,
|
||||||
sym::warn,
|
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| {
|
.for_each(|attr| {
|
||||||
if attr.is_doc_comment() {
|
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::classify;
|
||||||
use rustc_ast::util::comments::{Comment, CommentStyle};
|
use rustc_ast::util::comments::{Comment, CommentStyle};
|
||||||
use rustc_ast::{
|
use rustc_ast::{
|
||||||
self as ast, AttrArgs, AttrArgsEq, BindingMode, BlockCheckMode, ByRef, DelimArgs, GenericArg,
|
self as ast, AttrArgs, BindingMode, BlockCheckMode, ByRef, DelimArgs, GenericArg, GenericBound,
|
||||||
GenericBound, InlineAsmOperand, InlineAsmOptions, InlineAsmRegOrRegClass,
|
InlineAsmOperand, InlineAsmOptions, InlineAsmRegOrRegClass, InlineAsmTemplatePiece, PatKind,
|
||||||
InlineAsmTemplatePiece, PatKind, RangeEnd, RangeSyntax, Safety, SelfKind, Term, attr,
|
RangeEnd, RangeSyntax, Safety, SelfKind, Term, attr,
|
||||||
};
|
};
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_span::edition::Edition;
|
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,
|
comment_kind: CommentKind,
|
||||||
attr_style: ast::AttrStyle,
|
attr_style: ast::AttrStyle,
|
||||||
data: Symbol,
|
data: Symbol,
|
||||||
|
@ -648,20 +648,13 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
|
||||||
AttrArgs::Empty => {
|
AttrArgs::Empty => {
|
||||||
self.print_path(&item.path, false, 0);
|
self.print_path(&item.path, false, 0);
|
||||||
}
|
}
|
||||||
AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => {
|
AttrArgs::Eq { expr, .. } => {
|
||||||
self.print_path(&item.path, false, 0);
|
self.print_path(&item.path, false, 0);
|
||||||
self.space();
|
self.space();
|
||||||
self.word_space("=");
|
self.word_space("=");
|
||||||
let token_str = self.expr_to_string(expr);
|
let token_str = self.expr_to_string(expr);
|
||||||
self.word(token_str);
|
self.word(token_str);
|
||||||
}
|
}
|
||||||
AttrArgs::Eq { value: 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 {
|
match item.unsafety {
|
||||||
ast::Safety::Unsafe(_) => self.pclose(),
|
ast::Safety::Unsafe(_) => self.pclose(),
|
||||||
|
|
|
@ -3,10 +3,8 @@
|
||||||
use std::num::NonZero;
|
use std::num::NonZero;
|
||||||
|
|
||||||
use rustc_abi::Align;
|
use rustc_abi::Align;
|
||||||
use rustc_ast::{
|
use rustc_ast::attr::AttributeExt;
|
||||||
self as ast, Attribute, LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit, NodeId,
|
use rustc_ast::{self as ast, LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit, NodeId};
|
||||||
attr,
|
|
||||||
};
|
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_errors::ErrorGuaranteed;
|
use rustc_errors::ErrorGuaranteed;
|
||||||
use rustc_feature::{Features, GatedCfg, find_gated_cfg, is_builtin_attr_name};
|
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::hygiene::Transparency;
|
||||||
use rustc_span::symbol::{Symbol, kw, sym};
|
use rustc_span::symbol::{Symbol, kw, sym};
|
||||||
|
|
||||||
use crate::fluent_generated;
|
|
||||||
use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
|
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
|
/// The version placeholder that recently stabilized features contain inside the
|
||||||
/// `since` field of the `#[stable]` attribute.
|
/// `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).
|
/// For more, see [this pull request](https://github.com/rust-lang/rust/pull/100591).
|
||||||
pub const VERSION_PLACEHOLDER: &str = "CURRENT_RUSTC_VERSION";
|
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))
|
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.
|
/// attributes in `attrs`. Returns `None` if no stability attributes are found.
|
||||||
pub fn find_stability(
|
pub fn find_stability(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
attrs: &[Attribute],
|
attrs: &[impl AttributeExt],
|
||||||
item_sp: Span,
|
item_sp: Span,
|
||||||
) -> Option<(Stability, Span)> {
|
) -> Option<(Stability, Span)> {
|
||||||
let mut stab: Option<(Stability, Span)> = None;
|
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::rustc_allowed_through_unstable_modules => allowed_through_unstable_modules = true,
|
||||||
sym::unstable => {
|
sym::unstable => {
|
||||||
if stab.is_some() {
|
if stab.is_some() {
|
||||||
sess.dcx()
|
sess.dcx().emit_err(session_diagnostics::MultipleStabilityLevels {
|
||||||
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
|
span: attr.span(),
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((feature, level)) = parse_unstability(sess, attr) {
|
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 => {
|
sym::stable => {
|
||||||
if stab.is_some() {
|
if stab.is_some() {
|
||||||
sess.dcx()
|
sess.dcx().emit_err(session_diagnostics::MultipleStabilityLevels {
|
||||||
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
|
span: attr.span(),
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if let Some((feature, level)) = parse_stability(sess, attr) {
|
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.
|
/// attributes in `attrs`. Returns `None` if no stability attributes are found.
|
||||||
pub fn find_const_stability(
|
pub fn find_const_stability(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
attrs: &[Attribute],
|
attrs: &[impl AttributeExt],
|
||||||
item_sp: Span,
|
item_sp: Span,
|
||||||
) -> Option<(ConstStability, Span)> {
|
) -> Option<(ConstStability, Span)> {
|
||||||
let mut const_stab: Option<(ConstStability, Span)> = None;
|
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_stable_indirect => const_stable_indirect = true,
|
||||||
sym::rustc_const_unstable => {
|
sym::rustc_const_unstable => {
|
||||||
if const_stab.is_some() {
|
if const_stab.is_some() {
|
||||||
sess.dcx()
|
sess.dcx().emit_err(session_diagnostics::MultipleStabilityLevels {
|
||||||
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
|
span: attr.span(),
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,14 +299,15 @@ pub fn find_const_stability(
|
||||||
const_stable_indirect: false,
|
const_stable_indirect: false,
|
||||||
promotable: false,
|
promotable: false,
|
||||||
},
|
},
|
||||||
attr.span,
|
attr.span(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sym::rustc_const_stable => {
|
sym::rustc_const_stable => {
|
||||||
if const_stab.is_some() {
|
if const_stab.is_some() {
|
||||||
sess.dcx()
|
sess.dcx().emit_err(session_diagnostics::MultipleStabilityLevels {
|
||||||
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
|
span: attr.span(),
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if let Some((feature, level)) = parse_stability(sess, attr) {
|
if let Some((feature, level)) = parse_stability(sess, attr) {
|
||||||
|
@ -316,7 +318,7 @@ pub fn find_const_stability(
|
||||||
const_stable_indirect: false,
|
const_stable_indirect: false,
|
||||||
promotable: false,
|
promotable: false,
|
||||||
},
|
},
|
||||||
attr.span,
|
attr.span(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -361,7 +363,7 @@ pub fn find_const_stability(
|
||||||
/// without the `staged_api` feature.
|
/// without the `staged_api` feature.
|
||||||
pub fn unmarked_crate_const_stab(
|
pub fn unmarked_crate_const_stab(
|
||||||
_sess: &Session,
|
_sess: &Session,
|
||||||
attrs: &[Attribute],
|
attrs: &[impl AttributeExt],
|
||||||
regular_stab: Stability,
|
regular_stab: Stability,
|
||||||
) -> ConstStability {
|
) -> ConstStability {
|
||||||
assert!(regular_stab.level.is_unstable());
|
assert!(regular_stab.level.is_unstable());
|
||||||
|
@ -381,7 +383,7 @@ pub fn unmarked_crate_const_stab(
|
||||||
/// Returns `None` if no stability attributes are found.
|
/// Returns `None` if no stability attributes are found.
|
||||||
pub fn find_body_stability(
|
pub fn find_body_stability(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
attrs: &[Attribute],
|
attrs: &[impl AttributeExt],
|
||||||
) -> Option<(DefaultBodyStability, Span)> {
|
) -> Option<(DefaultBodyStability, Span)> {
|
||||||
let mut body_stab: Option<(DefaultBodyStability, Span)> = None;
|
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 attr.has_name(sym::rustc_default_body_unstable) {
|
||||||
if body_stab.is_some() {
|
if body_stab.is_some() {
|
||||||
sess.dcx()
|
sess.dcx()
|
||||||
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
|
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span() });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((feature, level)) = parse_unstability(sess, attr) {
|
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
|
/// Read the content of a `stable`/`rustc_const_stable` attribute, and return the feature name and
|
||||||
/// its stability information.
|
/// its stability information.
|
||||||
fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, StabilityLevel)> {
|
fn parse_stability(sess: &Session, attr: &impl AttributeExt) -> Option<(Symbol, StabilityLevel)> {
|
||||||
let meta = attr.meta()?;
|
let metas = attr.meta_item_list()?;
|
||||||
let MetaItem { kind: MetaItemKind::List(ref metas), .. } = meta else { return None };
|
|
||||||
|
|
||||||
let mut feature = None;
|
let mut feature = None;
|
||||||
let mut since = None;
|
let mut since = None;
|
||||||
|
@ -454,9 +455,9 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit
|
||||||
let feature = match feature {
|
let feature = match feature {
|
||||||
Some(feature) if rustc_lexer::is_ident(feature.as_str()) => Ok(feature),
|
Some(feature) if rustc_lexer::is_ident(feature.as_str()) => Ok(feature),
|
||||||
Some(_bad_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 {
|
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) {
|
} else if let Some(version) = parse_version(since) {
|
||||||
StableSince::Version(version)
|
StableSince::Version(version)
|
||||||
} else {
|
} else {
|
||||||
sess.dcx().emit_err(session_diagnostics::InvalidSince { span: attr.span });
|
sess.dcx().emit_err(session_diagnostics::InvalidSince { span: attr.span() });
|
||||||
StableSince::Err
|
StableSince::Err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sess.dcx().emit_err(session_diagnostics::MissingSince { span: attr.span });
|
sess.dcx().emit_err(session_diagnostics::MissingSince { span: attr.span() });
|
||||||
StableSince::Err
|
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`
|
/// Read the content of a `unstable`/`rustc_const_unstable`/`rustc_default_body_unstable`
|
||||||
/// attribute, and return the feature name and its stability information.
|
/// attribute, and return the feature name and its stability information.
|
||||||
fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, StabilityLevel)> {
|
fn parse_unstability(sess: &Session, attr: &impl AttributeExt) -> Option<(Symbol, StabilityLevel)> {
|
||||||
let meta = attr.meta()?;
|
let metas = attr.meta_item_list()?;
|
||||||
let MetaItem { kind: MetaItemKind::List(ref metas), .. } = meta else { return None };
|
|
||||||
|
|
||||||
let mut feature = None;
|
let mut feature = None;
|
||||||
let mut reason = None;
|
let mut reason = None;
|
||||||
|
@ -553,13 +553,14 @@ fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabil
|
||||||
let feature = match feature {
|
let feature = match feature {
|
||||||
Some(feature) if rustc_lexer::is_ident(feature.as_str()) => Ok(feature),
|
Some(feature) if rustc_lexer::is_ident(feature.as_str()) => Ok(feature),
|
||||||
Some(_bad_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
|
let issue = issue.ok_or_else(|| {
|
||||||
.ok_or_else(|| sess.dcx().emit_err(session_diagnostics::MissingIssue { span: attr.span }));
|
sess.dcx().emit_err(session_diagnostics::MissingIssue { span: attr.span() })
|
||||||
|
});
|
||||||
|
|
||||||
match (feature, issue) {
|
match (feature, issue) {
|
||||||
(Ok(feature), Ok(_)) => {
|
(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> {
|
pub fn find_crate_name(attrs: &[impl AttributeExt]) -> Option<Symbol> {
|
||||||
attr::first_attr_value_str_by_name(attrs, sym::crate_name)
|
first_attr_value_str_by_name(attrs, sym::crate_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -884,7 +885,7 @@ impl Deprecation {
|
||||||
pub fn find_deprecation(
|
pub fn find_deprecation(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
features: &Features,
|
features: &Features,
|
||||||
attrs: &[Attribute],
|
attrs: &[impl AttributeExt],
|
||||||
) -> Option<(Deprecation, Span)> {
|
) -> Option<(Deprecation, Span)> {
|
||||||
let mut depr: Option<(Deprecation, Span)> = None;
|
let mut depr: Option<(Deprecation, Span)> = None;
|
||||||
let is_rustc = features.staged_api();
|
let is_rustc = features.staged_api();
|
||||||
|
@ -894,16 +895,16 @@ pub fn find_deprecation(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(meta) = attr.meta() else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
let mut since = None;
|
let mut since = None;
|
||||||
let mut note = None;
|
let mut note = None;
|
||||||
let mut suggestion = None;
|
let mut suggestion = None;
|
||||||
match &meta.kind {
|
|
||||||
MetaItemKind::Word => {}
|
if attr.is_doc_comment() {
|
||||||
MetaItemKind::NameValue(..) => note = meta.value_str(),
|
continue;
|
||||||
MetaItemKind::List(list) => {
|
} 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>| {
|
let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
|
||||||
if item.is_some() {
|
if item.is_some() {
|
||||||
sess.dcx().emit_err(session_diagnostics::MultipleItem {
|
sess.dcx().emit_err(session_diagnostics::MultipleItem {
|
||||||
|
@ -924,16 +925,14 @@ pub fn find_deprecation(
|
||||||
start_point_span: sess.source_map().start_point(lit.span),
|
start_point_span: sess.source_map().start_point(lit.span),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
sess.dcx().emit_err(session_diagnostics::IncorrectMetaItem {
|
sess.dcx()
|
||||||
span: meta.span,
|
.emit_err(session_diagnostics::IncorrectMetaItem { span: meta.span });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for meta in list {
|
for meta in &list {
|
||||||
match meta {
|
match meta {
|
||||||
MetaItemInner::MetaItem(mi) => match mi.name_or_empty() {
|
MetaItemInner::MetaItem(mi) => match mi.name_or_empty() {
|
||||||
sym::since => {
|
sym::since => {
|
||||||
|
@ -985,7 +984,8 @@ pub fn find_deprecation(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let since = if let Some(since) = since {
|
let since = if let Some(since) = since {
|
||||||
|
@ -996,22 +996,22 @@ pub fn find_deprecation(
|
||||||
} else if let Some(version) = parse_version(since) {
|
} else if let Some(version) = parse_version(since) {
|
||||||
DeprecatedSince::RustcVersion(version)
|
DeprecatedSince::RustcVersion(version)
|
||||||
} else {
|
} else {
|
||||||
sess.dcx().emit_err(session_diagnostics::InvalidSince { span: attr.span });
|
sess.dcx().emit_err(session_diagnostics::InvalidSince { span: attr.span() });
|
||||||
DeprecatedSince::Err
|
DeprecatedSince::Err
|
||||||
}
|
}
|
||||||
} else if is_rustc {
|
} 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
|
DeprecatedSince::Err
|
||||||
} else {
|
} else {
|
||||||
DeprecatedSince::Unspecified
|
DeprecatedSince::Unspecified
|
||||||
};
|
};
|
||||||
|
|
||||||
if is_rustc && note.is_none() {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
depr = Some((Deprecation { since, note, suggestion }, attr.span));
|
depr = Some((Deprecation { since, note, suggestion }, attr.span()));
|
||||||
}
|
}
|
||||||
|
|
||||||
depr
|
depr
|
||||||
|
@ -1054,11 +1054,11 @@ impl IntType {
|
||||||
/// the same discriminant size that the corresponding C enum would or C
|
/// the same discriminant size that the corresponding C enum would or C
|
||||||
/// structure layout, `packed` to remove padding, and `transparent` to delegate representation
|
/// structure layout, `packed` to remove padding, and `transparent` to delegate representation
|
||||||
/// concerns to the only non-ZST field.
|
/// 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() }
|
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:?}");
|
assert!(attr.has_name(sym::repr), "expected `#[repr(..)]`, found: {attr:?}");
|
||||||
use ReprAttr::*;
|
use ReprAttr::*;
|
||||||
let mut acc = Vec::new();
|
let mut acc = Vec::new();
|
||||||
|
@ -1238,7 +1238,7 @@ pub enum TransparencyError {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_transparency(
|
pub fn find_transparency(
|
||||||
attrs: &[Attribute],
|
attrs: &[impl AttributeExt],
|
||||||
macro_rules: bool,
|
macro_rules: bool,
|
||||||
) -> (Transparency, Option<TransparencyError>) {
|
) -> (Transparency, Option<TransparencyError>) {
|
||||||
let mut transparency = None;
|
let mut transparency = None;
|
||||||
|
@ -1246,7 +1246,7 @@ pub fn find_transparency(
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
if attr.has_name(sym::rustc_macro_transparency) {
|
if attr.has_name(sym::rustc_macro_transparency) {
|
||||||
if let Some((_, old_span)) = transparency {
|
if let Some((_, old_span)) = transparency {
|
||||||
error = Some(TransparencyError::MultipleTransparencyAttrs(old_span, attr.span));
|
error = Some(TransparencyError::MultipleTransparencyAttrs(old_span, attr.span()));
|
||||||
break;
|
break;
|
||||||
} else if let Some(value) = attr.value_str() {
|
} else if let Some(value) = attr.value_str() {
|
||||||
transparency = Some((
|
transparency = Some((
|
||||||
|
@ -1255,11 +1255,12 @@ pub fn find_transparency(
|
||||||
sym::semitransparent => Transparency::SemiTransparent,
|
sym::semitransparent => Transparency::SemiTransparent,
|
||||||
sym::opaque => Transparency::Opaque,
|
sym::opaque => Transparency::Opaque,
|
||||||
_ => {
|
_ => {
|
||||||
error = Some(TransparencyError::UnknownTransparency(value, attr.span));
|
error =
|
||||||
|
Some(TransparencyError::UnknownTransparency(value, attr.span()));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
attr.span,
|
attr.span(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1270,29 +1271,29 @@ pub fn find_transparency(
|
||||||
|
|
||||||
pub fn allow_internal_unstable<'a>(
|
pub fn allow_internal_unstable<'a>(
|
||||||
sess: &'a Session,
|
sess: &'a Session,
|
||||||
attrs: &'a [Attribute],
|
attrs: &'a [impl AttributeExt],
|
||||||
) -> impl Iterator<Item = Symbol> + 'a {
|
) -> impl Iterator<Item = Symbol> + 'a {
|
||||||
allow_unstable(sess, attrs, sym::allow_internal_unstable)
|
allow_unstable(sess, attrs, sym::allow_internal_unstable)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rustc_allow_const_fn_unstable<'a>(
|
pub fn rustc_allow_const_fn_unstable<'a>(
|
||||||
sess: &'a Session,
|
sess: &'a Session,
|
||||||
attrs: &'a [Attribute],
|
attrs: &'a [impl AttributeExt],
|
||||||
) -> impl Iterator<Item = Symbol> + 'a {
|
) -> impl Iterator<Item = Symbol> + 'a {
|
||||||
allow_unstable(sess, attrs, sym::rustc_allow_const_fn_unstable)
|
allow_unstable(sess, attrs, sym::rustc_allow_const_fn_unstable)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn allow_unstable<'a>(
|
fn allow_unstable<'a>(
|
||||||
sess: &'a Session,
|
sess: &'a Session,
|
||||||
attrs: &'a [Attribute],
|
attrs: &'a [impl AttributeExt],
|
||||||
symbol: Symbol,
|
symbol: Symbol,
|
||||||
) -> impl Iterator<Item = Symbol> + 'a {
|
) -> impl Iterator<Item = Symbol> + 'a {
|
||||||
let attrs = attr::filter_by_name(attrs, symbol);
|
let attrs = filter_by_name(attrs, symbol);
|
||||||
let list = attrs
|
let list = attrs
|
||||||
.filter_map(move |attr| {
|
.filter_map(move |attr| {
|
||||||
attr.meta_item_list().or_else(|| {
|
attr.meta_item_list().or_else(|| {
|
||||||
sess.dcx().emit_err(session_diagnostics::ExpectsFeatureList {
|
sess.dcx().emit_err(session_diagnostics::ExpectsFeatureList {
|
||||||
span: attr.span,
|
span: attr.span(),
|
||||||
name: symbol.to_ident_string(),
|
name: symbol.to_ident_string(),
|
||||||
});
|
});
|
||||||
None
|
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.
|
/// Read the content of a `rustc_confusables` attribute, and return the list of candidate names.
|
||||||
pub fn parse_confusables(attr: &Attribute) -> Option<Vec<Symbol>> {
|
pub fn parse_confusables(attr: &impl AttributeExt) -> Option<Vec<Symbol>> {
|
||||||
let meta = attr.meta()?;
|
let metas = attr.meta_item_list()?;
|
||||||
let MetaItem { kind: MetaItemKind::List(ref metas), .. } = meta else { return None };
|
|
||||||
|
|
||||||
let mut candidates = Vec::new();
|
let mut candidates = Vec::new();
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ rustc_errors = { path = "../rustc_errors" }
|
||||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||||
rustc_fs_util = { path = "../rustc_fs_util" }
|
rustc_fs_util = { path = "../rustc_fs_util" }
|
||||||
rustc_hir = { path = "../rustc_hir" }
|
rustc_hir = { path = "../rustc_hir" }
|
||||||
|
rustc_hir_pretty = { path = "../rustc_hir_pretty" }
|
||||||
rustc_incremental = { path = "../rustc_incremental" }
|
rustc_incremental = { path = "../rustc_incremental" }
|
||||||
rustc_index = { path = "../rustc_index" }
|
rustc_index = { path = "../rustc_index" }
|
||||||
rustc_macros = { path = "../rustc_macros" }
|
rustc_macros = { path = "../rustc_macros" }
|
||||||
|
|
|
@ -26,9 +26,9 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use rustc_ast as ast;
|
|
||||||
use rustc_data_structures::unord::{UnordMap, UnordSet};
|
use rustc_data_structures::unord::{UnordMap, UnordSet};
|
||||||
use rustc_errors::{DiagArgValue, IntoDiagArg};
|
use rustc_errors::{DiagArgValue, IntoDiagArg};
|
||||||
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::LOCAL_CRATE;
|
use rustc_hir::def_id::LOCAL_CRATE;
|
||||||
use rustc_middle::mir::mono::CodegenUnitNameBuilder;
|
use rustc_middle::mir::mono::CodegenUnitNameBuilder;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
|
@ -77,7 +77,7 @@ struct AssertModuleSource<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> 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) {
|
let (expected_reuse, comp_kind) = if attr.has_name(sym::rustc_partition_reused) {
|
||||||
(CguReuse::PreLto, ComparisonKind::AtLeast)
|
(CguReuse::PreLto, ComparisonKind::AtLeast)
|
||||||
} else if attr.has_name(sym::rustc_partition_codegened) {
|
} 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) {
|
for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) {
|
||||||
if item.has_name(name) {
|
if item.has_name(name) {
|
||||||
if let Some(value) = item.value_str() {
|
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
|
/// Scan for a `cfg="foo"` attribute and check whether we have a
|
||||||
/// cfg flag called `foo`.
|
/// 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 config = &self.tcx.sess.psess.config;
|
||||||
let value = self.field(attr, sym::cfg);
|
let value = self.field(attr, sym::cfg);
|
||||||
debug!("check_config(config={:?}, value={:?})", config, value);
|
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_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr, list_contains_name};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_errors::codes::*;
|
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::DefKind;
|
||||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
|
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
|
||||||
use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
|
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::{
|
use rustc_middle::middle::codegen_fn_attrs::{
|
||||||
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry,
|
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry,
|
||||||
};
|
};
|
||||||
|
@ -525,13 +525,12 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
||||||
if !attr.has_name(sym::inline) {
|
if !attr.has_name(sym::inline) {
|
||||||
return ia;
|
return ia;
|
||||||
}
|
}
|
||||||
match attr.meta_kind() {
|
if attr.is_word() {
|
||||||
Some(MetaItemKind::Word) => InlineAttr::Hint,
|
InlineAttr::Hint
|
||||||
Some(MetaItemKind::List(ref items)) => {
|
} else if let Some(ref items) = attr.meta_item_list() {
|
||||||
inline_span = Some(attr.span);
|
inline_span = Some(attr.span);
|
||||||
if items.len() != 1 {
|
if items.len() != 1 {
|
||||||
struct_span_code_err!(tcx.dcx(), attr.span, E0534, "expected one argument")
|
struct_span_code_err!(tcx.dcx(), attr.span, E0534, "expected one argument").emit();
|
||||||
.emit();
|
|
||||||
InlineAttr::None
|
InlineAttr::None
|
||||||
} else if list_contains_name(items, sym::always) {
|
} else if list_contains_name(items, sym::always) {
|
||||||
InlineAttr::Always
|
InlineAttr::Always
|
||||||
|
@ -544,9 +543,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
||||||
|
|
||||||
InlineAttr::None
|
InlineAttr::None
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
Some(MetaItemKind::NameValue(_)) => ia,
|
ia
|
||||||
None => ia,
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -562,12 +560,10 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
||||||
return ia;
|
return ia;
|
||||||
}
|
}
|
||||||
let err = |sp, s| struct_span_code_err!(tcx.dcx(), sp, E0722, "{}", s).emit();
|
let err = |sp, s| struct_span_code_err!(tcx.dcx(), sp, E0722, "{}", s).emit();
|
||||||
match attr.meta_kind() {
|
if attr.is_word() {
|
||||||
Some(MetaItemKind::Word) => {
|
|
||||||
err(attr.span, "expected one argument");
|
err(attr.span, "expected one argument");
|
||||||
ia
|
ia
|
||||||
}
|
} else if let Some(ref items) = attr.meta_item_list() {
|
||||||
Some(MetaItemKind::List(ref items)) => {
|
|
||||||
inline_span = Some(attr.span);
|
inline_span = Some(attr.span);
|
||||||
if items.len() != 1 {
|
if items.len() != 1 {
|
||||||
err(attr.span, "expected one argument");
|
err(attr.span, "expected one argument");
|
||||||
|
@ -580,9 +576,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
||||||
err(items[0].span(), "invalid argument");
|
err(items[0].span(), "invalid argument");
|
||||||
OptimizeAttr::None
|
OptimizeAttr::None
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
Some(MetaItemKind::NameValue(_)) => ia,
|
OptimizeAttr::None
|
||||||
None => ia,
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -730,7 +725,7 @@ fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
||||||
false
|
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};
|
use rustc_ast::{LitIntType, LitKind, MetaItemLit};
|
||||||
let meta_item_list = attr.meta_item_list();
|
let meta_item_list = attr.meta_item_list();
|
||||||
let meta_item_list = meta_item_list.as_deref();
|
let meta_item_list = meta_item_list.as_deref();
|
||||||
|
@ -795,7 +790,7 @@ struct MixedExportNameAndNoMangleState<'a> {
|
||||||
export_name: Option<Span>,
|
export_name: Option<Span>,
|
||||||
hir_id: Option<HirId>,
|
hir_id: Option<HirId>,
|
||||||
no_mangle: Option<Span>,
|
no_mangle: Option<Span>,
|
||||||
no_mangle_attr: Option<&'a ast::Attribute>,
|
no_mangle_attr: Option<&'a hir::Attribute>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> MixedExportNameAndNoMangleState<'a> {
|
impl<'a> MixedExportNameAndNoMangleState<'a> {
|
||||||
|
@ -803,7 +798,7 @@ impl<'a> MixedExportNameAndNoMangleState<'a> {
|
||||||
self.export_name = Some(span);
|
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.no_mangle = Some(span);
|
||||||
self.hir_id = Some(hir_id);
|
self.hir_id = Some(hir_id);
|
||||||
self.no_mangle_attr = Some(attr_name);
|
self.no_mangle_attr = Some(attr_name);
|
||||||
|
@ -824,7 +819,7 @@ impl<'a> MixedExportNameAndNoMangleState<'a> {
|
||||||
no_mangle,
|
no_mangle,
|
||||||
errors::MixedExportNameAndNoMangle {
|
errors::MixedExportNameAndNoMangle {
|
||||||
no_mangle,
|
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,
|
export_name,
|
||||||
removal_span: no_mangle,
|
removal_span: no_mangle,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use rustc_ast::ast;
|
|
||||||
use rustc_attr::InstructionSetAttr;
|
use rustc_attr::InstructionSetAttr;
|
||||||
use rustc_data_structures::fx::FxIndexSet;
|
use rustc_data_structures::fx::FxIndexSet;
|
||||||
use rustc_data_structures::unord::{UnordMap, UnordSet};
|
use rustc_data_structures::unord::{UnordMap, UnordSet};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
|
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
|
||||||
use rustc_middle::middle::codegen_fn_attrs::TargetFeature;
|
use rustc_middle::middle::codegen_fn_attrs::TargetFeature;
|
||||||
|
@ -19,7 +19,7 @@ use crate::errors;
|
||||||
/// Enabled target features are added to `target_features`.
|
/// Enabled target features are added to `target_features`.
|
||||||
pub(crate) fn from_target_feature_attr(
|
pub(crate) fn from_target_feature_attr(
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
attr: &ast::Attribute,
|
attr: &hir::Attribute,
|
||||||
rust_target_features: &UnordMap<String, target_features::StabilityComputed>,
|
rust_target_features: &UnordMap<String, target_features::StabilityComputed>,
|
||||||
target_features: &mut Vec<TargetFeature>,
|
target_features: &mut Vec<TargetFeature>,
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::path::Component::Prefix;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use rustc_ast::attr::MarkedAttrs;
|
use rustc_ast::attr::{AttributeExt, MarkedAttrs};
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::token::Nonterminal;
|
use rustc_ast::token::Nonterminal;
|
||||||
use rustc_ast::tokenstream::TokenStream;
|
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 list = attr.meta_item_list();
|
||||||
let Some([MetaItemInner::MetaItem(item)]) = list.as_deref() else {
|
let Some([MetaItemInner::MetaItem(item)]) = list.as_deref() else {
|
||||||
return Err(attr.span);
|
return Err(attr.span());
|
||||||
};
|
};
|
||||||
if !item.is_word() {
|
if !item.is_word() {
|
||||||
return Err(item.span);
|
return Err(item.span);
|
||||||
|
@ -805,7 +807,7 @@ impl SyntaxExtension {
|
||||||
/// | (unspecified) | no | if-ext | if-ext | yes |
|
/// | (unspecified) | no | if-ext | if-ext | yes |
|
||||||
/// | external | no | if-ext | if-ext | yes |
|
/// | external | no | if-ext | if-ext | yes |
|
||||||
/// | yes | yes | yes | yes | 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 flag = sess.opts.cg.collapse_macro_debuginfo;
|
||||||
let attr = attr::find_by_name(attrs, sym::collapse_debuginfo)
|
let attr = attr::find_by_name(attrs, sym::collapse_debuginfo)
|
||||||
.and_then(|attr| {
|
.and_then(|attr| {
|
||||||
|
@ -842,11 +844,11 @@ impl SyntaxExtension {
|
||||||
helper_attrs: Vec<Symbol>,
|
helper_attrs: Vec<Symbol>,
|
||||||
edition: Edition,
|
edition: Edition,
|
||||||
name: Symbol,
|
name: Symbol,
|
||||||
attrs: &[ast::Attribute],
|
attrs: &[impl AttributeExt],
|
||||||
is_local: bool,
|
is_local: bool,
|
||||||
) -> SyntaxExtension {
|
) -> SyntaxExtension {
|
||||||
let allow_internal_unstable =
|
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 allow_internal_unsafe = attr::contains_name(attrs, sym::allow_internal_unsafe);
|
||||||
let local_inner_macros = attr::find_by_name(attrs, sym::macro_export)
|
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(
|
pub fn parse_macro_name_and_helper_attrs(
|
||||||
dcx: DiagCtxtHandle<'_>,
|
dcx: DiagCtxtHandle<'_>,
|
||||||
attr: &Attribute,
|
attr: &impl AttributeExt,
|
||||||
macro_type: &str,
|
macro_type: &str,
|
||||||
) -> Option<(Symbol, Vec<Symbol>)> {
|
) -> Option<(Symbol, Vec<Symbol>)> {
|
||||||
// Once we've located the `#[proc_macro_derive]` attribute, verify
|
// 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, ..))]`
|
// `#[proc_macro_derive(Foo, attributes(A, ..))]`
|
||||||
let list = attr.meta_item_list()?;
|
let list = attr.meta_item_list()?;
|
||||||
let ([trait_attr] | [trait_attr, _]) = list.as_slice() else {
|
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;
|
return None;
|
||||||
};
|
};
|
||||||
let Some(trait_attr) = trait_attr.meta_item() else {
|
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::tokenstream::{DelimSpan, TokenStream};
|
||||||
use rustc_ast::{self as ast, DUMMY_NODE_ID, NodeId};
|
use rustc_ast::{self as ast, DUMMY_NODE_ID, NodeId};
|
||||||
use rustc_ast_pretty::pprust;
|
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_data_structures::fx::{FxHashMap, FxIndexMap};
|
||||||
use rustc_errors::{Applicability, ErrorGuaranteed};
|
use rustc_errors::{Applicability, ErrorGuaranteed};
|
||||||
use rustc_feature::Features;
|
use rustc_feature::Features;
|
||||||
|
@ -371,7 +371,7 @@ pub fn compile_declarative_macro(
|
||||||
features: &Features,
|
features: &Features,
|
||||||
macro_def: &ast::MacroDef,
|
macro_def: &ast::MacroDef,
|
||||||
ident: Ident,
|
ident: Ident,
|
||||||
attrs: &[ast::Attribute],
|
attrs: &[impl AttributeExt],
|
||||||
span: Span,
|
span: Span,
|
||||||
node_id: NodeId,
|
node_id: NodeId,
|
||||||
edition: Edition,
|
edition: Edition,
|
||||||
|
|
|
@ -16,5 +16,6 @@ rustc_serialize = { path = "../rustc_serialize" }
|
||||||
rustc_span = { path = "../rustc_span" }
|
rustc_span = { path = "../rustc_span" }
|
||||||
rustc_target = { path = "../rustc_target" }
|
rustc_target = { path = "../rustc_target" }
|
||||||
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
|
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
|
||||||
|
thin-vec = "0.2.12"
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
# tidy-alphabetical-end
|
# tidy-alphabetical-end
|
||||||
|
|
|
@ -6,7 +6,7 @@ macro_rules! arena_types {
|
||||||
$macro!([
|
$macro!([
|
||||||
// HIR types
|
// HIR types
|
||||||
[] asm_template: rustc_ast::InlineAsmTemplatePiece,
|
[] asm_template: rustc_ast::InlineAsmTemplatePiece,
|
||||||
[] attribute: rustc_ast::Attribute,
|
[] attribute: rustc_hir::Attribute,
|
||||||
[] owner_info: rustc_hir::OwnerInfo<'tcx>,
|
[] owner_info: rustc_hir::OwnerInfo<'tcx>,
|
||||||
[] use_path: rustc_hir::UsePath<'tcx>,
|
[] use_path: rustc_hir::UsePath<'tcx>,
|
||||||
[] lit: rustc_hir::Lit,
|
[] lit: rustc_hir::Lit,
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use rustc_abi::ExternAbi;
|
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::util::parser::{AssocOp, ExprPrecedence};
|
||||||
use rustc_ast::{
|
use rustc_ast::{
|
||||||
self as ast, Attribute, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece, IntTy, Label,
|
self as ast, AttrId, AttrStyle, DelimArgs, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece,
|
||||||
LitKind, TraitObjectSyntax, UintTy,
|
IntTy, Label, LitKind, MetaItemInner, MetaItemLit, TraitObjectSyntax, UintTy,
|
||||||
};
|
};
|
||||||
pub use rustc_ast::{
|
pub use rustc_ast::{
|
||||||
BinOp, BinOpKind, BindingMode, BorrowKind, BoundConstness, BoundPolarity, ByRef, CaptureBy,
|
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_span::{BytePos, DUMMY_SP, ErrorGuaranteed, Span};
|
||||||
use rustc_target::asm::InlineAsmRegOrRegClass;
|
use rustc_target::asm::InlineAsmRegOrRegClass;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
use thin_vec::ThinVec;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use crate::LangItem;
|
use crate::LangItem;
|
||||||
|
@ -937,6 +941,250 @@ pub struct ParentedNode<'tcx> {
|
||||||
pub node: Node<'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.
|
/// Attributes owned by a HIR owner.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct AttributeMap<'tcx> {
|
pub struct AttributeMap<'tcx> {
|
||||||
|
|
|
@ -64,8 +64,8 @@
|
||||||
//! This order consistency is required in a few places in rustc, for
|
//! This order consistency is required in a few places in rustc, for
|
||||||
//! example coroutine inference, and possibly also HIR borrowck.
|
//! 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::visit::{VisitorResult, try_visit, visit_opt, walk_list};
|
||||||
use rustc_ast::{Attribute, Label};
|
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_span::def_id::LocalDefId;
|
use rustc_span::def_id::LocalDefId;
|
||||||
use rustc_span::symbol::{Ident, Symbol};
|
use rustc_span::symbol::{Ident, Symbol};
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
//! * Traits that represent operators; e.g., `Add`, `Sub`, `Index`.
|
//! * Traits that represent operators; e.g., `Add`, `Sub`, `Index`.
|
||||||
//! * Functions called by the compiler itself.
|
//! * 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::fx::FxIndexMap;
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
|
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.
|
/// Extracts the first `lang = "$name"` out of a list of attributes.
|
||||||
/// The `#[panic_handler]` attribute is also extracted out when found.
|
/// 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| {
|
attrs.iter().find_map(|attr| {
|
||||||
Some(match attr {
|
Some(match attr {
|
||||||
_ if attr.has_name(sym::lang) => (attr.value_str()?, 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),
|
_ if attr.has_name(sym::panic_handler) => (sym::panic_impl, attr.span()),
|
||||||
_ => return None,
|
_ => return None,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,7 +2,8 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHas
|
||||||
use rustc_span::def_id::DefPathHash;
|
use rustc_span::def_id::DefPathHash;
|
||||||
|
|
||||||
use crate::hir::{
|
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};
|
use crate::hir_id::{HirId, ItemLocalId};
|
||||||
|
|
||||||
|
@ -12,6 +13,7 @@ use crate::hir_id::{HirId, ItemLocalId};
|
||||||
pub trait HashStableContext:
|
pub trait HashStableContext:
|
||||||
rustc_ast::HashStableContext + rustc_target::HashStableContext
|
rustc_ast::HashStableContext + rustc_target::HashStableContext
|
||||||
{
|
{
|
||||||
|
fn hash_attr(&mut self, _: &Attribute, hasher: &mut StableHasher);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for HirId {
|
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)
|
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_abi::ExternAbi;
|
||||||
use rustc_ast::util::parser::{self, AssocOp, ExprPrecedence, Fixity};
|
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::Breaks::{Consistent, Inconsistent};
|
||||||
use rustc_ast_pretty::pp::{self, Breaks};
|
use rustc_ast_pretty::pp::{self, Breaks};
|
||||||
|
use rustc_ast_pretty::pprust::state::MacHeader;
|
||||||
use rustc_ast_pretty::pprust::{Comments, PrintState};
|
use rustc_ast_pretty::pprust::{Comments, PrintState};
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
BindingMode, ByRef, ConstArgKind, GenericArg, GenericBound, GenericParam, GenericParamKind,
|
BindingMode, ByRef, ConstArgKind, GenericArg, GenericBound, GenericParam, GenericParamKind,
|
||||||
HirId, LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term,
|
HirId, LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term,
|
||||||
};
|
};
|
||||||
use rustc_span::FileName;
|
|
||||||
use rustc_span::source_map::SourceMap;
|
use rustc_span::source_map::SourceMap;
|
||||||
use rustc_span::symbol::{Ident, Symbol, kw};
|
use rustc_span::symbol::{Ident, Symbol, kw};
|
||||||
|
use rustc_span::{FileName, Span};
|
||||||
use {rustc_ast as ast, rustc_hir as hir};
|
use {rustc_ast as ast, rustc_hir as hir};
|
||||||
|
|
||||||
pub fn id_to_string(map: &dyn rustc_hir::intravisit::Map<'_>, hir_id: HirId) -> String {
|
pub fn id_to_string(map: &dyn rustc_hir::intravisit::Map<'_>, hir_id: HirId) -> String {
|
||||||
|
@ -68,15 +70,115 @@ impl PpAnn for &dyn rustc_hir::intravisit::Map<'_> {
|
||||||
pub struct State<'a> {
|
pub struct State<'a> {
|
||||||
pub s: pp::Printer,
|
pub s: pp::Printer,
|
||||||
comments: Option<Comments<'a>>,
|
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),
|
ann: &'a (dyn PpAnn + 'a),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> State<'a> {
|
impl<'a> State<'a> {
|
||||||
fn attrs(&self, id: HirId) -> &'a [ast::Attribute] {
|
fn attrs(&self, id: HirId) -> &'a [hir::Attribute] {
|
||||||
(self.attrs)(id)
|
(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("#["),
|
||||||
|
}
|
||||||
|
if normal.unsafety == hir::Safety::Unsafe {
|
||||||
|
self.word("unsafe(");
|
||||||
|
}
|
||||||
|
self.print_attr_item(&normal, attr.span);
|
||||||
|
if normal.unsafety == hir::Safety::Unsafe {
|
||||||
|
self.word(")");
|
||||||
|
}
|
||||||
|
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<'_>) {
|
fn print_node(&mut self, node: Node<'_>) {
|
||||||
match node {
|
match node {
|
||||||
Node::Param(a) => self.print_param(a),
|
Node::Param(a) => self.print_param(a),
|
||||||
|
@ -164,7 +266,7 @@ pub fn print_crate<'a>(
|
||||||
krate: &hir::Mod<'_>,
|
krate: &hir::Mod<'_>,
|
||||||
filename: FileName,
|
filename: FileName,
|
||||||
input: String,
|
input: String,
|
||||||
attrs: &'a dyn Fn(HirId) -> &'a [ast::Attribute],
|
attrs: &'a dyn Fn(HirId) -> &'a [hir::Attribute],
|
||||||
ann: &'a dyn PpAnn,
|
ann: &'a dyn PpAnn,
|
||||||
) -> String {
|
) -> String {
|
||||||
let mut s = State {
|
let mut s = State {
|
||||||
|
@ -191,6 +293,10 @@ where
|
||||||
printer.s.eof()
|
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 {
|
pub fn ty_to_string(ann: &dyn PpAnn, ty: &hir::Ty<'_>) -> String {
|
||||||
to_string(ann, |s| s.print_type(ty))
|
to_string(ann, |s| s.print_type(ty))
|
||||||
}
|
}
|
||||||
|
@ -242,7 +348,7 @@ impl<'a> State<'a> {
|
||||||
self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e), |e| e.span);
|
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);
|
self.print_inner_attributes(attrs);
|
||||||
for &item_id in _mod.item_ids {
|
for &item_id in _mod.item_ids {
|
||||||
self.ann.nested(self, Nested::Item(item_id));
|
self.ann.nested(self, Nested::Item(item_id));
|
||||||
|
@ -926,14 +1032,14 @@ impl<'a> State<'a> {
|
||||||
self.print_block_maybe_unclosed(blk, &[], false)
|
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)
|
self.print_block_maybe_unclosed(blk, attrs, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_block_maybe_unclosed(
|
fn print_block_maybe_unclosed(
|
||||||
&mut self,
|
&mut self,
|
||||||
blk: &hir::Block<'_>,
|
blk: &hir::Block<'_>,
|
||||||
attrs: &[ast::Attribute],
|
attrs: &[hir::Attribute],
|
||||||
close_box: bool,
|
close_box: bool,
|
||||||
) {
|
) {
|
||||||
match blk.rules {
|
match blk.rules {
|
||||||
|
|
|
@ -50,7 +50,7 @@ use rustc_middle::{bug, span_bug};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_span::symbol::{Symbol, sym};
|
use rustc_span::symbol::{Symbol, sym};
|
||||||
use tracing::debug;
|
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;
|
use crate::errors;
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ struct IfThisChanged<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> 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;
|
let mut value = None;
|
||||||
for list_item in attr.meta_item_list().unwrap_or_default() {
|
for list_item in attr.meta_item_list().unwrap_or_default() {
|
||||||
match list_item.ident() {
|
match list_item.ident() {
|
||||||
|
|
|
@ -19,11 +19,13 @@
|
||||||
//! Errors are reported if we are in the suitable configuration but
|
//! Errors are reported if we are in the suitable configuration but
|
||||||
//! the required condition is not met.
|
//! 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::fx::FxHashSet;
|
||||||
use rustc_data_structures::unord::UnordSet;
|
use rustc_data_structures::unord::UnordSet;
|
||||||
use rustc_hir::def_id::LocalDefId;
|
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::dep_graph::{DepNode, DepNodeExt, label_strs};
|
||||||
use rustc_middle::hir::nested_filter;
|
use rustc_middle::hir::nested_filter;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
|
|
|
@ -387,7 +387,7 @@ pub struct MissingDoc;
|
||||||
|
|
||||||
impl_lint_pass!(MissingDoc => [MISSING_DOCS]);
|
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() {
|
if attr.is_doc_comment() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1012,7 +1012,7 @@ declare_lint_pass!(InvalidNoMangleItems => [NO_MANGLE_CONST_ITEMS, NO_MANGLE_GEN
|
||||||
impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
|
impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
|
||||||
fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
|
fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
|
||||||
let attrs = cx.tcx.hir().attrs(it.hir_id());
|
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<'_>>,
|
impl_generics: Option<&hir::Generics<'_>>,
|
||||||
generics: &hir::Generics<'_>,
|
generics: &hir::Generics<'_>,
|
||||||
span| {
|
span| {
|
||||||
|
@ -1176,7 +1176,7 @@ declare_lint_pass!(
|
||||||
);
|
);
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for UnstableFeatures {
|
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)
|
if attr.has_name(sym::feature)
|
||||||
&& let Some(items) = attr.meta_item_list()
|
&& let Some(items) = attr.meta_item_list()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
|
use rustc_attr::AttributeExt;
|
||||||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||||
use rustc_errors::{Diag, LintDiagnostic, MultiSpan};
|
use rustc_errors::{Diag, LintDiagnostic, MultiSpan};
|
||||||
use rustc_feature::{Features, GateIssue};
|
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,
|
/// FIXME(blyxyas): In a future revision, we should also graph #![allow]s,
|
||||||
/// but that is handled with more care
|
/// 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!(
|
if matches!(
|
||||||
Level::from_attr(attribute),
|
Level::from_attr(attribute),
|
||||||
Some(
|
Some(
|
||||||
|
@ -383,10 +384,9 @@ impl<'tcx> Visitor<'tcx> for LintLevelMaximum<'tcx> {
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
let store = unerased_lint_store(self.tcx.sess);
|
let store = unerased_lint_store(self.tcx.sess);
|
||||||
let Some(meta) = attribute.meta() else { return };
|
|
||||||
// Lint attributes are always a metalist inside a
|
// Lint attributes are always a metalist inside a
|
||||||
// metalist (even with just one lint).
|
// 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 {
|
for meta_list in meta_item_list {
|
||||||
// Convert Path to String
|
// 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;
|
let sess = self.sess;
|
||||||
for (attr_index, attr) in attrs.iter().enumerate() {
|
for (attr_index, attr) in attrs.iter().enumerate() {
|
||||||
if attr.has_name(sym::automatically_derived) {
|
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 };
|
let src = LintLevelSource::Node { name, span: sp, reason };
|
||||||
for &id in ids {
|
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));
|
self.insert_spec(id, (level, src));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use rustc_abi::ExternAbi;
|
use rustc_abi::ExternAbi;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::intravisit::FnKind;
|
use rustc_hir::intravisit::FnKind;
|
||||||
use rustc_hir::{GenericParamKind, PatKind};
|
use rustc_hir::{AttrArgs, AttrItem, AttrKind, GenericParamKind, PatKind};
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_session::config::CrateType;
|
use rustc_session::config::CrateType;
|
||||||
use rustc_session::{declare_lint, declare_lint_pass};
|
use rustc_session::{declare_lint, declare_lint_pass};
|
||||||
|
@ -342,11 +342,13 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
|
||||||
let crate_ident = if let Some(name) = &cx.tcx.sess.opts.crate_name {
|
let crate_ident = if let Some(name) = &cx.tcx.sess.opts.crate_name {
|
||||||
Some(Ident::from_str(name))
|
Some(Ident::from_str(name))
|
||||||
} else {
|
} else {
|
||||||
attr::find_by_name(cx.tcx.hir().attrs(hir::CRATE_HIR_ID), sym::crate_name)
|
attr::find_by_name(cx.tcx.hir().attrs(hir::CRATE_HIR_ID), sym::crate_name).and_then(
|
||||||
.and_then(|attr| attr.meta())
|
|attr| {
|
||||||
.and_then(|meta| {
|
if let AttrKind::Normal(n) = &attr.kind
|
||||||
meta.name_value_literal().and_then(|lit| {
|
&& let AttrItem { args: AttrArgs::Eq { eq_span: _, expr: ref lit }, .. } =
|
||||||
if let ast::LitKind::Str(name, ..) = lit.kind {
|
n.as_ref()
|
||||||
|
&& let ast::LitKind::Str(name, ..) = lit.kind
|
||||||
|
{
|
||||||
// Discard the double quotes surrounding the literal.
|
// Discard the double quotes surrounding the literal.
|
||||||
let sp = cx
|
let sp = cx
|
||||||
.sess()
|
.sess()
|
||||||
|
@ -355,8 +357,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|snippet| {
|
.and_then(|snippet| {
|
||||||
let left = snippet.find('"')?;
|
let left = snippet.find('"')?;
|
||||||
let right =
|
let right = snippet.rfind('"').map(|pos| snippet.len() - pos)?;
|
||||||
snippet.rfind('"').map(|pos| snippet.len() - pos)?;
|
|
||||||
|
|
||||||
Some(
|
Some(
|
||||||
lit.span
|
lit.span
|
||||||
|
@ -370,8 +371,8 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
})
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(ident) = &crate_ident {
|
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_field_def(a: &'tcx rustc_hir::FieldDef<'tcx>);
|
||||||
fn check_variant(a: &'tcx rustc_hir::Variant<'tcx>);
|
fn check_variant(a: &'tcx rustc_hir::Variant<'tcx>);
|
||||||
fn check_path(a: &rustc_hir::Path<'tcx>, b: rustc_hir::HirId);
|
fn check_path(a: &rustc_hir::Path<'tcx>, b: rustc_hir::HirId);
|
||||||
fn check_attribute(a: &'tcx rustc_ast::Attribute);
|
fn check_attribute(a: &'tcx rustc_hir::Attribute);
|
||||||
fn check_attributes(a: &'tcx [rustc_ast::Attribute]);
|
fn check_attributes(a: &'tcx [rustc_hir::Attribute]);
|
||||||
fn check_attributes_post(a: &'tcx [rustc_ast::Attribute]);
|
fn check_attributes_post(a: &'tcx [rustc_hir::Attribute]);
|
||||||
]);
|
]);
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,9 @@
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
|
|
||||||
use rustc_abi::ExternAbi;
|
use rustc_abi::ExternAbi;
|
||||||
|
use rustc_ast::AttrId;
|
||||||
|
use rustc_ast::attr::AttributeExt;
|
||||||
use rustc_ast::node_id::NodeId;
|
use rustc_ast::node_id::NodeId;
|
||||||
use rustc_ast::{AttrId, Attribute};
|
|
||||||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||||
use rustc_data_structures::stable_hasher::{
|
use rustc_data_structures::stable_hasher::{
|
||||||
HashStable, StableCompare, StableHasher, ToStableHashKey,
|
HashStable, StableCompare, StableHasher, ToStableHashKey,
|
||||||
|
@ -221,8 +222,8 @@ impl Level {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts an `Attribute` to a level.
|
/// Converts an `Attribute` to a level.
|
||||||
pub fn from_attr(attr: &Attribute) -> Option<Self> {
|
pub fn from_attr(attr: &impl AttributeExt) -> Option<Self> {
|
||||||
Self::from_symbol(attr.name_or_empty(), Some(attr.id))
|
Self::from_symbol(attr.name_or_empty(), Some(attr.id()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a `Symbol` to a level.
|
/// Converts a `Symbol` to a level.
|
||||||
|
|
|
@ -17,6 +17,7 @@ use rustc_data_structures::sync::{self, FreezeReadGuard, FreezeWriteGuard};
|
||||||
use rustc_errors::DiagCtxtHandle;
|
use rustc_errors::DiagCtxtHandle;
|
||||||
use rustc_expand::base::SyntaxExtension;
|
use rustc_expand::base::SyntaxExtension;
|
||||||
use rustc_fs_util::try_canonicalize;
|
use rustc_fs_util::try_canonicalize;
|
||||||
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE, LocalDefId, StableCrateId};
|
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE, LocalDefId, StableCrateId};
|
||||||
use rustc_hir::definitions::Definitions;
|
use rustc_hir::definitions::Definitions;
|
||||||
use rustc_index::IndexVec;
|
use rustc_index::IndexVec;
|
||||||
|
@ -97,7 +98,13 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum LoadedMacro {
|
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),
|
ProcMacro(SyntaxExtension),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1369,7 +1369,7 @@ impl<'a> CrateMetadataRef<'a> {
|
||||||
self,
|
self,
|
||||||
id: DefIndex,
|
id: DefIndex,
|
||||||
sess: &'a Session,
|
sess: &'a Session,
|
||||||
) -> impl Iterator<Item = ast::Attribute> + 'a {
|
) -> impl Iterator<Item = hir::Attribute> + 'a {
|
||||||
self.root
|
self.root
|
||||||
.tables
|
.tables
|
||||||
.attributes
|
.attributes
|
||||||
|
|
|
@ -344,7 +344,7 @@ provide! { tcx, def_id, other, cdata,
|
||||||
}
|
}
|
||||||
associated_item => { cdata.get_associated_item(def_id.index, tcx.sess) }
|
associated_item => { cdata.get_associated_item(def_id.index, tcx.sess) }
|
||||||
inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) }
|
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_mir_available => { cdata.is_item_mir_available(def_id.index) }
|
||||||
is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) }
|
is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) }
|
||||||
cross_crate_inlinable => { table_direct }
|
cross_crate_inlinable => { table_direct }
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::fs::File;
|
||||||
use std::io::{Read, Seek, Write};
|
use std::io::{Read, Seek, Write};
|
||||||
use std::path::{Path, PathBuf};
|
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::fx::{FxIndexMap, FxIndexSet};
|
||||||
use rustc_data_structures::memmap::{Mmap, MmapMut};
|
use rustc_data_structures::memmap::{Mmap, MmapMut};
|
||||||
use rustc_data_structures::sync::{Lrc, join, par_for_each_in};
|
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
|
/// 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.
|
/// attribute. Some attributes would only be usable downstream if they are public.
|
||||||
#[inline]
|
#[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;
|
let mut should_encode = false;
|
||||||
if !rustc_feature::encode_cross_crate(attr.name_or_empty()) {
|
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.
|
// 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()
|
.hir()
|
||||||
.attrs(tcx.local_def_id_to_hir_id(def_id))
|
.attrs(tcx.local_def_id_to_hir_id(def_id))
|
||||||
.iter()
|
.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);
|
record_array!(self.tables.attributes[def_id.to_def_id()] <- attr_iter);
|
||||||
|
|
||||||
|
|
|
@ -403,7 +403,7 @@ define_tables! {
|
||||||
cross_crate_inlinable: Table<DefIndex, bool>,
|
cross_crate_inlinable: Table<DefIndex, bool>,
|
||||||
|
|
||||||
- optional:
|
- 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`,
|
// 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.
|
// so we can take their names, visibilities etc from other encoded tables.
|
||||||
module_children_non_reexports: Table<DefIndex, LazyArray<DefIndex>>,
|
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>,
|
[] upvars_mentioned: rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>,
|
||||||
[] dyn_compatibility_violations: rustc_middle::traits::DynCompatibilityViolation,
|
[] dyn_compatibility_violations: rustc_middle::traits::DynCompatibilityViolation,
|
||||||
[] codegen_unit: rustc_middle::mir::mono::CodegenUnit<'tcx>,
|
[] 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>,
|
[] name_set: rustc_data_structures::unord::UnordSet<rustc_span::symbol::Symbol>,
|
||||||
[] ordered_name_set: rustc_data_structures::fx::FxIndexSet<rustc_span::symbol::Symbol>,
|
[] ordered_name_set: rustc_data_structures::fx::FxIndexSet<rustc_span::symbol::Symbol>,
|
||||||
[] pats: rustc_middle::ty::PatternKind<'tcx>,
|
[] 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::definitions::{DefKey, DefPath, DefPathHash};
|
||||||
use rustc_hir::intravisit::Visitor;
|
use rustc_hir::intravisit::Visitor;
|
||||||
use rustc_hir::*;
|
use rustc_hir::*;
|
||||||
|
use rustc_hir_pretty as pprust_hir;
|
||||||
use rustc_middle::hir::nested_filter;
|
use rustc_middle::hir::nested_filter;
|
||||||
use rustc_span::def_id::StableCrateId;
|
use rustc_span::def_id::StableCrateId;
|
||||||
use rustc_span::symbol::{Ident, Symbol, kw, sym};
|
use rustc_span::symbol::{Ident, Symbol, kw, sym};
|
||||||
use rustc_span::{ErrorGuaranteed, Span};
|
use rustc_span::{ErrorGuaranteed, Span};
|
||||||
use {rustc_ast as ast, rustc_hir_pretty as pprust_hir};
|
|
||||||
|
|
||||||
use crate::hir::ModuleItems;
|
use crate::hir::ModuleItems;
|
||||||
use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
|
use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
|
||||||
|
@ -381,7 +381,7 @@ impl<'hir> Map<'hir> {
|
||||||
/// Gets the attributes on the crate. This is preferable to
|
/// Gets the attributes on the crate. This is preferable to
|
||||||
/// invoking `krate.attrs` because it registers a tighter
|
/// invoking `krate.attrs` because it registers a tighter
|
||||||
/// dep-graph access.
|
/// dep-graph access.
|
||||||
pub fn krate_attrs(self) -> &'hir [ast::Attribute] {
|
pub fn krate_attrs(self) -> &'hir [Attribute] {
|
||||||
self.attrs(CRATE_HIR_ID)
|
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
|
/// Given a node ID, gets a list of attributes associated with the AST
|
||||||
/// corresponding to the node-ID.
|
/// 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)
|
self.tcx.hir_attrs(id.owner).get(id.local_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -151,7 +151,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
self,
|
self,
|
||||||
node: OwnerNode<'_>,
|
node: OwnerNode<'_>,
|
||||||
bodies: &SortedMap<ItemLocalId, &Body<'_>>,
|
bodies: &SortedMap<ItemLocalId, &Body<'_>>,
|
||||||
attrs: &SortedMap<ItemLocalId, &[rustc_ast::Attribute]>,
|
attrs: &SortedMap<ItemLocalId, &[Attribute]>,
|
||||||
) -> (Option<Fingerprint>, Option<Fingerprint>) {
|
) -> (Option<Fingerprint>, Option<Fingerprint>) {
|
||||||
if self.needs_crate_hash() {
|
if self.needs_crate_hash() {
|
||||||
self.with_stable_hashing_context(|mut hcx| {
|
self.with_stable_hashing_context(|mut hcx| {
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
use std::num::IntErrorKind;
|
use std::num::IntErrorKind;
|
||||||
|
|
||||||
use rustc_ast::Attribute;
|
use rustc_ast::attr::AttributeExt;
|
||||||
use rustc_session::{Limit, Limits, Session};
|
use rustc_session::{Limit, Limits, Session};
|
||||||
use rustc_span::symbol::{Symbol, sym};
|
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)
|
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) {
|
match get_limit_size(krate_attrs, sess, name) {
|
||||||
Some(size) => Limit::new(size),
|
Some(size) => Limit::new(size),
|
||||||
None => Limit::new(default),
|
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 {
|
for attr in krate_attrs {
|
||||||
if !attr.has_name(name) {
|
if !attr.has_name(name) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(s) = attr.value_str() {
|
if let Some(sym) = attr.value_str() {
|
||||||
match s.as_str().parse() {
|
match sym.as_str().parse() {
|
||||||
Ok(n) => return Some(n),
|
Ok(n) => return Some(n),
|
||||||
Err(e) => {
|
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() {
|
let error_str = match e.kind() {
|
||||||
IntErrorKind::PosOverflow => "`limit` is too large",
|
IntErrorKind::PosOverflow => "`limit` is too large",
|
||||||
IntErrorKind::Empty => "`limit` must be a non-negative integer",
|
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`"),
|
IntErrorKind::Zero => bug!("zero is a valid `limit`"),
|
||||||
kind => bug!("unimplemented IntErrorKind variant: {:?}", kind),
|
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`.
|
/// Returns the attributes on the item at `def_id`.
|
||||||
///
|
///
|
||||||
/// Do not use this directly, use `tcx.get_attrs` instead.
|
/// 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) }
|
desc { |tcx| "collecting attributes of `{}`", tcx.def_path_str(def_id) }
|
||||||
separate_provide_extern
|
separate_provide_extern
|
||||||
}
|
}
|
||||||
|
|
|
@ -798,7 +798,7 @@ macro_rules! impl_ref_decoder {
|
||||||
|
|
||||||
impl_ref_decoder! {<'tcx>
|
impl_ref_decoder! {<'tcx>
|
||||||
Span,
|
Span,
|
||||||
rustc_ast::Attribute,
|
rustc_hir::Attribute,
|
||||||
rustc_span::symbol::Ident,
|
rustc_span::symbol::Ident,
|
||||||
ty::Variance,
|
ty::Variance,
|
||||||
rustc_span::def_id::DefId,
|
rustc_span::def_id::DefId,
|
||||||
|
|
|
@ -13,7 +13,7 @@ use std::ops::{Bound, Deref};
|
||||||
use std::{fmt, iter, mem};
|
use std::{fmt, iter, mem};
|
||||||
|
|
||||||
use rustc_abi::{ExternAbi, FieldIdx, Layout, LayoutData, TargetDataLayout, VariantIdx};
|
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::defer;
|
||||||
use rustc_data_structures::fingerprint::Fingerprint;
|
use rustc_data_structures::fingerprint::Fingerprint;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
|
@ -29,13 +29,12 @@ use rustc_data_structures::unord::UnordSet;
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, LintDiagnostic, MultiSpan,
|
Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, LintDiagnostic, MultiSpan,
|
||||||
};
|
};
|
||||||
use rustc_hir as hir;
|
|
||||||
use rustc_hir::def::{CtorKind, DefKind};
|
use rustc_hir::def::{CtorKind, DefKind};
|
||||||
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
|
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
|
||||||
use rustc_hir::definitions::Definitions;
|
use rustc_hir::definitions::Definitions;
|
||||||
use rustc_hir::intravisit::Visitor;
|
use rustc_hir::intravisit::Visitor;
|
||||||
use rustc_hir::lang_items::LangItem;
|
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_index::IndexVec;
|
||||||
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
|
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
|
||||||
use rustc_query_system::cache::WithDepNode;
|
use rustc_query_system::cache::WithDepNode;
|
||||||
|
@ -3239,12 +3238,16 @@ pub fn provide(providers: &mut Providers) {
|
||||||
providers.extern_mod_stmt_cnum =
|
providers.extern_mod_stmt_cnum =
|
||||||
|tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned();
|
|tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned();
|
||||||
providers.is_panic_runtime =
|
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 =
|
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| {
|
providers.has_panic_handler = |tcx, LocalCrate| {
|
||||||
// We want to check if the panic handler was defined in this crate
|
// 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())
|
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);
|
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,
|
&self,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
attr: Symbol,
|
attr: Symbol,
|
||||||
) -> impl Iterator<Item = &'tcx rustc_ast::Attribute> {
|
) -> impl Iterator<Item = &'tcx hir::Attribute> {
|
||||||
tcx.get_attrs(self.def_id(), attr)
|
tcx.get_attrs(self.def_id(), attr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1745,11 +1745,11 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(@lcnr): Remove this function.
|
// 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() {
|
if let Some(did) = did.as_local() {
|
||||||
self.hir().attrs(self.local_def_id_to_hir_id(did))
|
self.hir().attrs(self.local_def_id_to_hir_id(did))
|
||||||
} else {
|
} else {
|
||||||
self.item_attrs(did)
|
self.attrs_for_def(did)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1758,14 +1758,14 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
self,
|
self,
|
||||||
did: impl Into<DefId>,
|
did: impl Into<DefId>,
|
||||||
attr: Symbol,
|
attr: Symbol,
|
||||||
) -> impl Iterator<Item = &'tcx ast::Attribute> {
|
) -> impl Iterator<Item = &'tcx hir::Attribute> {
|
||||||
let did: DefId = did.into();
|
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() {
|
if let Some(did) = did.as_local() {
|
||||||
self.hir().attrs(self.local_def_id_to_hir_id(did)).iter().filter(filter_fn)
|
self.hir().attrs(self.local_def_id_to_hir_id(did)).iter().filter(filter_fn)
|
||||||
} else {
|
} else {
|
||||||
debug_assert!(rustc_feature::encode_cross_crate(attr));
|
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,
|
self,
|
||||||
did: impl Into<DefId>,
|
did: impl Into<DefId>,
|
||||||
attr: Symbol,
|
attr: Symbol,
|
||||||
) -> Option<&'tcx ast::Attribute> {
|
) -> Option<&'tcx hir::Attribute> {
|
||||||
let did: DefId = did.into();
|
let did: DefId = did.into();
|
||||||
if did.as_local().is_some() {
|
if did.as_local().is_some() {
|
||||||
// it's a crate local item, we need to check feature flags
|
// 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
|
// we filter out unstable diagnostic attributes before
|
||||||
// encoding attributes
|
// encoding attributes
|
||||||
debug_assert!(rustc_feature::encode_cross_crate(attr));
|
debug_assert!(rustc_feature::encode_cross_crate(attr));
|
||||||
self.item_attrs(did)
|
self.attrs_for_def(did)
|
||||||
.iter()
|
.iter()
|
||||||
.find(|a| matches!(a.path().as_ref(), [sym::diagnostic, a] if *a == attr))
|
.find(|a| matches!(a.path().as_ref(), [sym::diagnostic, a] if *a == attr))
|
||||||
}
|
}
|
||||||
|
@ -1804,19 +1804,19 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
self,
|
self,
|
||||||
did: DefId,
|
did: DefId,
|
||||||
attr: &'attr [Symbol],
|
attr: &'attr [Symbol],
|
||||||
) -> impl Iterator<Item = &'tcx ast::Attribute> + 'attr
|
) -> impl Iterator<Item = &'tcx hir::Attribute> + 'attr
|
||||||
where
|
where
|
||||||
'tcx: 'attr,
|
'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() {
|
if let Some(did) = did.as_local() {
|
||||||
self.hir().attrs(self.local_def_id_to_hir_id(did)).iter().filter(filter_fn)
|
self.hir().attrs(self.local_def_id_to_hir_id(did)).iter().filter(filter_fn)
|
||||||
} else {
|
} 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) {
|
if cfg!(debug_assertions) && !rustc_feature::is_valid_for_get_attr(attr) {
|
||||||
let did: DefId = did.into();
|
let did: DefId = did.into();
|
||||||
bug!("get_attr: unexpected called with DefId `{:?}`, attr `{:?}`", did, attr);
|
bug!("get_attr: unexpected called with DefId `{:?}`, attr `{:?}`", did, attr);
|
||||||
|
|
|
@ -111,6 +111,7 @@ trivially_parameterized_over_tcx! {
|
||||||
rustc_span::hygiene::SyntaxContextData,
|
rustc_span::hygiene::SyntaxContextData,
|
||||||
rustc_span::symbol::Ident,
|
rustc_span::symbol::Ident,
|
||||||
rustc_type_ir::Variance,
|
rustc_type_ir::Variance,
|
||||||
|
rustc_hir::Attribute,
|
||||||
}
|
}
|
||||||
|
|
||||||
// HACK(compiler-errors): This macro rule can only take a fake path,
|
// HACK(compiler-errors): This macro rule can only take a fake path,
|
||||||
|
@ -140,5 +141,5 @@ parameterized_over_tcx! {
|
||||||
ty::Predicate,
|
ty::Predicate,
|
||||||
ty::Clause,
|
ty::Clause,
|
||||||
ty::ClauseKind,
|
ty::ClauseKind,
|
||||||
ty::ImplTraitHeader
|
ty::ImplTraitHeader,
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,9 @@
|
||||||
//! terminators, and everything below can be found in the `parse::instruction` submodule.
|
//! terminators, and everything below can be found in the `parse::instruction` submodule.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use rustc_ast::Attribute;
|
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_hir::HirId;
|
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
|
use rustc_hir::{Attribute, HirId};
|
||||||
use rustc_index::{IndexSlice, IndexVec};
|
use rustc_index::{IndexSlice, IndexVec};
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::span_bug;
|
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::token::{self, Delimiter};
|
||||||
|
use rustc_ast::{self as ast, Attribute, attr};
|
||||||
use rustc_errors::codes::*;
|
use rustc_errors::codes::*;
|
||||||
use rustc_errors::{Diag, PResult};
|
use rustc_errors::{Diag, PResult};
|
||||||
use rustc_span::symbol::kw;
|
use rustc_span::symbol::kw;
|
||||||
|
@ -48,7 +47,7 @@ impl<'a> Parser<'a> {
|
||||||
let start_pos = self.num_bump_calls;
|
let start_pos = self.num_bump_calls;
|
||||||
loop {
|
loop {
|
||||||
let attr = if self.check(&token::Pound) {
|
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 {
|
let inner_error_reason = if just_parsed_doc_comment {
|
||||||
Some(InnerAttrForbiddenReason::AfterOuterDocComment {
|
Some(InnerAttrForbiddenReason::AfterOuterDocComment {
|
||||||
|
|
|
@ -29,9 +29,9 @@ use rustc_ast::tokenstream::{
|
||||||
};
|
};
|
||||||
use rustc_ast::util::case::Case;
|
use rustc_ast::util::case::Case;
|
||||||
use rustc_ast::{
|
use rustc_ast::{
|
||||||
self as ast, AnonConst, AttrArgs, AttrArgsEq, AttrId, ByRef, Const, CoroutineKind,
|
self as ast, AnonConst, AttrArgs, AttrId, ByRef, Const, CoroutineKind, DUMMY_NODE_ID,
|
||||||
DUMMY_NODE_ID, DelimArgs, Expr, ExprKind, Extern, HasAttrs, HasTokens, Mutability, Recovered,
|
DelimArgs, Expr, ExprKind, Extern, HasAttrs, HasTokens, Mutability, Recovered, Safety, StrLit,
|
||||||
Safety, StrLit, Visibility, VisibilityKind,
|
Visibility, VisibilityKind,
|
||||||
};
|
};
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
|
@ -1376,7 +1376,7 @@ impl<'a> Parser<'a> {
|
||||||
AttrArgs::Delimited(args)
|
AttrArgs::Delimited(args)
|
||||||
} else if self.eat(&token::Eq) {
|
} else if self.eat(&token::Eq) {
|
||||||
let eq_span = self.prev_token.span;
|
let eq_span = self.prev_token.span;
|
||||||
AttrArgs::Eq { eq_span, value: AttrArgsEq::Ast(self.parse_expr_force_collect()?) }
|
AttrArgs::Eq { eq_span, expr: self.parse_expr_force_collect()? }
|
||||||
} else {
|
} else {
|
||||||
AttrArgs::Empty
|
AttrArgs::Empty
|
||||||
})
|
})
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
use rustc_ast::token::Delimiter;
|
use rustc_ast::token::Delimiter;
|
||||||
use rustc_ast::tokenstream::DelimSpan;
|
use rustc_ast::tokenstream::DelimSpan;
|
||||||
use rustc_ast::{
|
use rustc_ast::{
|
||||||
self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem, MetaItemInner, MetaItemKind,
|
self as ast, AttrArgs, Attribute, DelimArgs, MetaItem, MetaItemInner, MetaItemKind, Safety,
|
||||||
Safety,
|
|
||||||
};
|
};
|
||||||
use rustc_errors::{Applicability, FatalError, PResult};
|
use rustc_errors::{Applicability, FatalError, PResult};
|
||||||
use rustc_feature::{AttributeSafety, AttributeTemplate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute};
|
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())?;
|
parse_in(psess, tokens.clone(), "meta list", |p| p.parse_meta_seq_top())?;
|
||||||
MetaItemKind::List(nmis)
|
MetaItemKind::List(nmis)
|
||||||
}
|
}
|
||||||
AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => {
|
AttrArgs::Eq { expr, .. } => {
|
||||||
if let ast::ExprKind::Lit(token_lit) = expr.kind {
|
if let ast::ExprKind::Lit(token_lit) = expr.kind {
|
||||||
let res = ast::MetaItemLit::from_token_lit(token_lit, expr.span);
|
let res = ast::MetaItemLit::from_token_lit(token_lit, expr.span);
|
||||||
let res = match res {
|
let res = match res {
|
||||||
|
@ -116,9 +115,6 @@ pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Met
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AttrArgs::Eq { value: 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::DefKind;
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_middle::span_bug;
|
use rustc_middle::span_bug;
|
||||||
|
|
|
@ -7,17 +7,15 @@
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
|
|
||||||
use rustc_ast::{
|
use rustc_ast::{AttrStyle, LitKind, MetaItemInner, MetaItemKind, MetaItemLit, ast};
|
||||||
AttrKind, AttrStyle, Attribute, LitKind, MetaItemInner, MetaItemKind, MetaItemLit, ast,
|
|
||||||
};
|
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_errors::{Applicability, DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey};
|
use rustc_errors::{Applicability, DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey};
|
||||||
use rustc_feature::{AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute};
|
use rustc_feature::{AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute};
|
||||||
use rustc_hir::def_id::LocalModDefId;
|
use rustc_hir::def_id::LocalModDefId;
|
||||||
use rustc_hir::intravisit::{self, Visitor};
|
use rustc_hir::intravisit::{self, Visitor};
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
self as hir, self, AssocItemKind, CRATE_HIR_ID, CRATE_OWNER_ID, FnSig, ForeignItem, HirId,
|
self as hir, self, AssocItemKind, AttrKind, Attribute, CRATE_HIR_ID, CRATE_OWNER_ID, FnSig,
|
||||||
Item, ItemKind, MethodKind, Safety, Target, TraitItem,
|
ForeignItem, HirId, Item, ItemKind, MethodKind, Safety, Target, TraitItem,
|
||||||
};
|
};
|
||||||
use rustc_macros::LintDiagnostic;
|
use rustc_macros::LintDiagnostic;
|
||||||
use rustc_middle::hir::nested_filter;
|
use rustc_middle::hir::nested_filter;
|
||||||
|
@ -1176,10 +1174,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||||
specified_inline: &mut Option<(bool, Span)>,
|
specified_inline: &mut Option<(bool, Span)>,
|
||||||
aliases: &mut FxHashMap<String, Span>,
|
aliases: &mut FxHashMap<String, Span>,
|
||||||
) {
|
) {
|
||||||
if let Some(mi) = attr.meta()
|
if let Some(list) = attr.meta_item_list() {
|
||||||
&& let Some(list) = mi.meta_item_list()
|
for meta in &list {
|
||||||
{
|
|
||||||
for meta in list {
|
|
||||||
if let Some(i_meta) = meta.meta_item() {
|
if let Some(i_meta) = meta.meta_item() {
|
||||||
match i_meta.name_or_empty() {
|
match i_meta.name_or_empty() {
|
||||||
sym::alias => {
|
sym::alias => {
|
||||||
|
@ -1279,7 +1275,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||||
AttrStyle::Inner => "!",
|
AttrStyle::Inner => "!",
|
||||||
AttrStyle::Outer => "",
|
AttrStyle::Outer => "",
|
||||||
},
|
},
|
||||||
sugg: (attr.meta().unwrap().span, applicability),
|
sugg: (attr.span, applicability),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else if i_meta.has_name(sym::passes)
|
} else if i_meta.has_name(sym::passes)
|
||||||
|
@ -2141,10 +2137,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||||
fn check_confusables(&self, attr: &Attribute, target: Target) {
|
fn check_confusables(&self, attr: &Attribute, target: Target) {
|
||||||
match target {
|
match target {
|
||||||
Target::Method(MethodKind::Inherent) => {
|
Target::Method(MethodKind::Inherent) => {
|
||||||
let Some(meta) = attr.meta() else {
|
let Some(metas) = attr.meta_item_list() else {
|
||||||
return;
|
|
||||||
};
|
|
||||||
let ast::MetaItem { kind: MetaItemKind::List(ref metas), .. } = meta else {
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2602,7 +2595,7 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
|
||||||
|
|
||||||
if let AttrKind::Normal(ref p) = attr.kind {
|
if let AttrKind::Normal(ref p) = attr.kind {
|
||||||
tcx.dcx().try_steal_replace_and_emit_err(
|
tcx.dcx().try_steal_replace_and_emit_err(
|
||||||
p.item.path.span,
|
p.path.span,
|
||||||
StashKey::UndeterminedMacroResolution,
|
StashKey::UndeterminedMacroResolution,
|
||||||
err,
|
err,
|
||||||
);
|
);
|
||||||
|
|
|
@ -9,9 +9,8 @@
|
||||||
//!
|
//!
|
||||||
//! * Compiler internal types like `Ty` and `TyCtxt`
|
//! * 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::diagnostic_items::DiagnosticItems;
|
||||||
|
use rustc_hir::{Attribute, OwnerId};
|
||||||
use rustc_middle::query::{LocalCrate, Providers};
|
use rustc_middle::query::{LocalCrate, Providers};
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_span::def_id::{DefId, LOCAL_CRATE};
|
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.
|
/// 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| {
|
attrs.iter().find_map(|attr| {
|
||||||
if attr.has_name(sym::rustc_diagnostic_item) { attr.value_str() } else { None }
|
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)
|
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);
|
self.record("Attribute", None, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use rustc_abi::{HasDataLayout, TargetDataLayout};
|
use rustc_abi::{HasDataLayout, TargetDataLayout};
|
||||||
use rustc_ast::Attribute;
|
use rustc_hir::Attribute;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_middle::span_bug;
|
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
|
//! but are not declared in one single location (unlike lang features), which means we need to
|
||||||
//! collect them instead.
|
//! collect them instead.
|
||||||
|
|
||||||
use rustc_ast::Attribute;
|
|
||||||
use rustc_attr::VERSION_PLACEHOLDER;
|
use rustc_attr::VERSION_PLACEHOLDER;
|
||||||
|
use rustc_hir::Attribute;
|
||||||
use rustc_hir::intravisit::Visitor;
|
use rustc_hir::intravisit::Visitor;
|
||||||
use rustc_middle::hir::nested_filter;
|
use rustc_middle::hir::nested_filter;
|
||||||
use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures};
|
use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures};
|
||||||
|
|
|
@ -1,18 +1,17 @@
|
||||||
//! This module contains `HashStable` implementations for various data types
|
//! 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_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
|
use rustc_hir as hir;
|
||||||
use rustc_span::SourceFile;
|
use rustc_span::SourceFile;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use crate::ich::StableHashingContext;
|
use crate::ich::StableHashingContext;
|
||||||
|
|
||||||
impl<'ctx> rustc_target::HashStableContext for StableHashingContext<'ctx> {}
|
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) {
|
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
|
||||||
if self.is_empty() {
|
if self.is_empty() {
|
||||||
self.len().hash_stable(hcx, hasher);
|
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.
|
// Some attributes are always ignored during hashing.
|
||||||
let filtered: SmallVec<[&ast::Attribute; 8]> = self
|
let filtered: SmallVec<[&hir::Attribute; 8]> = self
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|attr| {
|
.filter(|attr| {
|
||||||
!attr.is_doc_comment()
|
!attr.is_doc_comment()
|
||||||
|
@ -35,30 +34,23 @@ impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx> rustc_ast::HashStableContext for StableHashingContext<'ctx> {
|
impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> {
|
||||||
fn hash_attr(&mut self, attr: &ast::Attribute, hasher: &mut StableHasher) {
|
fn hash_attr(&mut self, attr: &hir::Attribute, hasher: &mut StableHasher) {
|
||||||
// Make sure that these have been filtered out.
|
// 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.ident().is_some_and(|ident| self.is_ignored_attr(ident.name)));
|
||||||
debug_assert!(!attr.is_doc_comment());
|
debug_assert!(!attr.is_doc_comment());
|
||||||
|
|
||||||
let ast::Attribute { kind, id: _, style, span } = attr;
|
let hir::Attribute { kind, id: _, style, span } = attr;
|
||||||
if let ast::AttrKind::Normal(normal) = kind {
|
if let hir::AttrKind::Normal(item) = kind {
|
||||||
normal.item.hash_stable(self, hasher);
|
item.hash_stable(self, hasher);
|
||||||
style.hash_stable(self, hasher);
|
style.hash_stable(self, hasher);
|
||||||
span.hash_stable(self, hasher);
|
span.hash_stable(self, hasher);
|
||||||
assert_matches!(
|
|
||||||
normal.tokens.as_ref(),
|
|
||||||
None,
|
|
||||||
"Tokens should have been removed during lowering!"
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> {}
|
|
||||||
|
|
||||||
impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
|
impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
|
||||||
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
|
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
|
||||||
let SourceFile {
|
let SourceFile {
|
||||||
|
|
|
@ -7,7 +7,7 @@ use std::mem;
|
||||||
use rustc_ast::expand::StrippedCfgItem;
|
use rustc_ast::expand::StrippedCfgItem;
|
||||||
use rustc_ast::{self as ast, Crate, Inline, ItemKind, ModKind, NodeId, attr};
|
use rustc_ast::{self as ast, Crate, Inline, ItemKind, ModKind, NodeId, attr};
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_attr::StabilityLevel;
|
use rustc_attr::{AttributeExt, StabilityLevel};
|
||||||
use rustc_data_structures::intern::Interned;
|
use rustc_data_structures::intern::Interned;
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_errors::{Applicability, StashKey};
|
use rustc_errors::{Applicability, StashKey};
|
||||||
|
@ -1126,7 +1126,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||||
&mut self,
|
&mut self,
|
||||||
macro_def: &ast::MacroDef,
|
macro_def: &ast::MacroDef,
|
||||||
ident: Ident,
|
ident: Ident,
|
||||||
attrs: &[ast::Attribute],
|
attrs: &[impl AttributeExt],
|
||||||
span: Span,
|
span: Span,
|
||||||
node_id: NodeId,
|
node_id: NodeId,
|
||||||
edition: Edition,
|
edition: Edition,
|
||||||
|
|
|
@ -6,6 +6,7 @@ use pulldown_cmark::{
|
||||||
};
|
};
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_ast::util::comments::beautify_doc_string;
|
use rustc_ast::util::comments::beautify_doc_string;
|
||||||
|
use rustc_attr::AttributeExt;
|
||||||
use rustc_data_structures::fx::FxIndexMap;
|
use rustc_data_structures::fx::FxIndexMap;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_span::def_id::DefId;
|
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>(
|
pub fn attrs_to_doc_fragments<'a, A: AttributeExt + Clone + 'a>(
|
||||||
attrs: impl Iterator<Item = (&'a ast::Attribute, Option<DefId>)>,
|
attrs: impl Iterator<Item = (&'a A, Option<DefId>)>,
|
||||||
doc_only: bool,
|
doc_only: bool,
|
||||||
) -> (Vec<DocFragment>, ast::AttrVec) {
|
) -> (Vec<DocFragment>, Vec<A>) {
|
||||||
let mut doc_fragments = Vec::new();
|
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 {
|
for (attr, item_id) in attrs {
|
||||||
if let Some((doc_str, comment_kind)) = attr.doc_str_and_comment_kind() {
|
if let Some((doc_str, comment_kind)) = attr.doc_str_and_comment_kind() {
|
||||||
let doc = beautify_doc_string(doc_str, comment_kind);
|
let doc = beautify_doc_string(doc_str, comment_kind);
|
||||||
let (span, kind) = if attr.is_doc_comment() {
|
let (span, kind) = if attr.is_doc_comment() {
|
||||||
(attr.span, DocFragmentKind::SugaredDoc)
|
(attr.span(), DocFragmentKind::SugaredDoc)
|
||||||
} else {
|
} 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 };
|
let fragment = DocFragment { span, doc, kind, item_id, indent: 0 };
|
||||||
doc_fragments.push(fragment);
|
doc_fragments.push(fragment);
|
||||||
|
@ -218,16 +224,6 @@ pub fn attrs_to_doc_fragments<'a>(
|
||||||
(doc_fragments, other_attrs)
|
(doc_fragments, other_attrs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn span_for_value(attr: &ast::Attribute) -> Span {
|
|
||||||
if let ast::AttrKind::Normal(normal) = &attr.kind
|
|
||||||
&& let ast::AttrArgs::Eq { value, .. } = &normal.item.args
|
|
||||||
{
|
|
||||||
value.span().with_ctxt(attr.span.ctxt())
|
|
||||||
} else {
|
|
||||||
attr.span
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the doc-comments on this item, grouped by the module they came from.
|
/// 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.
|
/// 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.
|
//// If there are no doc-comments, return true.
|
||||||
/// FIXME(#78591): Support both inner and outer attributes on the same item.
|
/// FIXME(#78591): Support both inner and outer attributes on the same item.
|
||||||
pub fn inner_docs(attrs: &[ast::Attribute]) -> bool {
|
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)
|
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)]`.
|
/// 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 {
|
for attr in attrs {
|
||||||
if attr.has_name(sym::rustc_doc_primitive) {
|
if attr.has_name(sym::rustc_doc_primitive) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -408,7 +407,7 @@ pub fn may_be_doc_link(link_type: LinkType) -> bool {
|
||||||
|
|
||||||
/// Simplified version of `preprocessed_markdown_links` from rustdoc.
|
/// 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.
|
/// 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_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();
|
let doc = prepare_to_doc_link_resolution(&doc_fragments).into_values().next().unwrap();
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,9 @@ edition = "2021"
|
||||||
# tidy-alphabetical-start
|
# tidy-alphabetical-start
|
||||||
rustc_abi = { path = "../rustc_abi" }
|
rustc_abi = { path = "../rustc_abi" }
|
||||||
rustc_ast = { path = "../rustc_ast" }
|
rustc_ast = { path = "../rustc_ast" }
|
||||||
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
|
||||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||||
rustc_hir = { path = "../rustc_hir" }
|
rustc_hir = { path = "../rustc_hir" }
|
||||||
|
rustc_hir_pretty = { path = "../rustc_hir_pretty" }
|
||||||
rustc_middle = { path = "../rustc_middle" }
|
rustc_middle = { path = "../rustc_middle" }
|
||||||
rustc_session = { path = "../rustc_session" }
|
rustc_session = { path = "../rustc_session" }
|
||||||
rustc_span = { path = "../rustc_span" }
|
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();
|
attr.iter().map(|seg| rustc_span::symbol::Symbol::intern(&seg)).collect();
|
||||||
tcx.get_attrs_by_path(did, &attr_name)
|
tcx.get_attrs_by_path(did, &attr_name)
|
||||||
.map(|attribute| {
|
.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;
|
let span = attribute.span;
|
||||||
stable_mir::crate_def::Attribute::new(attr_str, span.stable(&mut *tables))
|
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 mut tables = self.0.borrow_mut();
|
||||||
let tcx = tables.tcx;
|
let tcx = tables.tcx;
|
||||||
let did = tables[def_id];
|
let did = tables[def_id];
|
||||||
let filter_fn = move |a: &&rustc_ast::ast::Attribute| {
|
let filter_fn =
|
||||||
matches!(a.kind, rustc_ast::ast::AttrKind::Normal(_))
|
move |a: &&rustc_hir::Attribute| matches!(a.kind, rustc_hir::AttrKind::Normal(_));
|
||||||
};
|
|
||||||
let attrs_iter = if let Some(did) = did.as_local() {
|
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)
|
tcx.hir().attrs(tcx.local_def_id_to_hir_id(did)).iter().filter(filter_fn)
|
||||||
} else {
|
} else {
|
||||||
tcx.item_attrs(did).iter().filter(filter_fn)
|
tcx.attrs_for_def(did).iter().filter(filter_fn)
|
||||||
};
|
};
|
||||||
attrs_iter
|
attrs_iter
|
||||||
.map(|attribute| {
|
.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;
|
let span = attribute.span;
|
||||||
stable_mir::crate_def::Attribute::new(attr_str, span.stable(&mut *tables))
|
stable_mir::crate_def::Attribute::new(attr_str, span.stable(&mut *tables))
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use rustc_ast::{AttrArgs, AttrKind, Attribute, MetaItemInner};
|
use rustc_ast::MetaItemInner;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_errors::codes::*;
|
use rustc_errors::codes::*;
|
||||||
use rustc_errors::{ErrorGuaranteed, struct_span_code_err};
|
use rustc_errors::{ErrorGuaranteed, struct_span_code_err};
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
|
use rustc_hir::{AttrArgs, AttrKind, Attribute};
|
||||||
use rustc_macros::LintDiagnostic;
|
use rustc_macros::LintDiagnostic;
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::ty::print::PrintTraitRefExt as _;
|
use rustc_middle::ty::print::PrintTraitRefExt as _;
|
||||||
|
@ -639,7 +640,7 @@ impl<'tcx> OnUnimplementedDirective {
|
||||||
let report_span = match &item.args {
|
let report_span = match &item.args {
|
||||||
AttrArgs::Empty => item.path.span,
|
AttrArgs::Empty => item.path.span,
|
||||||
AttrArgs::Delimited(args) => args.dspan.entire(),
|
AttrArgs::Delimited(args) => args.dspan.entire(),
|
||||||
AttrArgs::Eq { eq_span, value } => eq_span.to(value.span()),
|
AttrArgs::Eq { eq_span, expr } => eq_span.to(expr.span),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(item_def_id) = item_def_id.as_local() {
|
if let Some(item_def_id) = item_def_id.as_local() {
|
||||||
|
@ -654,7 +655,7 @@ impl<'tcx> OnUnimplementedDirective {
|
||||||
}
|
}
|
||||||
} else if is_diagnostic_namespace_variant {
|
} else if is_diagnostic_namespace_variant {
|
||||||
match &attr.kind {
|
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() {
|
if let Some(item_def_id) = item_def_id.as_local() {
|
||||||
tcx.emit_node_span_lint(
|
tcx.emit_node_span_lint(
|
||||||
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
|
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
|
||||||
|
|
|
@ -4,6 +4,7 @@ use std::iter::once;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
|
use rustc_hir as hir;
|
||||||
use rustc_hir::Mutability;
|
use rustc_hir::Mutability;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::def_id::{DefId, DefIdSet, LocalDefId, LocalModDefId};
|
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 rustc_span::symbol::{Symbol, sym};
|
||||||
use thin_vec::{ThinVec, thin_vec};
|
use thin_vec::{ThinVec, thin_vec};
|
||||||
use tracing::{debug, trace};
|
use tracing::{debug, trace};
|
||||||
use {rustc_ast as ast, rustc_hir as hir};
|
|
||||||
|
|
||||||
use super::Item;
|
use super::Item;
|
||||||
use crate::clean::{
|
use crate::clean::{
|
||||||
|
@ -43,7 +43,7 @@ pub(crate) fn try_inline(
|
||||||
cx: &mut DocContext<'_>,
|
cx: &mut DocContext<'_>,
|
||||||
res: Res,
|
res: Res,
|
||||||
name: Symbol,
|
name: Symbol,
|
||||||
attrs: Option<(&[ast::Attribute], Option<LocalDefId>)>,
|
attrs: Option<(&[hir::Attribute], Option<LocalDefId>)>,
|
||||||
visited: &mut DefIdSet,
|
visited: &mut DefIdSet,
|
||||||
) -> Option<Vec<clean::Item>> {
|
) -> Option<Vec<clean::Item>> {
|
||||||
let did = res.opt_def_id()?;
|
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)
|
cx.tcx.get_attrs_unchecked(did)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,7 +360,7 @@ fn build_type_alias(
|
||||||
pub(crate) fn build_impls(
|
pub(crate) fn build_impls(
|
||||||
cx: &mut DocContext<'_>,
|
cx: &mut DocContext<'_>,
|
||||||
did: DefId,
|
did: DefId,
|
||||||
attrs: Option<(&[ast::Attribute], Option<LocalDefId>)>,
|
attrs: Option<(&[hir::Attribute], Option<LocalDefId>)>,
|
||||||
ret: &mut Vec<clean::Item>,
|
ret: &mut Vec<clean::Item>,
|
||||||
) {
|
) {
|
||||||
let _prof_timer = cx.tcx.sess.prof.generic_activity("build_inherent_impls");
|
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(
|
pub(crate) fn merge_attrs(
|
||||||
cx: &mut DocContext<'_>,
|
cx: &mut DocContext<'_>,
|
||||||
old_attrs: &[ast::Attribute],
|
old_attrs: &[hir::Attribute],
|
||||||
new_attrs: Option<(&[ast::Attribute], Option<LocalDefId>)>,
|
new_attrs: Option<(&[hir::Attribute], Option<LocalDefId>)>,
|
||||||
) -> (clean::Attributes, Option<Arc<clean::cfg::Cfg>>) {
|
) -> (clean::Attributes, Option<Arc<clean::cfg::Cfg>>) {
|
||||||
// NOTE: If we have additional attributes (from a re-export),
|
// NOTE: If we have additional attributes (from a re-export),
|
||||||
// always insert them first. This ensure that 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);
|
both.extend_from_slice(old_attrs);
|
||||||
(
|
(
|
||||||
if let Some(item_id) = item_id {
|
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 {
|
} else {
|
||||||
Attributes::from_ast(&both)
|
Attributes::from_hir(&both)
|
||||||
},
|
},
|
||||||
both.cfg(cx.tcx, &cx.cache.hidden_cfg),
|
both.cfg(cx.tcx, &cx.cache.hidden_cfg),
|
||||||
)
|
)
|
||||||
} else {
|
} 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(
|
pub(crate) fn build_impl(
|
||||||
cx: &mut DocContext<'_>,
|
cx: &mut DocContext<'_>,
|
||||||
did: DefId,
|
did: DefId,
|
||||||
attrs: Option<(&[ast::Attribute], Option<LocalDefId>)>,
|
attrs: Option<(&[hir::Attribute], Option<LocalDefId>)>,
|
||||||
ret: &mut Vec<clean::Item>,
|
ret: &mut Vec<clean::Item>,
|
||||||
) {
|
) {
|
||||||
if !cx.inlined.insert(did.into()) {
|
if !cx.inlined.insert(did.into()) {
|
||||||
|
@ -629,7 +629,7 @@ fn build_module_items(
|
||||||
visited: &mut DefIdSet,
|
visited: &mut DefIdSet,
|
||||||
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
|
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
|
||||||
allowed_def_ids: Option<&DefIdSet>,
|
allowed_def_ids: Option<&DefIdSet>,
|
||||||
attrs: Option<(&[ast::Attribute], Option<LocalDefId>)>,
|
attrs: Option<(&[hir::Attribute], Option<LocalDefId>)>,
|
||||||
) -> Vec<clean::Item> {
|
) -> Vec<clean::Item> {
|
||||||
let mut items = Vec::new();
|
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 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 name = renamed.or(Some(name));
|
||||||
let mut item = Item::from_def_id_and_attrs_and_parts(def_id, name, kind, attrs, cfg);
|
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
|
/// This is needed to make it more "readable" when documenting functions using
|
||||||
/// `rustc_legacy_const_generics`. More information in
|
/// `rustc_legacy_const_generics`. More information in
|
||||||
/// <https://github.com/rust-lang/rust/issues/83167>.
|
/// <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
|
for meta_item_list in attrs
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|a| a.has_name(sym::rustc_legacy_const_generics))
|
.filter(|a| a.has_name(sym::rustc_legacy_const_generics))
|
||||||
|
@ -2578,7 +2578,7 @@ fn get_all_import_attributes<'hir>(
|
||||||
import_def_id: LocalDefId,
|
import_def_id: LocalDefId,
|
||||||
target_def_id: DefId,
|
target_def_id: DefId,
|
||||||
is_inline: bool,
|
is_inline: bool,
|
||||||
) -> Vec<(Cow<'hir, ast::Attribute>, Option<DefId>)> {
|
) -> Vec<(Cow<'hir, hir::Attribute>, Option<DefId>)> {
|
||||||
let mut attrs = Vec::new();
|
let mut attrs = Vec::new();
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
for def_id in reexport_chain(cx.tcx, import_def_id, target_def_id)
|
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.
|
/// Remove attributes from `normal` that should not be inherited by `use` re-export.
|
||||||
/// Before calling this function, make sure `normal` is a `#[doc]` attribute.
|
/// Before calling this function, make sure `normal` is a `#[doc]` attribute.
|
||||||
fn filter_doc_attr(normal: &mut ast::NormalAttr, is_inline: bool) {
|
fn filter_doc_attr(args: &mut hir::AttrArgs, is_inline: bool) {
|
||||||
match normal.item.args {
|
match args {
|
||||||
ast::AttrArgs::Delimited(ref mut args) => {
|
hir::AttrArgs::Delimited(ref mut args) => {
|
||||||
let tokens = filter_tokens_from_list(&args.tokens, |token| {
|
let tokens = filter_tokens_from_list(&args.tokens, |token| {
|
||||||
!matches!(
|
!matches!(
|
||||||
token,
|
token,
|
||||||
|
@ -2651,7 +2651,7 @@ fn filter_doc_attr(normal: &mut ast::NormalAttr, is_inline: bool) {
|
||||||
});
|
});
|
||||||
args.tokens = TokenStream::new(tokens);
|
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(no_inline)`
|
||||||
/// * `doc(hidden)`
|
/// * `doc(hidden)`
|
||||||
fn add_without_unwanted_attributes<'hir>(
|
fn add_without_unwanted_attributes<'hir>(
|
||||||
attrs: &mut Vec<(Cow<'hir, ast::Attribute>, Option<DefId>)>,
|
attrs: &mut Vec<(Cow<'hir, hir::Attribute>, Option<DefId>)>,
|
||||||
new_attrs: &'hir [ast::Attribute],
|
new_attrs: &'hir [hir::Attribute],
|
||||||
is_inline: bool,
|
is_inline: bool,
|
||||||
import_parent: Option<DefId>,
|
import_parent: Option<DefId>,
|
||||||
) {
|
) {
|
||||||
for attr in new_attrs {
|
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));
|
attrs.push((Cow::Borrowed(attr), import_parent));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let mut attr = attr.clone();
|
let mut attr = attr.clone();
|
||||||
match attr.kind {
|
match attr.kind {
|
||||||
ast::AttrKind::Normal(ref mut normal) => {
|
hir::AttrKind::Normal(ref mut normal) => {
|
||||||
if let [ident] = &*normal.item.path.segments {
|
if let [ident] = &*normal.path.segments {
|
||||||
let ident = ident.ident.name;
|
let ident = ident.name;
|
||||||
if ident == sym::doc {
|
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));
|
attrs.push((Cow::Owned(attr), import_parent));
|
||||||
} else if is_inline || ident != sym::cfg {
|
} else if is_inline || ident != sym::cfg {
|
||||||
// If it's not a `cfg()` attribute, we keep it.
|
// If it's not a `cfg()` attribute, we keep it.
|
||||||
|
|
|
@ -6,8 +6,6 @@ use std::{fmt, iter};
|
||||||
|
|
||||||
use arrayvec::ArrayVec;
|
use arrayvec::ArrayVec;
|
||||||
use rustc_abi::{ExternAbi, VariantIdx};
|
use rustc_abi::{ExternAbi, VariantIdx};
|
||||||
use rustc_ast::MetaItemInner;
|
|
||||||
use rustc_ast_pretty::pprust;
|
|
||||||
use rustc_attr::{ConstStability, Deprecation, Stability, StableSince};
|
use rustc_attr::{ConstStability, Deprecation, Stability, StableSince};
|
||||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||||
|
@ -454,14 +452,14 @@ impl Item {
|
||||||
kind: ItemKind,
|
kind: ItemKind,
|
||||||
cx: &mut DocContext<'_>,
|
cx: &mut DocContext<'_>,
|
||||||
) -> Item {
|
) -> 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(
|
Self::from_def_id_and_attrs_and_parts(
|
||||||
def_id,
|
def_id,
|
||||||
name,
|
name,
|
||||||
kind,
|
kind,
|
||||||
Attributes::from_ast(ast_attrs),
|
Attributes::from_hir(hir_attrs),
|
||||||
ast_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
|
hir_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -742,10 +740,10 @@ impl Item {
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|attr| {
|
.filter_map(|attr| {
|
||||||
if keep_as_is {
|
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()) {
|
} else if ALLOWED_ATTRIBUTES.contains(&attr.name_or_empty()) {
|
||||||
Some(
|
Some(
|
||||||
pprust::attribute_to_string(attr)
|
rustc_hir_pretty::attribute_to_string(&tcx, attr)
|
||||||
.replace("\\\n", "")
|
.replace("\\\n", "")
|
||||||
.replace('\n', "")
|
.replace('\n', "")
|
||||||
.replace(" ", " "),
|
.replace(" ", " "),
|
||||||
|
@ -955,7 +953,7 @@ pub(crate) trait AttributesExt {
|
||||||
type AttributeIterator<'a>: Iterator<Item = ast::MetaItemInner>
|
type AttributeIterator<'a>: Iterator<Item = ast::MetaItemInner>
|
||||||
where
|
where
|
||||||
Self: 'a;
|
Self: 'a;
|
||||||
type Attributes<'a>: Iterator<Item = &'a ast::Attribute>
|
type Attributes<'a>: Iterator<Item = &'a hir::Attribute>
|
||||||
where
|
where
|
||||||
Self: 'a;
|
Self: 'a;
|
||||||
|
|
||||||
|
@ -1009,7 +1007,7 @@ pub(crate) trait AttributesExt {
|
||||||
// #[doc]
|
// #[doc]
|
||||||
if attr.doc_str().is_none() && attr.has_name(sym::doc) {
|
if attr.doc_str().is_none() && attr.has_name(sym::doc) {
|
||||||
// #[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 {
|
for item in list {
|
||||||
// #[doc(hidden)]
|
// #[doc(hidden)]
|
||||||
if !item.has_name(sym::cfg) {
|
if !item.has_name(sym::cfg) {
|
||||||
|
@ -1042,7 +1040,7 @@ pub(crate) trait AttributesExt {
|
||||||
let mut meta = attr.meta_item().unwrap().clone();
|
let mut meta = attr.meta_item().unwrap().clone();
|
||||||
meta.path = ast::Path::from_ident(Ident::with_dummy_span(sym::target_feature));
|
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;
|
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 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<'_> {
|
fn lists(&self, name: Symbol) -> Self::AttributeIterator<'_> {
|
||||||
self.iter()
|
self.iter()
|
||||||
.filter(move |attr| attr.has_name(name))
|
.filter(move |attr| attr.has_name(name))
|
||||||
.filter_map(ast::Attribute::meta_item_list)
|
.filter_map(ast::attr::AttributeExt::meta_item_list)
|
||||||
.flatten()
|
.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>
|
type AttributeIterator<'a>
|
||||||
= impl Iterator<Item = ast::MetaItemInner> + 'a
|
= impl Iterator<Item = ast::MetaItemInner> + 'a
|
||||||
where
|
where
|
||||||
Self: 'a;
|
Self: 'a;
|
||||||
type Attributes<'a>
|
type Attributes<'a>
|
||||||
= impl Iterator<Item = &'a ast::Attribute> + 'a
|
= impl Iterator<Item = &'a hir::Attribute> + 'a
|
||||||
where
|
where
|
||||||
Self: 'a;
|
Self: 'a;
|
||||||
|
|
||||||
fn lists(&self, name: Symbol) -> Self::AttributeIterator<'_> {
|
fn lists(&self, name: Symbol) -> Self::AttributeIterator<'_> {
|
||||||
AttributesExt::iter(self)
|
AttributesExt::iter(self)
|
||||||
.filter(move |attr| attr.has_name(name))
|
.filter(move |attr| attr.has_name(name))
|
||||||
.filter_map(ast::Attribute::meta_item_list)
|
.filter_map(hir::Attribute::meta_item_list)
|
||||||
.flatten()
|
.flatten()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1152,7 +1150,7 @@ pub struct RenderedLink {
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub(crate) struct Attributes {
|
pub(crate) struct Attributes {
|
||||||
pub(crate) doc_strings: Vec<DocFragment>,
|
pub(crate) doc_strings: Vec<DocFragment>,
|
||||||
pub(crate) other_attrs: ast::AttrVec,
|
pub(crate) other_attrs: Vec<hir::Attribute>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Attributes {
|
impl Attributes {
|
||||||
|
@ -1180,22 +1178,22 @@ impl Attributes {
|
||||||
self.has_doc_flag(sym::hidden)
|
self.has_doc_flag(sym::hidden)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_ast(attrs: &[ast::Attribute]) -> Attributes {
|
pub(crate) fn from_hir(attrs: &[hir::Attribute]) -> Attributes {
|
||||||
Attributes::from_ast_iter(attrs.iter().map(|attr| (attr, None)), false)
|
Attributes::from_hir_iter(attrs.iter().map(|attr| (attr, None)), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_ast_with_additional(
|
pub(crate) fn from_hir_with_additional(
|
||||||
attrs: &[ast::Attribute],
|
attrs: &[hir::Attribute],
|
||||||
(additional_attrs, def_id): (&[ast::Attribute], DefId),
|
(additional_attrs, def_id): (&[hir::Attribute], DefId),
|
||||||
) -> Attributes {
|
) -> Attributes {
|
||||||
// Additional documentation should be shown before the original documentation.
|
// Additional documentation should be shown before the original documentation.
|
||||||
let attrs1 = additional_attrs.iter().map(|attr| (attr, Some(def_id)));
|
let attrs1 = additional_attrs.iter().map(|attr| (attr, Some(def_id)));
|
||||||
let attrs2 = attrs.iter().map(|attr| (attr, None));
|
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>(
|
pub(crate) fn from_hir_iter<'a>(
|
||||||
attrs: impl Iterator<Item = (&'a ast::Attribute, Option<DefId>)>,
|
attrs: impl Iterator<Item = (&'a hir::Attribute, Option<DefId>)>,
|
||||||
doc_only: bool,
|
doc_only: bool,
|
||||||
) -> Attributes {
|
) -> Attributes {
|
||||||
let (doc_strings, other_attrs) = attrs_to_doc_fragments(attrs, doc_only);
|
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>(
|
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,
|
flag: Symbol,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
attrs
|
attrs
|
||||||
|
|
|
@ -13,10 +13,10 @@ use std::{panic, str};
|
||||||
|
|
||||||
pub(crate) use make::DocTestBuilder;
|
pub(crate) use make::DocTestBuilder;
|
||||||
pub(crate) use markdown::test as test_markdown;
|
pub(crate) use markdown::test as test_markdown;
|
||||||
use rustc_ast as ast;
|
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
|
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
|
||||||
use rustc_errors::emitter::HumanReadableErrorType;
|
use rustc_errors::emitter::HumanReadableErrorType;
|
||||||
use rustc_errors::{ColorConfig, DiagCtxtHandle};
|
use rustc_errors::{ColorConfig, DiagCtxtHandle};
|
||||||
|
use rustc_hir as hir;
|
||||||
use rustc_hir::CRATE_HIR_ID;
|
use rustc_hir::CRATE_HIR_ID;
|
||||||
use rustc_hir::def_id::LOCAL_CRATE;
|
use rustc_hir::def_id::LOCAL_CRATE;
|
||||||
use rustc_interface::interface;
|
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.
|
// Look for `#![doc(test(no_crate_inject))]`, used by crates in the std facade.
|
||||||
fn scrape_test_config(
|
fn scrape_test_config(
|
||||||
crate_name: String,
|
crate_name: String,
|
||||||
attrs: &[ast::Attribute],
|
attrs: &[hir::Attribute],
|
||||||
args_file: PathBuf,
|
args_file: PathBuf,
|
||||||
) -> GlobalTestOptions {
|
) -> GlobalTestOptions {
|
||||||
use rustc_ast_pretty::pprust;
|
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
|
// The collapse-docs pass won't combine sugared/raw doc attributes, or included files with
|
||||||
// anything else, this will combine them for us.
|
// 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() {
|
if let Some(doc) = attrs.opt_doc_value() {
|
||||||
let span = span_of_fragments(&attrs.doc_strings).unwrap_or(sp);
|
let span = span_of_fragments(&attrs.doc_strings).unwrap_or(sp);
|
||||||
self.collector.position = if span.edition().at_least_rust_2024() {
|
self.collector.position = if span.edition().at_least_rust_2024() {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use super::INLINE_ALWAYS;
|
use super::INLINE_ALWAYS;
|
||||||
use super::utils::is_word;
|
use super::utils::is_word;
|
||||||
use clippy_utils::diagnostics::span_lint;
|
use clippy_utils::diagnostics::span_lint;
|
||||||
use rustc_ast::Attribute;
|
use rustc_hir::Attribute;
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
use rustc_span::{Span, sym};
|
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 clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use rustc_ast::token::{Token, TokenKind};
|
use rustc_ast::token::{Token, TokenKind};
|
||||||
use rustc_ast::tokenstream::TokenTree;
|
use rustc_ast::tokenstream::TokenTree;
|
||||||
use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind};
|
use rustc_ast::{AttrArgs, AttrKind};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_lint::EarlyContext;
|
use rustc_lint::EarlyContext;
|
||||||
use rustc_span::sym;
|
use rustc_span::sym;
|
||||||
|
|
||||||
pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) {
|
pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) {
|
||||||
if let AttrKind::Normal(normal_attr) = &attr.kind {
|
if let AttrKind::Normal(normal_attr) = &attr.kind {
|
||||||
if let AttrArgs::Eq { value: AttrArgsEq::Ast(_), .. } = &normal_attr.item.args {
|
if let AttrArgs::Eq { .. } = &normal_attr.item.args {
|
||||||
// `#[should_panic = ".."]` found, good
|
// `#[should_panic = ".."]` found, good
|
||||||
return;
|
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::visitors::for_each_expr_without_closures;
|
||||||
use clippy_utils::{LimitStack, get_async_fn_body, is_async_fn};
|
use clippy_utils::{LimitStack, get_async_fn_body, is_async_fn};
|
||||||
use core::ops::ControlFlow;
|
use core::ops::ControlFlow;
|
||||||
use rustc_ast::ast::Attribute;
|
|
||||||
use rustc_hir::intravisit::FnKind;
|
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_lint::{LateContext, LateLintPass, LintContext};
|
||||||
use rustc_session::impl_lint_pass;
|
use rustc_session::impl_lint_pass;
|
||||||
use rustc_span::def_id::LocalDefId;
|
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::source::{SpanRangeExt, snippet_indent};
|
||||||
use clippy_utils::tokenize_with_text;
|
use clippy_utils::tokenize_with_text;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
use rustc_ast::AttrStyle;
|
||||||
use rustc_ast::token::CommentKind;
|
use rustc_ast::token::CommentKind;
|
||||||
use rustc_ast::{AttrKind, AttrStyle, Attribute};
|
|
||||||
use rustc_errors::{Applicability, Diag, SuggestionStyle};
|
use rustc_errors::{Applicability, Diag, SuggestionStyle};
|
||||||
use rustc_hir::{ItemKind, Node};
|
use rustc_hir::{AttrKind, Attribute, ItemKind, Node};
|
||||||
use rustc_lexer::TokenKind;
|
use rustc_lexer::TokenKind;
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_span::{BytePos, ExpnKind, InnerSpan, Span, SpanData};
|
use rustc_span::{BytePos, ExpnKind, InnerSpan, Span, SpanData};
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::snippet_opt;
|
||||||
use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind, AttrStyle, Attribute};
|
use rustc_ast::{AttrStyle};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_span::sym;
|
use rustc_hir::{Attribute, AttrKind, AttrArgs};
|
||||||
|
|
||||||
use super::DOC_INCLUDE_WITHOUT_CFG;
|
use super::DOC_INCLUDE_WITHOUT_CFG;
|
||||||
|
|
||||||
pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) {
|
pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) {
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
if !attr.span.from_expansion()
|
if !attr.span.from_expansion()
|
||||||
&& let AttrKind::Normal(ref normal) = attr.kind
|
&& let AttrKind::Normal(ref item) = attr.kind
|
||||||
&& normal.item.path == sym::doc
|
&& attr.doc_str().is_some()
|
||||||
&& let AttrArgs::Eq { value: AttrArgsEq::Hir(ref meta), .. } = normal.item.args
|
&& let AttrArgs::Eq { expr: meta, .. } = &item.args
|
||||||
&& !attr.span.contains(meta.span)
|
&& !attr.span.contains(meta.span)
|
||||||
// Since the `include_str` is already expanded at this point, we can only take the
|
// Since the `include_str` is already expanded at this point, we can only take the
|
||||||
// whole attribute snippet and then modify for our suggestion.
|
// 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::Tag::{BlockQuote, CodeBlock, FootnoteDefinition, Heading, Item, Link, Paragraph};
|
||||||
use pulldown_cmark::{BrokenLink, CodeBlockKind, CowStr, Options, TagEnd};
|
use pulldown_cmark::{BrokenLink, CodeBlockKind, CowStr, Options, TagEnd};
|
||||||
use rustc_ast::ast::Attribute;
|
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_hir::intravisit::{self, Visitor};
|
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_lint::{LateContext, LateLintPass, LintContext};
|
||||||
use rustc_middle::hir::nested_filter;
|
use rustc_middle::hir::nested_filter;
|
||||||
use rustc_middle::lint::in_external_macro;
|
use rustc_middle::lint::in_external_macro;
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
|
use rustc_ast::AttrStyle;
|
||||||
use rustc_ast::token::CommentKind;
|
use rustc_ast::token::CommentKind;
|
||||||
use rustc_ast::{AttrKind, AttrStyle, Attribute};
|
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
|
use rustc_hir::Attribute;
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
|
@ -35,7 +36,7 @@ fn collect_doc_replacements(attrs: &[Attribute]) -> Vec<(Span, String)> {
|
||||||
attrs
|
attrs
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|attr| {
|
.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 AttrStyle::Outer = attr.style
|
||||||
&& let Some(com) = sym.as_str().strip_prefix('!')
|
&& let Some(com) = sym.as_str().strip_prefix('!')
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use rustc_ast::ast::Attribute;
|
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{Item, ItemKind};
|
use rustc_hir::{Attribute, Item, ItemKind};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
|
|
||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
use hir::FnSig;
|
use hir::FnSig;
|
||||||
use rustc_ast::ast::Attribute;
|
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::def::Res;
|
use rustc_hir::def::Res;
|
||||||
use rustc_hir::def_id::DefIdSet;
|
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_infer::infer::TyCtxtInferExt;
|
||||||
use rustc_lint::{LateContext, LintContext};
|
use rustc_lint::{LateContext, LintContext};
|
||||||
use rustc_middle::lint::in_external_macro;
|
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::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::macros::root_macro_call_first_node;
|
use clippy_utils::macros::root_macro_call_first_node;
|
||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::snippet_opt;
|
||||||
use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind, Attribute, LitKind};
|
use rustc_ast::{LitKind};
|
||||||
use rustc_hir::{Expr, ExprKind};
|
use rustc_hir::{Expr, ExprKind, Attribute, AttrArgs, AttrKind};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_session::impl_lint_pass;
|
use rustc_session::impl_lint_pass;
|
||||||
use rustc_span::{Span, sym};
|
use rustc_span::{Span, sym};
|
||||||
|
@ -93,10 +93,10 @@ impl LateLintPass<'_> for LargeIncludeFile {
|
||||||
if !attr.span.from_expansion()
|
if !attr.span.from_expansion()
|
||||||
// Currently, rustc limits the usage of macro at the top-level of attributes,
|
// Currently, rustc limits the usage of macro at the top-level of attributes,
|
||||||
// so we don't need to recurse into each level.
|
// 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()
|
&& let Some(doc) = attr.doc_str()
|
||||||
&& doc.as_str().len() as u64 > self.max_file_size
|
&& doc.as_str().len() as u64 > self.max_file_size
|
||||||
&& let AttrArgs::Eq { value: AttrArgsEq::Hir(ref meta), .. } = normal.item.args
|
&& let AttrArgs::Eq { expr: meta, .. } = &item.args
|
||||||
&& !attr.span.contains(meta.span)
|
&& !attr.span.contains(meta.span)
|
||||||
// Since the `include_str` is already expanded at this point, we can only take the
|
// Since the `include_str` is already expanded at this point, we can only take the
|
||||||
// whole attribute snippet and then modify for our suggestion.
|
// 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::diagnostics::span_lint_hir_and_then;
|
||||||
use clippy_utils::source::snippet;
|
use clippy_utils::source::snippet;
|
||||||
use hir::def::{DefKind, Res};
|
use hir::def::{DefKind, Res};
|
||||||
use rustc_ast::ast;
|
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
@ -104,7 +103,7 @@ impl LateLintPass<'_> for MacroUseImports {
|
||||||
self.push_unique_macro_pat_ty(cx, item.span);
|
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() {
|
if attr.span.from_expansion() {
|
||||||
self.push_unique_macro(cx, attr.span);
|
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::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::source::snippet_with_applicability;
|
use clippy_utils::source::snippet_with_applicability;
|
||||||
use clippy_utils::{is_lint_allowed, is_wild, span_contains_comment};
|
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_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_lint::{LateContext, LintContext};
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_span::source_map::Spanned;
|
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::diagnostics::span_lint;
|
||||||
use clippy_utils::is_from_proc_macro;
|
use clippy_utils::is_from_proc_macro;
|
||||||
use clippy_utils::source::SpanRangeExt;
|
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 as hir;
|
||||||
|
use rustc_hir::Attribute;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||||
|
@ -67,9 +68,8 @@ impl MissingDoc {
|
||||||
*self.doc_hidden_stack.last().expect("empty doc_hidden_stack")
|
*self.doc_hidden_stack.last().expect("empty doc_hidden_stack")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_include(meta: Option<MetaItem>) -> bool {
|
fn has_include(meta: Option<&[MetaItemInner]>) -> bool {
|
||||||
if let Some(meta) = meta
|
if let Some(list) = meta
|
||||||
&& let MetaItemKind::List(list) = meta.kind
|
|
||||||
&& let Some(meta) = list.first()
|
&& let Some(meta) = list.first()
|
||||||
&& let Some(name) = meta.ident()
|
&& let Some(name) = meta.ident()
|
||||||
{
|
{
|
||||||
|
@ -83,7 +83,7 @@ impl MissingDoc {
|
||||||
&self,
|
&self,
|
||||||
cx: &LateContext<'_>,
|
cx: &LateContext<'_>,
|
||||||
def_id: LocalDefId,
|
def_id: LocalDefId,
|
||||||
attrs: &[ast::Attribute],
|
attrs: &[Attribute],
|
||||||
sp: Span,
|
sp: Span,
|
||||||
article: &'static str,
|
article: &'static str,
|
||||||
desc: &'static str,
|
desc: &'static str,
|
||||||
|
@ -129,7 +129,7 @@ impl MissingDoc {
|
||||||
|
|
||||||
let has_doc = attrs
|
let has_doc = attrs
|
||||||
.iter()
|
.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));
|
|| matches!(self.search_span(sp), Some(span) if span_to_snippet_contains_docs(cx, span));
|
||||||
|
|
||||||
if !has_doc {
|
if !has_doc {
|
||||||
|
@ -172,12 +172,12 @@ impl MissingDoc {
|
||||||
impl_lint_pass!(MissingDoc => [MISSING_DOCS_IN_PRIVATE_ITEMS]);
|
impl_lint_pass!(MissingDoc => [MISSING_DOCS_IN_PRIVATE_ITEMS]);
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for MissingDoc {
|
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);
|
let doc_hidden = self.doc_hidden() || is_doc_hidden(attrs);
|
||||||
self.doc_hidden_stack.push(doc_hidden);
|
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");
|
self.doc_hidden_stack.pop().expect("empty doc_hidden_stack");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use clippy_utils::diagnostics::span_lint;
|
use clippy_utils::diagnostics::span_lint;
|
||||||
use rustc_ast::ast;
|
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
use rustc_hir::Attribute;
|
||||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||||
use rustc_middle::ty::AssocItemContainer;
|
use rustc_middle::ty::AssocItemContainer;
|
||||||
use rustc_session::declare_lint_pass;
|
use rustc_session::declare_lint_pass;
|
||||||
|
@ -63,7 +63,7 @@ declare_clippy_lint! {
|
||||||
"detects missing `#[inline]` attribute for public callables (functions, trait methods, methods...)"
|
"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));
|
let has_inline = attrs.iter().any(|a| a.has_name(sym::inline));
|
||||||
if !has_inline {
|
if !has_inline {
|
||||||
span_lint(
|
span_lint(
|
||||||
|
|
|
@ -5,12 +5,11 @@ use clippy_utils::source::{SpanRangeExt, snippet};
|
||||||
use clippy_utils::ty::{
|
use clippy_utils::ty::{
|
||||||
implements_trait, implements_trait_with_env_from_iter, is_copy, is_type_diagnostic_item, is_type_lang_item,
|
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_errors::{Applicability, Diag};
|
||||||
use rustc_hir::intravisit::FnKind;
|
use rustc_hir::intravisit::FnKind;
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
BindingMode, Body, FnDecl, GenericArg, HirId, HirIdSet, Impl, ItemKind, LangItem, Mutability, Node, PatKind, QPath,
|
Attribute, BindingMode, Body, FnDecl, GenericArg, HirId, HirIdSet, Impl, ItemKind, LangItem, Mutability, Node,
|
||||||
TyKind,
|
PatKind, QPath, TyKind,
|
||||||
};
|
};
|
||||||
use rustc_hir_typeck::expr_use_visitor as euv;
|
use rustc_hir_typeck::expr_use_visitor as euv;
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
|
|
|
@ -872,8 +872,7 @@ pub fn eq_attr_args(l: &AttrArgs, r: &AttrArgs) -> bool {
|
||||||
match (l, r) {
|
match (l, r) {
|
||||||
(Empty, Empty) => true,
|
(Empty, Empty) => true,
|
||||||
(Delimited(la), Delimited(ra)) => eq_delim_args(la, ra),
|
(Delimited(la), Delimited(ra)) => eq_delim_args(la, ra),
|
||||||
(Eq { value: AttrArgsEq::Ast(le), .. }, Eq{ value: AttrArgsEq::Ast(re), .. }) => eq_expr(le, re),
|
(Eq { eq_span: _, expr: le }, Eq { eq_span: _, expr: re }) => eq_expr(le, re),
|
||||||
(Eq { value: AttrArgsEq::Hir(ll), .. }, Eq{ value: AttrArgsEq::Hir(rl), .. }) => ll.kind == rl.kind,
|
|
||||||
_ => false,
|
_ => 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_errors::Applicability;
|
||||||
use rustc_lexer::TokenKind;
|
use rustc_lexer::TokenKind;
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
|
@ -51,33 +52,31 @@ impl LimitStack {
|
||||||
pub fn limit(&self) -> u64 {
|
pub fn limit(&self) -> u64 {
|
||||||
*self.stack.last().expect("there should always be a value in the stack")
|
*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;
|
let stack = &mut self.stack;
|
||||||
parse_attrs(sess, attrs, name, |val| stack.push(val));
|
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;
|
let stack = &mut self.stack;
|
||||||
parse_attrs(sess, attrs, name, |val| assert_eq!(stack.pop(), Some(val)));
|
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,
|
sess: &'a Session,
|
||||||
attrs: &'a [ast::Attribute],
|
attrs: &'a [A],
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
) -> impl Iterator<Item = &'a ast::Attribute> {
|
) -> impl Iterator<Item = &'a A> {
|
||||||
attrs.iter().filter(move |attr| {
|
attrs.iter().filter(move |attr| {
|
||||||
let attr = if let ast::AttrKind::Normal(ref normal) = attr.kind {
|
let Some(attr_segments) = attr.ident_path() else {
|
||||||
&normal.item
|
|
||||||
} else {
|
|
||||||
return false;
|
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
|
BUILTIN_ATTRIBUTES
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|&(builtin_name, ref deprecation_status)| {
|
.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)
|
Some(deprecation_status)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -85,14 +84,13 @@ pub fn get_attr<'a>(
|
||||||
})
|
})
|
||||||
.map_or_else(
|
.map_or_else(
|
||||||
|| {
|
|| {
|
||||||
sess.dcx()
|
sess.dcx().span_err(attr_segments[1].span, "usage of unknown attribute");
|
||||||
.span_err(attr_segments[1].ident.span, "usage of unknown attribute");
|
|
||||||
false
|
false
|
||||||
},
|
},
|
||||||
|deprecation_status| {
|
|deprecation_status| {
|
||||||
let mut diag = sess
|
let mut diag = sess
|
||||||
.dcx()
|
.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 {
|
match *deprecation_status {
|
||||||
DeprecationStatus::Deprecated => {
|
DeprecationStatus::Deprecated => {
|
||||||
diag.emit();
|
diag.emit();
|
||||||
|
@ -100,7 +98,7 @@ pub fn get_attr<'a>(
|
||||||
},
|
},
|
||||||
DeprecationStatus::Replaced(new_name) => {
|
DeprecationStatus::Replaced(new_name) => {
|
||||||
diag.span_suggestion(
|
diag.span_suggestion(
|
||||||
attr_segments[1].ident.span,
|
attr_segments[1].span,
|
||||||
"consider using",
|
"consider using",
|
||||||
new_name,
|
new_name,
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
|
@ -110,7 +108,7 @@ pub fn get_attr<'a>(
|
||||||
},
|
},
|
||||||
DeprecationStatus::None => {
|
DeprecationStatus::None => {
|
||||||
diag.cancel();
|
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) {
|
for attr in get_attr(sess, attrs, name) {
|
||||||
if let Some(ref value) = attr.value_str() {
|
if let Some(ref value) = attr.value_str() {
|
||||||
if let Ok(value) = FromStr::from_str(value.as_str()) {
|
if let Ok(value) = FromStr::from_str(value.as_str()) {
|
||||||
f(value);
|
f(value);
|
||||||
} else {
|
} else {
|
||||||
sess.dcx().span_err(attr.span, "not a number");
|
sess.dcx().span_err(attr.span(), "not a number");
|
||||||
}
|
}
|
||||||
} else {
|
} 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,
|
sess: &'a Session,
|
||||||
attrs: &'a [ast::Attribute],
|
attrs: &'a [A],
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
) -> Option<&'a ast::Attribute> {
|
) -> Option<&'a A> {
|
||||||
let mut unique_attr: Option<&ast::Attribute> = None;
|
let mut unique_attr: Option<&A> = None;
|
||||||
for attr in get_attr(sess, attrs, name) {
|
for attr in get_attr(sess, attrs, name) {
|
||||||
if let Some(duplicate) = unique_attr {
|
if let Some(duplicate) = unique_attr {
|
||||||
sess.dcx()
|
sess.dcx()
|
||||||
.struct_span_err(attr.span, format!("`{name}` is defined multiple times"))
|
.struct_span_err(attr.span(), format!("`{name}` is defined multiple times"))
|
||||||
.with_span_note(duplicate.span, "first definition found here")
|
.with_span_note(duplicate.span(), "first definition found here")
|
||||||
.emit();
|
.emit();
|
||||||
} else {
|
} else {
|
||||||
unique_attr = Some(attr);
|
unique_attr = Some(attr);
|
||||||
|
@ -156,16 +154,16 @@ pub fn get_unique_attr<'a>(
|
||||||
|
|
||||||
/// Returns true if the attributes contain any of `proc_macro`,
|
/// Returns true if the attributes contain any of `proc_macro`,
|
||||||
/// `proc_macro_derive` or `proc_macro_attribute`, false otherwise
|
/// `proc_macro_derive` or `proc_macro_attribute`, false otherwise
|
||||||
pub fn is_proc_macro(attrs: &[ast::Attribute]) -> bool {
|
pub fn is_proc_macro(attrs: &[impl AttributeExt]) -> bool {
|
||||||
attrs.iter().any(rustc_ast::Attribute::is_proc_macro_attr)
|
attrs.iter().any(AttributeExt::is_proc_macro_attr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the attributes contain `#[doc(hidden)]`
|
/// 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
|
attrs
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|attr| attr.has_name(sym::doc))
|
.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))
|
.any(|l| attr::list_contains_name(&l, sym::hidden))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -135,13 +135,24 @@ use rustc_middle::hir::nested_filter;
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! extract_msrv_attr {
|
macro_rules! extract_msrv_attr {
|
||||||
($context:ident) => {
|
(LateContext) => {
|
||||||
fn check_attributes(&mut self, cx: &rustc_lint::$context<'_>, attrs: &[rustc_ast::ast::Attribute]) {
|
fn check_attributes(&mut self, cx: &rustc_lint::LateContext<'_>, attrs: &[rustc_hir::Attribute]) {
|
||||||
let sess = rustc_lint::LintContext::sess(cx);
|
let sess = rustc_lint::LintContext::sess(cx);
|
||||||
self.msrv.check_attributes(sess, attrs);
|
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);
|
let sess = rustc_lint::LintContext::sess(cx);
|
||||||
self.msrv.check_attributes_post(sess, attrs);
|
self.msrv.check_attributes_post(sess, attrs);
|
||||||
}
|
}
|
||||||
|
@ -1912,7 +1923,7 @@ pub fn clip(tcx: TyCtxt<'_>, u: u128, ity: UintTy) -> u128 {
|
||||||
(u << amt) >> amt
|
(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))
|
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 {
|
pub fn is_no_std_crate(cx: &LateContext<'_>) -> bool {
|
||||||
cx.tcx.hir().attrs(hir::CRATE_HIR_ID).iter().any(|attr| {
|
cx.tcx.hir().attrs(hir::CRATE_HIR_ID).iter().any(|attr| {
|
||||||
if let ast::AttrKind::Normal(ref normal) = attr.kind {
|
attr.name_or_empty() == sym::no_std
|
||||||
normal.item.path == sym::no_std
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool {
|
pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool {
|
||||||
cx.tcx.hir().attrs(hir::CRATE_HIR_ID).iter().any(|attr| {
|
cx.tcx.hir().attrs(hir::CRATE_HIR_ID).iter().any(|attr| {
|
||||||
if let ast::AttrKind::Normal(ref normal) = attr.kind {
|
attr.name_or_empty() == sym::no_core
|
||||||
normal.item.path == sym::no_core
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustc_ast::Attribute;
|
use rustc_attr::AttributeExt;
|
||||||
use rustc_attr::parse_version;
|
use rustc_attr::parse_version;
|
||||||
use rustc_session::{RustcVersion, Session};
|
use rustc_session::{RustcVersion, Session};
|
||||||
use rustc_span::{Symbol, sym};
|
use rustc_span::{Symbol, sym};
|
||||||
|
@ -124,15 +124,15 @@ impl Msrv {
|
||||||
self.current().is_none_or(|msrv| msrv >= required)
|
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 sym_msrv = Symbol::intern("msrv");
|
||||||
let mut msrv_attrs = attrs.iter().filter(|attr| attr.path_matches(&[sym::clippy, sym_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(msrv_attr) = msrv_attrs.next() {
|
||||||
if let Some(duplicate) = msrv_attrs.last() {
|
if let Some(duplicate) = msrv_attrs.last() {
|
||||||
sess.dcx()
|
sess.dcx()
|
||||||
.struct_span_err(duplicate.span, "`clippy::msrv` is defined multiple times")
|
.struct_span_err(duplicate.span(), "`clippy::msrv` is defined multiple times")
|
||||||
.with_span_note(msrv_attr.span, "first definition found here")
|
.with_span_note(msrv_attr.span(), "first definition found here")
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,22 +142,22 @@ impl Msrv {
|
||||||
}
|
}
|
||||||
|
|
||||||
sess.dcx()
|
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 {
|
} else {
|
||||||
sess.dcx().span_err(msrv_attr.span, "bad clippy attribute");
|
sess.dcx().span_err(msrv_attr.span(), "bad clippy attribute");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
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) {
|
if let Some(version) = Self::parse_attr(sess, attrs) {
|
||||||
self.stack.push(version);
|
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() {
|
if Self::parse_attr(sess, attrs).is_some() {
|
||||||
self.stack.pop();
|
self.stack.pop();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,7 @@ extern crate std;
|
||||||
// issue#97006
|
// issue#97006
|
||||||
|
|
||||||
macro_rules! m { ($attr_path: path) => { #[$attr_path] fn f() {} } }
|
macro_rules! m { ($attr_path: path) => { #[$attr_path] fn f() {} } }
|
||||||
#[
|
#[inline]
|
||||||
|
|
||||||
inline]
|
|
||||||
fn f() { }
|
fn f() { }
|
||||||
|
|
||||||
fn main() { }
|
fn main() { }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue