Auto merge of #104861 - nnethercote:attr-cleanups, r=petrochenkov
Attribute cleanups Best reviewed one commit at a time. r? `@petrochenkov`
This commit is contained in:
commit
d6c4de0fb2
29 changed files with 231 additions and 307 deletions
|
@ -479,20 +479,10 @@ pub struct Crate {
|
||||||
pub is_placeholder: bool,
|
pub is_placeholder: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Possible values inside of compile-time attribute lists.
|
/// A semantic representation of a meta item. A meta item is a slightly
|
||||||
///
|
/// restricted form of an attribute -- it can only contain expressions in
|
||||||
/// E.g., the '..' in `#[name(..)]`.
|
/// certain leaf positions, rather than arbitrary token streams -- that is used
|
||||||
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
|
/// for most built-in attributes.
|
||||||
pub enum NestedMetaItem {
|
|
||||||
/// A full MetaItem, for recursive meta items.
|
|
||||||
MetaItem(MetaItem),
|
|
||||||
/// A literal.
|
|
||||||
///
|
|
||||||
/// E.g., `"foo"`, `64`, `true`.
|
|
||||||
Lit(MetaItemLit),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A spanned compile-time attribute item.
|
|
||||||
///
|
///
|
||||||
/// E.g., `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`.
|
/// E.g., `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`.
|
||||||
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
|
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||||
|
@ -502,25 +492,39 @@ pub struct MetaItem {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A compile-time attribute item.
|
/// The meta item kind, containing the data after the initial path.
|
||||||
///
|
|
||||||
/// E.g., `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`.
|
|
||||||
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
|
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||||
pub enum MetaItemKind {
|
pub enum MetaItemKind {
|
||||||
/// Word meta item.
|
/// Word meta item.
|
||||||
///
|
///
|
||||||
/// E.g., `test` as in `#[test]`.
|
/// E.g., `#[test]`, which lacks any arguments after `test`.
|
||||||
Word,
|
Word,
|
||||||
|
|
||||||
/// List meta item.
|
/// List meta item.
|
||||||
///
|
///
|
||||||
/// E.g., `derive(..)` as in `#[derive(..)]`.
|
/// E.g., `#[derive(..)]`, where the field represents the `..`.
|
||||||
List(Vec<NestedMetaItem>),
|
List(Vec<NestedMetaItem>),
|
||||||
|
|
||||||
/// Name value meta item.
|
/// Name value meta item.
|
||||||
///
|
///
|
||||||
/// E.g., `feature = "foo"` as in `#[feature = "foo"]`.
|
/// E.g., `#[feature = "foo"]`, where the field represents the `"foo"`.
|
||||||
NameValue(MetaItemLit),
|
NameValue(MetaItemLit),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Values inside meta item lists.
|
||||||
|
///
|
||||||
|
/// E.g., each of `Clone`, `Copy` in `#[derive(Clone, Copy)]`.
|
||||||
|
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||||
|
pub enum NestedMetaItem {
|
||||||
|
/// A full MetaItem, for recursive meta items.
|
||||||
|
MetaItem(MetaItem),
|
||||||
|
|
||||||
|
/// A literal.
|
||||||
|
///
|
||||||
|
/// E.g., `"foo"`, `64`, `true`.
|
||||||
|
Lit(MetaItemLit),
|
||||||
|
}
|
||||||
|
|
||||||
/// A block (`{ .. }`).
|
/// A block (`{ .. }`).
|
||||||
///
|
///
|
||||||
/// E.g., `{ .. }` as in `fn foo() { .. }`.
|
/// E.g., `{ .. }` as in `fn foo() { .. }`.
|
||||||
|
@ -2570,17 +2574,10 @@ impl<D: Decoder> Decodable<D> for AttrId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
|
|
||||||
pub struct AttrItem {
|
|
||||||
pub path: Path,
|
|
||||||
pub args: AttrArgs,
|
|
||||||
pub tokens: Option<LazyAttrTokenStream>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A list of attributes.
|
/// A list of attributes.
|
||||||
pub type AttrVec = ThinVec<Attribute>;
|
pub type AttrVec = ThinVec<Attribute>;
|
||||||
|
|
||||||
/// Metadata associated with an item.
|
/// A syntax-level representation of an attribute.
|
||||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||||
pub struct Attribute {
|
pub struct Attribute {
|
||||||
pub kind: AttrKind,
|
pub kind: AttrKind,
|
||||||
|
@ -2591,12 +2588,6 @@ pub struct Attribute {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
|
||||||
pub struct NormalAttr {
|
|
||||||
pub item: AttrItem,
|
|
||||||
pub tokens: Option<LazyAttrTokenStream>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||||
pub enum AttrKind {
|
pub enum AttrKind {
|
||||||
/// A normal attribute.
|
/// A normal attribute.
|
||||||
|
@ -2608,6 +2599,19 @@ pub enum AttrKind {
|
||||||
DocComment(CommentKind, Symbol),
|
DocComment(CommentKind, Symbol),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||||
|
pub struct NormalAttr {
|
||||||
|
pub item: AttrItem,
|
||||||
|
pub tokens: Option<LazyAttrTokenStream>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||||
|
pub struct AttrItem {
|
||||||
|
pub path: Path,
|
||||||
|
pub args: AttrArgs,
|
||||||
|
pub tokens: Option<LazyAttrTokenStream>,
|
||||||
|
}
|
||||||
|
|
||||||
/// `TraitRef`s appear in impls.
|
/// `TraitRef`s appear in impls.
|
||||||
///
|
///
|
||||||
/// Resolution maps each `TraitRef`'s `ref_id` to its defining trait; that's all
|
/// Resolution maps each `TraitRef`'s `ref_id` to its defining trait; that's all
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
//! Functions dealing with attributes and meta items.
|
//! Functions dealing with attributes and meta items.
|
||||||
|
|
||||||
use crate::ast;
|
use crate::ast;
|
||||||
use crate::ast::{AttrArgs, AttrArgsEq, AttrId, AttrItem, AttrKind, AttrStyle, Attribute};
|
use crate::ast::{AttrArgs, AttrArgsEq, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute};
|
||||||
use crate::ast::{DelimArgs, LitKind, MetaItemLit};
|
use crate::ast::{DelimArgs, Expr, ExprKind, LitKind, MetaItemLit};
|
||||||
use crate::ast::{MacDelimiter, MetaItem, MetaItemKind, NestedMetaItem};
|
use crate::ast::{MacDelimiter, MetaItem, MetaItemKind, NestedMetaItem, NormalAttr};
|
||||||
use crate::ast::{Path, PathSegment};
|
use crate::ast::{Path, PathSegment, StrStyle, DUMMY_NODE_ID};
|
||||||
use crate::ptr::P;
|
use crate::ptr::P;
|
||||||
use crate::token::{self, CommentKind, Delimiter, Token};
|
use crate::token::{self, CommentKind, Delimiter, Token};
|
||||||
use crate::tokenstream::{DelimSpan, Spacing, TokenTree};
|
use crate::tokenstream::{DelimSpan, Spacing, TokenTree};
|
||||||
|
@ -12,7 +12,6 @@ use crate::tokenstream::{LazyAttrTokenStream, TokenStream};
|
||||||
use crate::util::comments;
|
use crate::util::comments;
|
||||||
use rustc_data_structures::sync::WorkerLocal;
|
use rustc_data_structures::sync::WorkerLocal;
|
||||||
use rustc_index::bit_set::GrowableBitSet;
|
use rustc_index::bit_set::GrowableBitSet;
|
||||||
use rustc_span::source_map::BytePos;
|
|
||||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
@ -223,11 +222,7 @@ impl AttrItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn meta(&self, span: Span) -> Option<MetaItem> {
|
pub fn meta(&self, span: Span) -> Option<MetaItem> {
|
||||||
Some(MetaItem {
|
Some(MetaItem { path: self.path.clone(), kind: self.meta_kind()?, span })
|
||||||
path: self.path.clone(),
|
|
||||||
kind: MetaItemKind::from_attr_args(&self.args)?,
|
|
||||||
span,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn meta_kind(&self) -> Option<MetaItemKind> {
|
pub fn meta_kind(&self) -> Option<MetaItemKind> {
|
||||||
|
@ -329,26 +324,13 @@ impl Attribute {
|
||||||
/* Constructors */
|
/* Constructors */
|
||||||
|
|
||||||
pub fn mk_name_value_item_str(ident: Ident, str: Symbol, str_span: Span) -> MetaItem {
|
pub fn mk_name_value_item_str(ident: Ident, str: Symbol, str_span: Span) -> MetaItem {
|
||||||
let lit_kind = LitKind::Str(str, ast::StrStyle::Cooked);
|
mk_name_value_item(ident, LitKind::Str(str, ast::StrStyle::Cooked), str_span)
|
||||||
mk_name_value_item(ident, lit_kind, str_span)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mk_name_value_item(ident: Ident, lit_kind: LitKind, lit_span: Span) -> MetaItem {
|
pub fn mk_name_value_item(ident: Ident, kind: LitKind, lit_span: Span) -> MetaItem {
|
||||||
let lit = MetaItemLit::from_lit_kind(lit_kind, lit_span);
|
let lit = MetaItemLit { token_lit: kind.to_token_lit(), kind, span: lit_span };
|
||||||
let span = ident.span.to(lit_span);
|
let span = ident.span.to(lit_span);
|
||||||
MetaItem { path: Path::from_ident(ident), span, kind: MetaItemKind::NameValue(lit) }
|
MetaItem { path: Path::from_ident(ident), kind: MetaItemKind::NameValue(lit), span }
|
||||||
}
|
|
||||||
|
|
||||||
pub fn mk_list_item(ident: Ident, items: Vec<NestedMetaItem>) -> MetaItem {
|
|
||||||
MetaItem { path: Path::from_ident(ident), span: ident.span, kind: MetaItemKind::List(items) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn mk_word_item(ident: Ident) -> MetaItem {
|
|
||||||
MetaItem { path: Path::from_ident(ident), span: ident.span, kind: MetaItemKind::Word }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem {
|
|
||||||
NestedMetaItem::MetaItem(mk_word_item(ident))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AttrIdGenerator(WorkerLocal<Cell<u32>>);
|
pub struct AttrIdGenerator(WorkerLocal<Cell<u32>>);
|
||||||
|
@ -406,21 +388,58 @@ pub fn mk_attr_from_item(
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Attribute {
|
) -> Attribute {
|
||||||
Attribute {
|
Attribute {
|
||||||
kind: AttrKind::Normal(P(ast::NormalAttr { item, tokens })),
|
kind: AttrKind::Normal(P(NormalAttr { item, tokens })),
|
||||||
id: g.mk_attr_id(),
|
id: g.mk_attr_id(),
|
||||||
style,
|
style,
|
||||||
span,
|
span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an inner attribute with the given value and span.
|
pub fn mk_attr_word(g: &AttrIdGenerator, style: AttrStyle, name: Symbol, span: Span) -> Attribute {
|
||||||
pub fn mk_attr_inner(g: &AttrIdGenerator, item: MetaItem) -> Attribute {
|
let path = Path::from_ident(Ident::new(name, span));
|
||||||
mk_attr(g, AttrStyle::Inner, item.path, item.kind.attr_args(item.span), item.span)
|
let args = AttrArgs::Empty;
|
||||||
|
mk_attr(g, style, path, args, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an outer attribute with the given value and span.
|
pub fn mk_attr_name_value_str(
|
||||||
pub fn mk_attr_outer(g: &AttrIdGenerator, item: MetaItem) -> Attribute {
|
g: &AttrIdGenerator,
|
||||||
mk_attr(g, AttrStyle::Outer, item.path, item.kind.attr_args(item.span), item.span)
|
style: AttrStyle,
|
||||||
|
name: Symbol,
|
||||||
|
val: Symbol,
|
||||||
|
span: Span,
|
||||||
|
) -> Attribute {
|
||||||
|
let lit = LitKind::Str(val, StrStyle::Cooked).to_token_lit();
|
||||||
|
let expr = P(Expr {
|
||||||
|
id: DUMMY_NODE_ID,
|
||||||
|
kind: ExprKind::Lit(lit),
|
||||||
|
span,
|
||||||
|
attrs: AttrVec::new(),
|
||||||
|
tokens: None,
|
||||||
|
});
|
||||||
|
let path = Path::from_ident(Ident::new(name, span));
|
||||||
|
let args = AttrArgs::Eq(span, AttrArgsEq::Ast(expr));
|
||||||
|
mk_attr(g, style, path, args, span)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mk_attr_nested_word(
|
||||||
|
g: &AttrIdGenerator,
|
||||||
|
style: AttrStyle,
|
||||||
|
outer: Symbol,
|
||||||
|
inner: Symbol,
|
||||||
|
span: Span,
|
||||||
|
) -> Attribute {
|
||||||
|
let inner_tokens = TokenStream::new(vec![TokenTree::Token(
|
||||||
|
Token::from_ast_ident(Ident::new(inner, span)),
|
||||||
|
Spacing::Alone,
|
||||||
|
)]);
|
||||||
|
let outer_ident = Ident::new(outer, span);
|
||||||
|
let path = Path::from_ident(outer_ident);
|
||||||
|
let attr_args = AttrArgs::Delimited(DelimArgs {
|
||||||
|
dspan: DelimSpan::from_single(span),
|
||||||
|
delim: MacDelimiter::Parenthesis,
|
||||||
|
tokens: inner_tokens,
|
||||||
|
});
|
||||||
|
mk_attr(g, style, path, attr_args, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mk_doc_comment(
|
pub fn mk_doc_comment(
|
||||||
|
@ -438,23 +457,6 @@ pub fn list_contains_name(items: &[NestedMetaItem], name: Symbol) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MetaItem {
|
impl MetaItem {
|
||||||
fn token_trees(&self) -> Vec<TokenTree> {
|
|
||||||
let mut idents = vec![];
|
|
||||||
let mut last_pos = BytePos(0_u32);
|
|
||||||
for (i, segment) in self.path.segments.iter().enumerate() {
|
|
||||||
let is_first = i == 0;
|
|
||||||
if !is_first {
|
|
||||||
let mod_sep_span =
|
|
||||||
Span::new(last_pos, segment.ident.span.lo(), segment.ident.span.ctxt(), None);
|
|
||||||
idents.push(TokenTree::token_alone(token::ModSep, mod_sep_span));
|
|
||||||
}
|
|
||||||
idents.push(TokenTree::Token(Token::from_ast_ident(segment.ident), Spacing::Alone));
|
|
||||||
last_pos = segment.ident.span.hi();
|
|
||||||
}
|
|
||||||
idents.extend(self.kind.token_trees(self.span));
|
|
||||||
idents
|
|
||||||
}
|
|
||||||
|
|
||||||
fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItem>
|
fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItem>
|
||||||
where
|
where
|
||||||
I: Iterator<Item = TokenTree>,
|
I: Iterator<Item = TokenTree>,
|
||||||
|
@ -526,62 +528,6 @@ impl MetaItemKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn attr_args(&self, span: Span) -> AttrArgs {
|
|
||||||
match self {
|
|
||||||
MetaItemKind::Word => AttrArgs::Empty,
|
|
||||||
MetaItemKind::NameValue(lit) => {
|
|
||||||
let expr = P(ast::Expr {
|
|
||||||
id: ast::DUMMY_NODE_ID,
|
|
||||||
kind: ast::ExprKind::Lit(lit.token_lit.clone()),
|
|
||||||
span: lit.span,
|
|
||||||
attrs: ast::AttrVec::new(),
|
|
||||||
tokens: None,
|
|
||||||
});
|
|
||||||
AttrArgs::Eq(span, AttrArgsEq::Ast(expr))
|
|
||||||
}
|
|
||||||
MetaItemKind::List(list) => {
|
|
||||||
let mut tts = Vec::new();
|
|
||||||
for (i, item) in list.iter().enumerate() {
|
|
||||||
if i > 0 {
|
|
||||||
tts.push(TokenTree::token_alone(token::Comma, span));
|
|
||||||
}
|
|
||||||
tts.extend(item.token_trees())
|
|
||||||
}
|
|
||||||
AttrArgs::Delimited(DelimArgs {
|
|
||||||
dspan: DelimSpan::from_single(span),
|
|
||||||
delim: MacDelimiter::Parenthesis,
|
|
||||||
tokens: TokenStream::new(tts),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn token_trees(&self, span: Span) -> Vec<TokenTree> {
|
|
||||||
match self {
|
|
||||||
MetaItemKind::Word => vec![],
|
|
||||||
MetaItemKind::NameValue(lit) => {
|
|
||||||
vec![
|
|
||||||
TokenTree::token_alone(token::Eq, span),
|
|
||||||
TokenTree::Token(lit.to_token(), Spacing::Alone),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
MetaItemKind::List(list) => {
|
|
||||||
let mut tokens = Vec::new();
|
|
||||||
for (i, item) in list.iter().enumerate() {
|
|
||||||
if i > 0 {
|
|
||||||
tokens.push(TokenTree::token_alone(token::Comma, span));
|
|
||||||
}
|
|
||||||
tokens.extend(item.token_trees())
|
|
||||||
}
|
|
||||||
vec![TokenTree::Delimited(
|
|
||||||
DelimSpan::from_single(span),
|
|
||||||
Delimiter::Parenthesis,
|
|
||||||
TokenStream::new(tokens),
|
|
||||||
)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn list_from_tokens(tokens: TokenStream) -> Option<MetaItemKind> {
|
fn list_from_tokens(tokens: TokenStream) -> Option<MetaItemKind> {
|
||||||
let mut tokens = tokens.into_trees().peekable();
|
let mut tokens = tokens.into_trees().peekable();
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
|
@ -620,7 +566,7 @@ impl MetaItemKind {
|
||||||
}) => MetaItemKind::list_from_tokens(tokens.clone()),
|
}) => MetaItemKind::list_from_tokens(tokens.clone()),
|
||||||
AttrArgs::Delimited(..) => None,
|
AttrArgs::Delimited(..) => None,
|
||||||
AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => match expr.kind {
|
AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => match expr.kind {
|
||||||
ast::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)
|
||||||
.ok()
|
.ok()
|
||||||
|
@ -659,15 +605,6 @@ impl NestedMetaItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn token_trees(&self) -> Vec<TokenTree> {
|
|
||||||
match self {
|
|
||||||
NestedMetaItem::MetaItem(item) => item.token_trees(),
|
|
||||||
NestedMetaItem::Lit(lit) => {
|
|
||||||
vec![TokenTree::Token(lit.to_token(), Spacing::Alone)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<NestedMetaItem>
|
fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<NestedMetaItem>
|
||||||
where
|
where
|
||||||
I: Iterator<Item = TokenTree>,
|
I: Iterator<Item = TokenTree>,
|
||||||
|
|
|
@ -206,22 +206,6 @@ impl MetaItemLit {
|
||||||
token::Lit::from_token(token)
|
token::Lit::from_token(token)
|
||||||
.and_then(|token_lit| MetaItemLit::from_token_lit(token_lit, token.span).ok())
|
.and_then(|token_lit| MetaItemLit::from_token_lit(token_lit, token.span).ok())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to create a meta item literal from a `LitKind`.
|
|
||||||
/// This function is used when the original token doesn't exist (e.g. the literal is created
|
|
||||||
/// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing).
|
|
||||||
pub fn from_lit_kind(kind: LitKind, span: Span) -> MetaItemLit {
|
|
||||||
MetaItemLit { token_lit: kind.to_token_lit(), kind, span }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Losslessly convert a meta item literal into a token.
|
|
||||||
pub fn to_token(&self) -> Token {
|
|
||||||
let kind = match self.token_lit.kind {
|
|
||||||
token::Bool => token::Ident(self.token_lit.symbol, false),
|
|
||||||
_ => token::Literal(self.token_lit),
|
|
||||||
};
|
|
||||||
Token::new(kind, self.span)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn strip_underscores(symbol: Symbol) -> Symbol {
|
fn strip_underscores(symbol: Symbol) -> Symbol {
|
||||||
|
|
|
@ -1606,16 +1606,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// `#[allow(unreachable_code)]`
|
// `#[allow(unreachable_code)]`
|
||||||
let attr = {
|
let attr = attr::mk_attr_nested_word(
|
||||||
// `allow(unreachable_code)`
|
&self.tcx.sess.parse_sess.attr_id_generator,
|
||||||
let allow = {
|
AttrStyle::Outer,
|
||||||
let allow_ident = Ident::new(sym::allow, self.lower_span(span));
|
sym::allow,
|
||||||
let uc_ident = Ident::new(sym::unreachable_code, self.lower_span(span));
|
sym::unreachable_code,
|
||||||
let uc_nested = attr::mk_nested_word_item(uc_ident);
|
self.lower_span(span),
|
||||||
attr::mk_list_item(allow_ident, vec![uc_nested])
|
);
|
||||||
};
|
|
||||||
attr::mk_attr_outer(&self.tcx.sess.parse_sess.attr_id_generator, allow)
|
|
||||||
};
|
|
||||||
let attrs: AttrVec = thin_vec![attr];
|
let attrs: AttrVec = thin_vec![attr];
|
||||||
|
|
||||||
// `ControlFlow::Continue(val) => #[allow(unreachable_code)] val,`
|
// `ControlFlow::Continue(val) => #[allow(unreachable_code)] val,`
|
||||||
|
|
|
@ -912,7 +912,7 @@ fn validate_generic_param_order(
|
||||||
|
|
||||||
impl<'a> Visitor<'a> for AstValidator<'a> {
|
impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
fn visit_attribute(&mut self, attr: &Attribute) {
|
fn visit_attribute(&mut self, attr: &Attribute) {
|
||||||
validate_attr::check_meta(&self.session.parse_sess, attr);
|
validate_attr::check_attr(&self.session.parse_sess, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_expr(&mut self, expr: &'a Expr) {
|
fn visit_expr(&mut self, expr: &'a Expr) {
|
||||||
|
|
|
@ -19,7 +19,7 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
||||||
use rustc_span::edition::Edition;
|
use rustc_span::edition::Edition;
|
||||||
use rustc_span::source_map::{SourceMap, Spanned};
|
use rustc_span::source_map::{SourceMap, Spanned};
|
||||||
use rustc_span::symbol::{kw, sym, Ident, IdentPrinter, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, IdentPrinter, Symbol};
|
||||||
use rustc_span::{BytePos, FileName, Span};
|
use rustc_span::{BytePos, FileName, Span, DUMMY_SP};
|
||||||
|
|
||||||
use rustc_ast::attr::AttrIdGenerator;
|
use rustc_ast::attr::AttrIdGenerator;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
@ -120,17 +120,20 @@ pub fn print_crate<'a>(
|
||||||
// of the feature gate, so we fake them up here.
|
// of the feature gate, so we fake them up here.
|
||||||
|
|
||||||
// `#![feature(prelude_import)]`
|
// `#![feature(prelude_import)]`
|
||||||
let pi_nested = attr::mk_nested_word_item(Ident::with_dummy_span(sym::prelude_import));
|
let fake_attr = attr::mk_attr_nested_word(
|
||||||
let list = attr::mk_list_item(Ident::with_dummy_span(sym::feature), vec![pi_nested]);
|
g,
|
||||||
let fake_attr = attr::mk_attr_inner(g, list);
|
ast::AttrStyle::Inner,
|
||||||
|
sym::feature,
|
||||||
|
sym::prelude_import,
|
||||||
|
DUMMY_SP,
|
||||||
|
);
|
||||||
s.print_attribute(&fake_attr);
|
s.print_attribute(&fake_attr);
|
||||||
|
|
||||||
// Currently, in Rust 2018 we don't have `extern crate std;` at the crate
|
// Currently, in Rust 2018 we don't have `extern crate std;` at the crate
|
||||||
// root, so this is not needed, and actually breaks things.
|
// root, so this is not needed, and actually breaks things.
|
||||||
if edition == Edition::Edition2015 {
|
if edition == Edition::Edition2015 {
|
||||||
// `#![no_std]`
|
// `#![no_std]`
|
||||||
let no_std_meta = attr::mk_word_item(Ident::with_dummy_span(sym::no_std));
|
let fake_attr = attr::mk_attr_word(g, ast::AttrStyle::Inner, sym::no_std, DUMMY_SP);
|
||||||
let fake_attr = attr::mk_attr_inner(g, no_std_meta);
|
|
||||||
s.print_attribute(&fake_attr);
|
s.print_attribute(&fake_attr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1713,9 +1716,9 @@ impl<'a> State<'a> {
|
||||||
where_clause: ast::WhereClause {
|
where_clause: ast::WhereClause {
|
||||||
has_where_token: false,
|
has_where_token: false,
|
||||||
predicates: Vec::new(),
|
predicates: Vec::new(),
|
||||||
span: rustc_span::DUMMY_SP,
|
span: DUMMY_SP,
|
||||||
},
|
},
|
||||||
span: rustc_span::DUMMY_SP,
|
span: DUMMY_SP,
|
||||||
};
|
};
|
||||||
let header = ast::FnHeader { unsafety, ext, ..ast::FnHeader::default() };
|
let header = ast::FnHeader { unsafety, ext, ..ast::FnHeader::default() };
|
||||||
self.print_fn(decl, header, name, &generics);
|
self.print_fn(decl, header, name, &generics);
|
||||||
|
|
|
@ -95,9 +95,7 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span
|
||||||
body,
|
body,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let special = sym::rustc_std_internal_symbol;
|
let attrs = thin_vec![cx.attr_word(sym::rustc_std_internal_symbol, span)];
|
||||||
let special = cx.meta_word(span, special);
|
|
||||||
let attrs = thin_vec![cx.attribute(special)];
|
|
||||||
|
|
||||||
let item = cx.item(span, Ident::from_str_and_span("__rg_oom", span), attrs, kind);
|
let item = cx.item(span, Ident::from_str_and_span("__rg_oom", span), attrs, kind);
|
||||||
cx.stmt_item(sig_span, item)
|
cx.stmt_item(sig_span, item)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use rustc_ast::{
|
use rustc_ast::{
|
||||||
attr,
|
|
||||||
ptr::P,
|
ptr::P,
|
||||||
token,
|
token,
|
||||||
tokenstream::{DelimSpan, TokenStream, TokenTree},
|
tokenstream::{DelimSpan, TokenStream, TokenTree},
|
||||||
|
@ -118,10 +117,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
||||||
self.cx.item(
|
self.cx.item(
|
||||||
self.span,
|
self.span,
|
||||||
Ident::empty(),
|
Ident::empty(),
|
||||||
thin_vec![self.cx.attribute(attr::mk_list_item(
|
thin_vec![self.cx.attr_nested_word(sym::allow, sym::unused_imports, self.span)],
|
||||||
Ident::new(sym::allow, self.span),
|
|
||||||
vec![attr::mk_nested_word_item(Ident::new(sym::unused_imports, self.span))],
|
|
||||||
))],
|
|
||||||
ItemKind::Use(UseTree {
|
ItemKind::Use(UseTree {
|
||||||
prefix: self.cx.path(self.span, self.cx.std_path(&[sym::asserting])),
|
prefix: self.cx.path(self.span, self.cx.std_path(&[sym::asserting])),
|
||||||
kind: UseTreeKind::Nested(vec![
|
kind: UseTreeKind::Nested(vec![
|
||||||
|
|
|
@ -37,10 +37,10 @@ impl MultiItemModifier for Expander {
|
||||||
_is_derive_const: bool,
|
_is_derive_const: bool,
|
||||||
) -> ExpandResult<Vec<Annotatable>, Annotatable> {
|
) -> ExpandResult<Vec<Annotatable>, Annotatable> {
|
||||||
let template = AttributeTemplate { list: Some("path"), ..Default::default() };
|
let template = AttributeTemplate { list: Some("path"), ..Default::default() };
|
||||||
let attr = &ecx.attribute(meta_item.clone());
|
validate_attr::check_builtin_meta_item(
|
||||||
validate_attr::check_builtin_attribute(
|
|
||||||
&ecx.sess.parse_sess,
|
&ecx.sess.parse_sess,
|
||||||
attr,
|
&meta_item,
|
||||||
|
ast::AttrStyle::Outer,
|
||||||
sym::cfg_accessible,
|
sym::cfg_accessible,
|
||||||
template,
|
template,
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::cfg_eval::cfg_eval;
|
use crate::cfg_eval::cfg_eval;
|
||||||
|
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_ast::{attr, token, GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
|
use rustc_ast::{token, GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
|
||||||
use rustc_errors::{struct_span_err, Applicability};
|
use rustc_errors::{struct_span_err, Applicability};
|
||||||
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier};
|
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier};
|
||||||
use rustc_feature::AttributeTemplate;
|
use rustc_feature::AttributeTemplate;
|
||||||
|
@ -33,34 +33,36 @@ impl MultiItemModifier for Expander {
|
||||||
ecx.resolver.resolve_derives(ecx.current_expansion.id, ecx.force_mode, &|| {
|
ecx.resolver.resolve_derives(ecx.current_expansion.id, ecx.force_mode, &|| {
|
||||||
let template =
|
let template =
|
||||||
AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() };
|
AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() };
|
||||||
let attr =
|
validate_attr::check_builtin_meta_item(
|
||||||
attr::mk_attr_outer(&sess.parse_sess.attr_id_generator, meta_item.clone());
|
|
||||||
validate_attr::check_builtin_attribute(
|
|
||||||
&sess.parse_sess,
|
&sess.parse_sess,
|
||||||
&attr,
|
&meta_item,
|
||||||
|
ast::AttrStyle::Outer,
|
||||||
sym::derive,
|
sym::derive,
|
||||||
template,
|
template,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut resolutions: Vec<_> = attr
|
let mut resolutions = match &meta_item.kind {
|
||||||
.meta_item_list()
|
MetaItemKind::List(list) => {
|
||||||
.unwrap_or_default()
|
list.iter()
|
||||||
.into_iter()
|
.filter_map(|nested_meta| match nested_meta {
|
||||||
.filter_map(|nested_meta| match nested_meta {
|
NestedMetaItem::MetaItem(meta) => Some(meta),
|
||||||
NestedMetaItem::MetaItem(meta) => Some(meta),
|
NestedMetaItem::Lit(lit) => {
|
||||||
NestedMetaItem::Lit(lit) => {
|
// Reject `#[derive("Debug")]`.
|
||||||
// Reject `#[derive("Debug")]`.
|
report_unexpected_meta_item_lit(sess, &lit);
|
||||||
report_unexpected_meta_item_lit(sess, &lit);
|
None
|
||||||
None
|
}
|
||||||
}
|
})
|
||||||
})
|
.map(|meta| {
|
||||||
.map(|meta| {
|
// Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the
|
||||||
// Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the paths.
|
// paths.
|
||||||
report_path_args(sess, &meta);
|
report_path_args(sess, &meta);
|
||||||
meta.path
|
meta.path.clone()
|
||||||
})
|
})
|
||||||
.map(|path| (path, dummy_annotatable(), None, self.0))
|
.map(|path| (path, dummy_annotatable(), None, self.0))
|
||||||
.collect();
|
.collect()
|
||||||
|
}
|
||||||
|
_ => vec![],
|
||||||
|
};
|
||||||
|
|
||||||
// Do not configure or clone items unless necessary.
|
// Do not configure or clone items unless necessary.
|
||||||
match &mut resolutions[..] {
|
match &mut resolutions[..] {
|
||||||
|
|
|
@ -68,8 +68,7 @@ pub fn expand_deriving_clone(
|
||||||
_ => cx.span_bug(span, "`#[derive(Clone)]` on trait item or impl item"),
|
_ => cx.span_bug(span, "`#[derive(Clone)]` on trait item or impl item"),
|
||||||
}
|
}
|
||||||
|
|
||||||
let inline = cx.meta_word(span, sym::inline);
|
let attrs = thin_vec![cx.attr_word(sym::inline, span)];
|
||||||
let attrs = thin_vec![cx.attribute(inline)];
|
|
||||||
let trait_def = TraitDef {
|
let trait_def = TraitDef {
|
||||||
span,
|
span,
|
||||||
path: path_std!(clone::Clone),
|
path: path_std!(clone::Clone),
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::deriving::path_std;
|
||||||
use rustc_ast::{self as ast, MetaItem};
|
use rustc_ast::{self as ast, MetaItem};
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||||
use rustc_span::symbol::{sym, Ident};
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use thin_vec::thin_vec;
|
use thin_vec::thin_vec;
|
||||||
|
|
||||||
|
@ -18,11 +18,11 @@ pub fn expand_deriving_eq(
|
||||||
is_const: bool,
|
is_const: bool,
|
||||||
) {
|
) {
|
||||||
let span = cx.with_def_site_ctxt(span);
|
let span = cx.with_def_site_ctxt(span);
|
||||||
let inline = cx.meta_word(span, sym::inline);
|
let attrs = thin_vec![
|
||||||
let hidden = rustc_ast::attr::mk_nested_word_item(Ident::new(sym::hidden, span));
|
cx.attr_word(sym::inline, span),
|
||||||
let doc = rustc_ast::attr::mk_list_item(Ident::new(sym::doc, span), vec![hidden]);
|
cx.attr_nested_word(sym::doc, sym::hidden, span),
|
||||||
let no_coverage = cx.meta_word(span, sym::no_coverage);
|
cx.attr_word(sym::no_coverage, span)
|
||||||
let attrs = thin_vec![cx.attribute(inline), cx.attribute(doc), cx.attribute(no_coverage)];
|
];
|
||||||
let trait_def = TraitDef {
|
let trait_def = TraitDef {
|
||||||
span,
|
span,
|
||||||
path: path_std!(cmp::Eq),
|
path: path_std!(cmp::Eq),
|
||||||
|
|
|
@ -15,8 +15,7 @@ pub fn expand_deriving_ord(
|
||||||
push: &mut dyn FnMut(Annotatable),
|
push: &mut dyn FnMut(Annotatable),
|
||||||
is_const: bool,
|
is_const: bool,
|
||||||
) {
|
) {
|
||||||
let inline = cx.meta_word(span, sym::inline);
|
let attrs = thin_vec![cx.attr_word(sym::inline, span)];
|
||||||
let attrs = thin_vec![cx.attribute(inline)];
|
|
||||||
let trait_def = TraitDef {
|
let trait_def = TraitDef {
|
||||||
span,
|
span,
|
||||||
path: path_std!(cmp::Ord),
|
path: path_std!(cmp::Ord),
|
||||||
|
|
|
@ -68,8 +68,7 @@ pub fn expand_deriving_partial_eq(
|
||||||
|
|
||||||
// No need to generate `ne`, the default suffices, and not generating it is
|
// No need to generate `ne`, the default suffices, and not generating it is
|
||||||
// faster.
|
// faster.
|
||||||
let inline = cx.meta_word(span, sym::inline);
|
let attrs = thin_vec![cx.attr_word(sym::inline, span)];
|
||||||
let attrs = thin_vec![cx.attribute(inline)];
|
|
||||||
let methods = vec![MethodDef {
|
let methods = vec![MethodDef {
|
||||||
name: sym::eq,
|
name: sym::eq,
|
||||||
generics: Bounds::empty(),
|
generics: Bounds::empty(),
|
||||||
|
|
|
@ -19,8 +19,7 @@ pub fn expand_deriving_partial_ord(
|
||||||
let ret_ty =
|
let ret_ty =
|
||||||
Path(Path::new_(pathvec_std!(option::Option), vec![Box::new(ordering_ty)], PathKind::Std));
|
Path(Path::new_(pathvec_std!(option::Option), vec![Box::new(ordering_ty)], PathKind::Std));
|
||||||
|
|
||||||
let inline = cx.meta_word(span, sym::inline);
|
let attrs = thin_vec![cx.attr_word(sym::inline, span)];
|
||||||
let attrs = thin_vec![cx.attribute(inline)];
|
|
||||||
|
|
||||||
let partial_cmp_def = MethodDef {
|
let partial_cmp_def = MethodDef {
|
||||||
name: sym::partial_cmp,
|
name: sym::partial_cmp,
|
||||||
|
|
|
@ -20,8 +20,7 @@ pub fn expand_deriving_default(
|
||||||
) {
|
) {
|
||||||
item.visit_with(&mut DetectNonVariantDefaultAttr { cx });
|
item.visit_with(&mut DetectNonVariantDefaultAttr { cx });
|
||||||
|
|
||||||
let inline = cx.meta_word(span, sym::inline);
|
let attrs = thin_vec![cx.attr_word(sym::inline, span)];
|
||||||
let attrs = thin_vec![cx.attribute(inline)];
|
|
||||||
let trait_def = TraitDef {
|
let trait_def = TraitDef {
|
||||||
span,
|
span,
|
||||||
path: Path::new(vec![kw::Default, sym::Default]),
|
path: Path::new(vec![kw::Default, sym::Default]),
|
||||||
|
|
|
@ -718,7 +718,7 @@ impl<'a> TraitDef<'a> {
|
||||||
let path = cx.path_all(self.span, false, vec![type_ident], self_params);
|
let path = cx.path_all(self.span, false, vec![type_ident], self_params);
|
||||||
let self_type = cx.ty_path(path);
|
let self_type = cx.ty_path(path);
|
||||||
|
|
||||||
let attr = cx.attribute(cx.meta_word(self.span, sym::automatically_derived));
|
let attr = cx.attr_word(sym::automatically_derived, self.span);
|
||||||
let attrs = thin_vec![attr];
|
let attrs = thin_vec![attr];
|
||||||
let opt_trait_ref = Some(trait_ref);
|
let opt_trait_ref = Some(trait_ref);
|
||||||
|
|
||||||
|
|
|
@ -188,7 +188,7 @@ fn inject_impl_of_structural_trait(
|
||||||
.cloned(),
|
.cloned(),
|
||||||
);
|
);
|
||||||
// Mark as `automatically_derived` to avoid some silly lints.
|
// Mark as `automatically_derived` to avoid some silly lints.
|
||||||
attrs.push(cx.attribute(cx.meta_word(span, sym::automatically_derived)));
|
attrs.push(cx.attr_word(sym::automatically_derived, span));
|
||||||
|
|
||||||
let newitem = cx.item(
|
let newitem = cx.item(
|
||||||
span,
|
span,
|
||||||
|
|
|
@ -115,9 +115,7 @@ impl AllocFnFactory<'_, '_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn attrs(&self) -> AttrVec {
|
fn attrs(&self) -> AttrVec {
|
||||||
let special = sym::rustc_std_internal_symbol;
|
thin_vec![self.cx.attr_word(sym::rustc_std_internal_symbol, self.span)]
|
||||||
let special = self.cx.meta_word(self.span, special);
|
|
||||||
thin_vec![self.cx.attribute(special)]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn arg_ty(
|
fn arg_ty(
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
use std::mem;
|
|
||||||
|
|
||||||
use rustc_ast::attr;
|
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::visit::{self, Visitor};
|
use rustc_ast::visit::{self, Visitor};
|
||||||
use rustc_ast::{self as ast, NodeId};
|
use rustc_ast::{self as ast, NodeId};
|
||||||
|
@ -13,6 +10,7 @@ use rustc_span::source_map::SourceMap;
|
||||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||||
use rustc_span::{Span, DUMMY_SP};
|
use rustc_span::{Span, DUMMY_SP};
|
||||||
use smallvec::smallvec;
|
use smallvec::smallvec;
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
struct ProcMacroDerive {
|
struct ProcMacroDerive {
|
||||||
id: NodeId,
|
id: NodeId,
|
||||||
|
@ -365,14 +363,8 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> {
|
||||||
cx.expr_array_ref(span, decls),
|
cx.expr_array_ref(span, decls),
|
||||||
)
|
)
|
||||||
.map(|mut i| {
|
.map(|mut i| {
|
||||||
let attr = cx.meta_word(span, sym::rustc_proc_macro_decls);
|
i.attrs.push(cx.attr_word(sym::rustc_proc_macro_decls, span));
|
||||||
i.attrs.push(cx.attribute(attr));
|
i.attrs.push(cx.attr_nested_word(sym::allow, sym::deprecated, span));
|
||||||
|
|
||||||
let deprecated_attr = attr::mk_nested_word_item(Ident::new(sym::deprecated, span));
|
|
||||||
let allow_deprecated_attr =
|
|
||||||
attr::mk_list_item(Ident::new(sym::allow, span), vec![deprecated_attr]);
|
|
||||||
i.attrs.push(cx.attribute(allow_deprecated_attr));
|
|
||||||
|
|
||||||
i
|
i
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ pub fn inject(
|
||||||
cx.item(
|
cx.item(
|
||||||
span,
|
span,
|
||||||
ident,
|
ident,
|
||||||
thin_vec![cx.attribute(cx.meta_word(span, sym::macro_use))],
|
thin_vec![cx.attr_word(sym::macro_use, span)],
|
||||||
ast::ItemKind::ExternCrate(None),
|
ast::ItemKind::ExternCrate(None),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -79,7 +79,7 @@ pub fn inject(
|
||||||
let use_item = cx.item(
|
let use_item = cx.item(
|
||||||
span,
|
span,
|
||||||
Ident::empty(),
|
Ident::empty(),
|
||||||
thin_vec![cx.attribute(cx.meta_word(span, sym::prelude_import))],
|
thin_vec![cx.attr_word(sym::prelude_import, span)],
|
||||||
ast::ItemKind::Use(ast::UseTree {
|
ast::ItemKind::Use(ast::UseTree {
|
||||||
prefix: cx.path(span, import_path),
|
prefix: cx.path(span, import_path),
|
||||||
kind: ast::UseTreeKind::Glob,
|
kind: ast::UseTreeKind::Glob,
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
/// Ideally, this code would be in libtest but for efficiency and error messages it lives here.
|
/// Ideally, this code would be in libtest but for efficiency and error messages it lives here.
|
||||||
use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute};
|
use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute};
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_ast::attr;
|
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
|
@ -47,11 +46,7 @@ pub fn expand_test_case(
|
||||||
tokens: None,
|
tokens: None,
|
||||||
};
|
};
|
||||||
item.ident.span = item.ident.span.with_ctxt(sp.ctxt());
|
item.ident.span = item.ident.span.with_ctxt(sp.ctxt());
|
||||||
item.attrs.push(ecx.attribute(attr::mk_name_value_item_str(
|
item.attrs.push(ecx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, sp));
|
||||||
Ident::new(sym::rustc_test_marker, sp),
|
|
||||||
test_path_symbol,
|
|
||||||
sp,
|
|
||||||
)));
|
|
||||||
item
|
item
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -241,16 +236,9 @@ pub fn expand_test_or_bench(
|
||||||
Ident::new(item.ident.name, sp),
|
Ident::new(item.ident.name, sp),
|
||||||
thin_vec![
|
thin_vec![
|
||||||
// #[cfg(test)]
|
// #[cfg(test)]
|
||||||
cx.attribute(attr::mk_list_item(
|
cx.attr_nested_word(sym::cfg, sym::test, attr_sp),
|
||||||
Ident::new(sym::cfg, attr_sp),
|
|
||||||
vec![attr::mk_nested_word_item(Ident::new(sym::test, attr_sp))],
|
|
||||||
)),
|
|
||||||
// #[rustc_test_marker = "test_case_sort_key"]
|
// #[rustc_test_marker = "test_case_sort_key"]
|
||||||
cx.attribute(attr::mk_name_value_item_str(
|
cx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, attr_sp),
|
||||||
Ident::new(sym::rustc_test_marker, attr_sp),
|
|
||||||
test_path_symbol,
|
|
||||||
attr_sp,
|
|
||||||
)),
|
|
||||||
]
|
]
|
||||||
.into(),
|
.into(),
|
||||||
// const $ident: test::TestDescAndFn =
|
// const $ident: test::TestDescAndFn =
|
||||||
|
|
|
@ -185,13 +185,12 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> {
|
||||||
let item = match entry_point_type(self.sess, &item, self.depth) {
|
let item = match entry_point_type(self.sess, &item, self.depth) {
|
||||||
EntryPointType::MainNamed | EntryPointType::RustcMainAttr | EntryPointType::Start => {
|
EntryPointType::MainNamed | EntryPointType::RustcMainAttr | EntryPointType::Start => {
|
||||||
item.map(|ast::Item { id, ident, attrs, kind, vis, span, tokens }| {
|
item.map(|ast::Item { id, ident, attrs, kind, vis, span, tokens }| {
|
||||||
let allow_ident = Ident::new(sym::allow, self.def_site);
|
let allow_dead_code = attr::mk_attr_nested_word(
|
||||||
let dc_nested =
|
|
||||||
attr::mk_nested_word_item(Ident::new(sym::dead_code, self.def_site));
|
|
||||||
let allow_dead_code_item = attr::mk_list_item(allow_ident, vec![dc_nested]);
|
|
||||||
let allow_dead_code = attr::mk_attr_outer(
|
|
||||||
&self.sess.parse_sess.attr_id_generator,
|
&self.sess.parse_sess.attr_id_generator,
|
||||||
allow_dead_code_item,
|
ast::AttrStyle::Outer,
|
||||||
|
sym::allow,
|
||||||
|
sym::dead_code,
|
||||||
|
self.def_site,
|
||||||
);
|
);
|
||||||
let attrs = attrs
|
let attrs = attrs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -309,8 +308,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
|
||||||
);
|
);
|
||||||
|
|
||||||
// #[rustc_main]
|
// #[rustc_main]
|
||||||
let main_meta = ecx.meta_word(sp, sym::rustc_main);
|
let main_attr = ecx.attr_word(sym::rustc_main, sp);
|
||||||
let main_attr = ecx.attribute(main_meta);
|
|
||||||
|
|
||||||
// pub fn main() { ... }
|
// pub fn main() { ... }
|
||||||
let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(vec![]));
|
let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(vec![]));
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustc_ast::{Attribute, MetaItem};
|
use rustc_ast::{AttrStyle, Attribute, MetaItem};
|
||||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||||
use rustc_feature::AttributeTemplate;
|
use rustc_feature::AttributeTemplate;
|
||||||
use rustc_lint_defs::builtin::DUPLICATE_MACRO_ATTRIBUTES;
|
use rustc_lint_defs::builtin::DUPLICATE_MACRO_ATTRIBUTES;
|
||||||
|
@ -8,8 +8,13 @@ use rustc_span::Symbol;
|
||||||
pub fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, name: Symbol) {
|
pub fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, name: Symbol) {
|
||||||
// All the built-in macro attributes are "words" at the moment.
|
// All the built-in macro attributes are "words" at the moment.
|
||||||
let template = AttributeTemplate { word: true, ..Default::default() };
|
let template = AttributeTemplate { word: true, ..Default::default() };
|
||||||
let attr = ecx.attribute(meta_item.clone());
|
validate_attr::check_builtin_meta_item(
|
||||||
validate_attr::check_builtin_attribute(&ecx.sess.parse_sess, &attr, name, template);
|
&ecx.sess.parse_sess,
|
||||||
|
&meta_item,
|
||||||
|
AttrStyle::Outer,
|
||||||
|
name,
|
||||||
|
template,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Emit a warning if the item is annotated with the given attribute. This is used to diagnose when
|
/// Emit a warning if the item is annotated with the given attribute. This is used to diagnose when
|
||||||
|
|
|
@ -579,8 +579,6 @@ impl<'a> ExtCtxt<'a> {
|
||||||
attrs: ast::AttrVec,
|
attrs: ast::AttrVec,
|
||||||
kind: ast::ItemKind,
|
kind: ast::ItemKind,
|
||||||
) -> P<ast::Item> {
|
) -> P<ast::Item> {
|
||||||
// FIXME: Would be nice if our generated code didn't violate
|
|
||||||
// Rust coding conventions
|
|
||||||
P(ast::Item {
|
P(ast::Item {
|
||||||
ident: name,
|
ident: name,
|
||||||
attrs,
|
attrs,
|
||||||
|
@ -618,11 +616,23 @@ impl<'a> ExtCtxt<'a> {
|
||||||
self.item(span, name, AttrVec::new(), ast::ItemKind::Const(def, ty, Some(expr)))
|
self.item(span, name, AttrVec::new(), ast::ItemKind::Const(def, ty, Some(expr)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn attribute(&self, mi: ast::MetaItem) -> ast::Attribute {
|
// Builds `#[name]`.
|
||||||
attr::mk_attr_outer(&self.sess.parse_sess.attr_id_generator, mi)
|
pub fn attr_word(&self, name: Symbol, span: Span) -> ast::Attribute {
|
||||||
|
let g = &self.sess.parse_sess.attr_id_generator;
|
||||||
|
attr::mk_attr_word(g, ast::AttrStyle::Outer, name, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn meta_word(&self, sp: Span, w: Symbol) -> ast::MetaItem {
|
// Builds `#[name = val]`.
|
||||||
attr::mk_word_item(Ident::new(w, sp))
|
//
|
||||||
|
// Note: `span` is used for both the identifer and the value.
|
||||||
|
pub fn attr_name_value_str(&self, name: Symbol, val: Symbol, span: Span) -> ast::Attribute {
|
||||||
|
let g = &self.sess.parse_sess.attr_id_generator;
|
||||||
|
attr::mk_attr_name_value_str(g, ast::AttrStyle::Outer, name, val, span)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Builds `#[outer(inner)]`.
|
||||||
|
pub fn attr_nested_word(&self, outer: Symbol, inner: Symbol, span: Span) -> ast::Attribute {
|
||||||
|
let g = &self.sess.parse_sess.attr_id_generator;
|
||||||
|
attr::mk_attr_nested_word(g, ast::AttrStyle::Outer, outer, inner, span)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1644,7 +1644,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
||||||
let mut span: Option<Span> = None;
|
let mut span: Option<Span> = None;
|
||||||
while let Some(attr) = attrs.next() {
|
while let Some(attr) = attrs.next() {
|
||||||
rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features);
|
rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features);
|
||||||
validate_attr::check_meta(&self.cx.sess.parse_sess, attr);
|
validate_attr::check_attr(&self.cx.sess.parse_sess, attr);
|
||||||
|
|
||||||
let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span };
|
let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span };
|
||||||
span = Some(current_span);
|
span = Some(current_span);
|
||||||
|
|
|
@ -10,9 +10,9 @@ use rustc_errors::{Applicability, FatalError, PResult};
|
||||||
use rustc_feature::{AttributeTemplate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
|
use rustc_feature::{AttributeTemplate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
|
||||||
use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
|
use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
|
||||||
use rustc_session::parse::ParseSess;
|
use rustc_session::parse::ParseSess;
|
||||||
use rustc_span::{sym, Symbol};
|
use rustc_span::{sym, Span, Symbol};
|
||||||
|
|
||||||
pub fn check_meta(sess: &ParseSess, attr: &Attribute) {
|
pub fn check_attr(sess: &ParseSess, attr: &Attribute) {
|
||||||
if attr.is_doc_comment() {
|
if attr.is_doc_comment() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -115,25 +115,34 @@ pub fn check_builtin_attribute(
|
||||||
name: Symbol,
|
name: Symbol,
|
||||||
template: AttributeTemplate,
|
template: AttributeTemplate,
|
||||||
) {
|
) {
|
||||||
// Some special attributes like `cfg` must be checked
|
|
||||||
// before the generic check, so we skip them here.
|
|
||||||
let should_skip = |name| name == sym::cfg;
|
|
||||||
|
|
||||||
match parse_meta(sess, attr) {
|
match parse_meta(sess, attr) {
|
||||||
Ok(meta) => {
|
Ok(meta) => check_builtin_meta_item(sess, &meta, attr.style, name, template),
|
||||||
if !should_skip(name) && !is_attr_template_compatible(&template, &meta.kind) {
|
|
||||||
emit_malformed_attribute(sess, attr, name, template);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(mut err) => {
|
Err(mut err) => {
|
||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn check_builtin_meta_item(
|
||||||
|
sess: &ParseSess,
|
||||||
|
meta: &MetaItem,
|
||||||
|
style: ast::AttrStyle,
|
||||||
|
name: Symbol,
|
||||||
|
template: AttributeTemplate,
|
||||||
|
) {
|
||||||
|
// Some special attributes like `cfg` must be checked
|
||||||
|
// before the generic check, so we skip them here.
|
||||||
|
let should_skip = |name| name == sym::cfg;
|
||||||
|
|
||||||
|
if !should_skip(name) && !is_attr_template_compatible(&template, &meta.kind) {
|
||||||
|
emit_malformed_attribute(sess, style, meta.span, name, template);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn emit_malformed_attribute(
|
fn emit_malformed_attribute(
|
||||||
sess: &ParseSess,
|
sess: &ParseSess,
|
||||||
attr: &Attribute,
|
style: ast::AttrStyle,
|
||||||
|
span: Span,
|
||||||
name: Symbol,
|
name: Symbol,
|
||||||
template: AttributeTemplate,
|
template: AttributeTemplate,
|
||||||
) {
|
) {
|
||||||
|
@ -147,7 +156,7 @@ fn emit_malformed_attribute(
|
||||||
let mut msg = "attribute must be of the form ".to_owned();
|
let mut msg = "attribute must be of the form ".to_owned();
|
||||||
let mut suggestions = vec![];
|
let mut suggestions = vec![];
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
let inner = if attr.style == ast::AttrStyle::Inner { "!" } else { "" };
|
let inner = if style == ast::AttrStyle::Inner { "!" } else { "" };
|
||||||
if template.word {
|
if template.word {
|
||||||
first = false;
|
first = false;
|
||||||
let code = format!("#{}[{}]", inner, name);
|
let code = format!("#{}[{}]", inner, name);
|
||||||
|
@ -172,12 +181,12 @@ fn emit_malformed_attribute(
|
||||||
suggestions.push(code);
|
suggestions.push(code);
|
||||||
}
|
}
|
||||||
if should_warn(name) {
|
if should_warn(name) {
|
||||||
sess.buffer_lint(&ILL_FORMED_ATTRIBUTE_INPUT, attr.span, ast::CRATE_NODE_ID, &msg);
|
sess.buffer_lint(&ILL_FORMED_ATTRIBUTE_INPUT, span, ast::CRATE_NODE_ID, &msg);
|
||||||
} else {
|
} else {
|
||||||
sess.span_diagnostic
|
sess.span_diagnostic
|
||||||
.struct_span_err(attr.span, &error_msg)
|
.struct_span_err(span, &error_msg)
|
||||||
.span_suggestions(
|
.span_suggestions(
|
||||||
attr.span,
|
span,
|
||||||
if suggestions.len() == 1 {
|
if suggestions.len() == 1 {
|
||||||
"must be of the form"
|
"must be of the form"
|
||||||
} else {
|
} else {
|
||||||
|
@ -196,7 +205,7 @@ pub fn emit_fatal_malformed_builtin_attribute(
|
||||||
name: Symbol,
|
name: Symbol,
|
||||||
) -> ! {
|
) -> ! {
|
||||||
let template = BUILTIN_ATTRIBUTE_MAP.get(&name).expect("builtin attr defined").template;
|
let template = BUILTIN_ATTRIBUTE_MAP.get(&name).expect("builtin attr defined").template;
|
||||||
emit_malformed_attribute(sess, attr, name, template);
|
emit_malformed_attribute(sess, attr.style, attr.span, name, template);
|
||||||
// This is fatal, otherwise it will likely cause a cascade of other errors
|
// This is fatal, otherwise it will likely cause a cascade of other errors
|
||||||
// (and an error here is expected to be very rare).
|
// (and an error here is expected to be very rare).
|
||||||
FatalError.raise()
|
FatalError.raise()
|
||||||
|
|
|
@ -9,5 +9,7 @@ macro_rules! foo { () => () }
|
||||||
fn main() {
|
fn main() {
|
||||||
foo::<T>!(); //~ ERROR generic arguments in macro path
|
foo::<T>!(); //~ ERROR generic arguments in macro path
|
||||||
foo::<>!(); //~ ERROR generic arguments in macro path
|
foo::<>!(); //~ ERROR generic arguments in macro path
|
||||||
m!(Default<>); //~ ERROR unexpected generic arguments in path
|
m!(Default<>);
|
||||||
|
//~^ ERROR unexpected generic arguments in path
|
||||||
|
//~^^ ERROR generic arguments in macro path
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,5 +16,11 @@ error: unexpected generic arguments in path
|
||||||
LL | m!(Default<>);
|
LL | m!(Default<>);
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: generic arguments in macro path
|
||||||
|
--> $DIR/macro-ty-params.rs:12:15
|
||||||
|
|
|
||||||
|
LL | m!(Default<>);
|
||||||
|
| ^^
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue