Expand NtExpr
tokens only in key-value attributes
This commit is contained in:
parent
338f939a8d
commit
19dbb02a89
18 changed files with 402 additions and 134 deletions
|
@ -34,6 +34,13 @@ impl<A: Array> ExpectOne<A> for SmallVec<A> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait MutVisitor: Sized {
|
pub trait MutVisitor: Sized {
|
||||||
|
/// Mutable token visiting only exists for the `macro_rules` token marker and should not be
|
||||||
|
/// used otherwise. Token visitor would be entirely separate from the regular visitor if
|
||||||
|
/// the marker didn't have to visit AST fragments in nonterminal tokens.
|
||||||
|
fn token_visiting_enabled(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
// Methods in this trait have one of three forms:
|
// Methods in this trait have one of three forms:
|
||||||
//
|
//
|
||||||
// fn visit_t(&mut self, t: &mut T); // common
|
// fn visit_t(&mut self, t: &mut T); // common
|
||||||
|
@ -246,22 +253,6 @@ pub trait MutVisitor: Sized {
|
||||||
noop_flat_map_generic_param(param, self)
|
noop_flat_map_generic_param(param, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_tt(&mut self, tt: &mut TokenTree) {
|
|
||||||
noop_visit_tt(tt, self);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_tts(&mut self, tts: &mut TokenStream) {
|
|
||||||
noop_visit_tts(tts, self);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_token(&mut self, t: &mut Token) {
|
|
||||||
noop_visit_token(t, self);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_interpolated(&mut self, nt: &mut token::Nonterminal) {
|
|
||||||
noop_visit_interpolated(nt, self);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_param_bound(&mut self, tpb: &mut GenericBound) {
|
fn visit_param_bound(&mut self, tpb: &mut GenericBound) {
|
||||||
noop_visit_param_bound(tpb, self);
|
noop_visit_param_bound(tpb, self);
|
||||||
}
|
}
|
||||||
|
@ -375,11 +366,30 @@ pub fn visit_mac_args<T: MutVisitor>(args: &mut MacArgs, vis: &mut T) {
|
||||||
MacArgs::Empty => {}
|
MacArgs::Empty => {}
|
||||||
MacArgs::Delimited(dspan, _delim, tokens) => {
|
MacArgs::Delimited(dspan, _delim, tokens) => {
|
||||||
visit_delim_span(dspan, vis);
|
visit_delim_span(dspan, vis);
|
||||||
vis.visit_tts(tokens);
|
visit_tts(tokens, vis);
|
||||||
}
|
}
|
||||||
MacArgs::Eq(eq_span, tokens) => {
|
MacArgs::Eq(eq_span, tokens) => {
|
||||||
vis.visit_span(eq_span);
|
vis.visit_span(eq_span);
|
||||||
vis.visit_tts(tokens);
|
visit_tts(tokens, vis);
|
||||||
|
// The value in `#[key = VALUE]` must be visited as an expression for backward
|
||||||
|
// compatibility, so that macros can be expanded in that position.
|
||||||
|
if !vis.token_visiting_enabled() {
|
||||||
|
if let Some(TokenTree::Token(token)) = tokens.trees_ref().next() {
|
||||||
|
if let token::Interpolated(..) = token.kind {
|
||||||
|
// ^^ Do not `make_mut` unless we have to.
|
||||||
|
match Lrc::make_mut(&mut tokens.0).get_mut(0) {
|
||||||
|
Some((TokenTree::Token(token), _spacing)) => match &mut token.kind {
|
||||||
|
token::Interpolated(nt) => match Lrc::make_mut(nt) {
|
||||||
|
token::NtExpr(expr) => vis.visit_expr(expr),
|
||||||
|
t => panic!("unexpected token in key-value attribute: {:?}", t),
|
||||||
|
},
|
||||||
|
t => panic!("unexpected token in key-value attribute: {:?}", t),
|
||||||
|
},
|
||||||
|
t => panic!("unexpected token in key-value attribute: {:?}", t),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -626,28 +636,33 @@ pub fn noop_flat_map_param<T: MutVisitor>(mut param: Param, vis: &mut T) -> Smal
|
||||||
smallvec![param]
|
smallvec![param]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn noop_visit_tt<T: MutVisitor>(tt: &mut TokenTree, vis: &mut T) {
|
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
|
||||||
|
pub fn visit_tt<T: MutVisitor>(tt: &mut TokenTree, vis: &mut T) {
|
||||||
match tt {
|
match tt {
|
||||||
TokenTree::Token(token) => {
|
TokenTree::Token(token) => {
|
||||||
vis.visit_token(token);
|
visit_token(token, vis);
|
||||||
}
|
}
|
||||||
TokenTree::Delimited(DelimSpan { open, close }, _delim, tts) => {
|
TokenTree::Delimited(DelimSpan { open, close }, _delim, tts) => {
|
||||||
vis.visit_span(open);
|
vis.visit_span(open);
|
||||||
vis.visit_span(close);
|
vis.visit_span(close);
|
||||||
vis.visit_tts(tts);
|
visit_tts(tts, vis);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn noop_visit_tts<T: MutVisitor>(TokenStream(tts): &mut TokenStream, vis: &mut T) {
|
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
|
||||||
let tts = Lrc::make_mut(tts);
|
pub fn visit_tts<T: MutVisitor>(TokenStream(tts): &mut TokenStream, vis: &mut T) {
|
||||||
visit_vec(tts, |(tree, _is_joint)| vis.visit_tt(tree));
|
if vis.token_visiting_enabled() {
|
||||||
|
let tts = Lrc::make_mut(tts);
|
||||||
|
visit_vec(tts, |(tree, _is_joint)| visit_tt(tree, vis));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
|
||||||
// Applies ident visitor if it's an ident; applies other visits to interpolated nodes.
|
// Applies ident visitor if it's an ident; applies other visits to interpolated nodes.
|
||||||
// In practice the ident part is not actually used by specific visitors right now,
|
// In practice the ident part is not actually used by specific visitors right now,
|
||||||
// but there's a test below checking that it works.
|
// but there's a test below checking that it works.
|
||||||
pub fn noop_visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) {
|
pub fn visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) {
|
||||||
let Token { kind, span } = t;
|
let Token { kind, span } = t;
|
||||||
match kind {
|
match kind {
|
||||||
token::Ident(name, _) | token::Lifetime(name) => {
|
token::Ident(name, _) | token::Lifetime(name) => {
|
||||||
|
@ -659,13 +674,14 @@ pub fn noop_visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) {
|
||||||
}
|
}
|
||||||
token::Interpolated(nt) => {
|
token::Interpolated(nt) => {
|
||||||
let mut nt = Lrc::make_mut(nt);
|
let mut nt = Lrc::make_mut(nt);
|
||||||
vis.visit_interpolated(&mut nt);
|
visit_interpolated(&mut nt, vis);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
vis.visit_span(span);
|
vis.visit_span(span);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
|
||||||
/// Applies the visitor to elements of interpolated nodes.
|
/// Applies the visitor to elements of interpolated nodes.
|
||||||
//
|
//
|
||||||
// N.B., this can occur only when applying a visitor to partially expanded
|
// N.B., this can occur only when applying a visitor to partially expanded
|
||||||
|
@ -689,7 +705,7 @@ pub fn noop_visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) {
|
||||||
// contain multiple items, but decided against it when I looked at
|
// contain multiple items, but decided against it when I looked at
|
||||||
// `parse_item_or_view_item` and tried to figure out what I would do with
|
// `parse_item_or_view_item` and tried to figure out what I would do with
|
||||||
// multiple items there....
|
// multiple items there....
|
||||||
pub fn noop_visit_interpolated<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut T) {
|
pub fn visit_interpolated<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut T) {
|
||||||
match nt {
|
match nt {
|
||||||
token::NtItem(item) => visit_clobber(item, |item| {
|
token::NtItem(item) => visit_clobber(item, |item| {
|
||||||
// This is probably okay, because the only visitors likely to
|
// This is probably okay, because the only visitors likely to
|
||||||
|
@ -714,7 +730,7 @@ pub fn noop_visit_interpolated<T: MutVisitor>(nt: &mut token::Nonterminal, vis:
|
||||||
visit_mac_args(args, vis);
|
visit_mac_args(args, vis);
|
||||||
}
|
}
|
||||||
token::NtPath(path) => vis.visit_path(path),
|
token::NtPath(path) => vis.visit_path(path),
|
||||||
token::NtTT(tt) => vis.visit_tt(tt),
|
token::NtTT(tt) => visit_tt(tt, vis),
|
||||||
token::NtVis(visib) => vis.visit_vis(visib),
|
token::NtVis(visib) => vis.visit_vis(visib),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -318,6 +318,10 @@ impl TokenStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn trees_ref(&self) -> CursorRef<'_> {
|
||||||
|
CursorRef::new(self)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn trees(&self) -> Cursor {
|
pub fn trees(&self) -> Cursor {
|
||||||
self.clone().into_trees()
|
self.clone().into_trees()
|
||||||
}
|
}
|
||||||
|
@ -408,6 +412,36 @@ impl TokenStreamBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// By-reference iterator over a `TokenStream`.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct CursorRef<'t> {
|
||||||
|
stream: &'t TokenStream,
|
||||||
|
index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'t> CursorRef<'t> {
|
||||||
|
fn new(stream: &TokenStream) -> CursorRef<'_> {
|
||||||
|
CursorRef { stream, index: 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_with_spacing(&mut self) -> Option<&'t TreeAndSpacing> {
|
||||||
|
self.stream.0.get(self.index).map(|tree| {
|
||||||
|
self.index += 1;
|
||||||
|
tree
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'t> Iterator for CursorRef<'t> {
|
||||||
|
type Item = &'t TokenTree;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<&'t TokenTree> {
|
||||||
|
self.next_with_spacing().map(|(tree, _)| tree)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Owning by-value iterator over a `TokenStream`.
|
||||||
|
/// FIXME: Many uses of this can be replaced with by-reference iterator to avoid clones.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Cursor {
|
pub struct Cursor {
|
||||||
pub stream: TokenStream,
|
pub stream: TokenStream,
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
//! those that are created by the expansion of a macro.
|
//! those that are created by the expansion of a macro.
|
||||||
|
|
||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
use crate::token::Token;
|
use crate::token;
|
||||||
use crate::tokenstream::{TokenStream, TokenTree};
|
use crate::tokenstream::TokenTree;
|
||||||
|
|
||||||
use rustc_span::symbol::{Ident, Symbol};
|
use rustc_span::symbol::{Ident, Symbol};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
@ -208,14 +208,6 @@ pub trait Visitor<'ast>: Sized {
|
||||||
fn visit_attribute(&mut self, attr: &'ast Attribute) {
|
fn visit_attribute(&mut self, attr: &'ast Attribute) {
|
||||||
walk_attribute(self, attr)
|
walk_attribute(self, attr)
|
||||||
}
|
}
|
||||||
fn visit_tt(&mut self, tt: TokenTree) {
|
|
||||||
walk_tt(self, tt)
|
|
||||||
}
|
|
||||||
fn visit_tts(&mut self, tts: TokenStream) {
|
|
||||||
walk_tts(self, tts)
|
|
||||||
}
|
|
||||||
fn visit_token(&mut self, _t: Token) {}
|
|
||||||
// FIXME: add `visit_interpolated` and `walk_interpolated`
|
|
||||||
fn visit_vis(&mut self, vis: &'ast Visibility) {
|
fn visit_vis(&mut self, vis: &'ast Visibility) {
|
||||||
walk_vis(self, vis)
|
walk_vis(self, vis)
|
||||||
}
|
}
|
||||||
|
@ -902,20 +894,19 @@ pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute)
|
||||||
pub fn walk_mac_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a MacArgs) {
|
pub fn walk_mac_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a MacArgs) {
|
||||||
match args {
|
match args {
|
||||||
MacArgs::Empty => {}
|
MacArgs::Empty => {}
|
||||||
MacArgs::Delimited(_dspan, _delim, tokens) => visitor.visit_tts(tokens.clone()),
|
MacArgs::Delimited(_dspan, _delim, _tokens) => {}
|
||||||
MacArgs::Eq(_eq_span, tokens) => visitor.visit_tts(tokens.clone()),
|
// The value in `#[key = VALUE]` must be visited as an expression for backward
|
||||||
}
|
// compatibility, so that macros can be expanded in that position.
|
||||||
}
|
MacArgs::Eq(_eq_span, tokens) => match tokens.trees_ref().next() {
|
||||||
|
Some(TokenTree::Token(token)) => match &token.kind {
|
||||||
pub fn walk_tt<'a, V: Visitor<'a>>(visitor: &mut V, tt: TokenTree) {
|
token::Interpolated(nt) => match &**nt {
|
||||||
match tt {
|
token::NtExpr(expr) => visitor.visit_expr(expr),
|
||||||
TokenTree::Token(token) => visitor.visit_token(token),
|
t => panic!("unexpected token in key-value attribute: {:?}", t),
|
||||||
TokenTree::Delimited(_, _, tts) => visitor.visit_tts(tts),
|
},
|
||||||
}
|
token::Literal(..) | token::Ident(..) => {}
|
||||||
}
|
t => panic!("unexpected token in key-value attribute: {:?}", t),
|
||||||
|
},
|
||||||
pub fn walk_tts<'a, V: Visitor<'a>>(visitor: &mut V, tts: TokenStream) {
|
t => panic!("unexpected token in key-value attribute: {:?}", t),
|
||||||
for tt in tts.trees() {
|
},
|
||||||
visitor.visit_tt(tt);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,10 @@ use std::mem;
|
||||||
struct Marker(ExpnId, Transparency);
|
struct Marker(ExpnId, Transparency);
|
||||||
|
|
||||||
impl MutVisitor for Marker {
|
impl MutVisitor for Marker {
|
||||||
|
fn token_visiting_enabled(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_span(&mut self, span: &mut Span) {
|
fn visit_span(&mut self, span: &mut Span) {
|
||||||
*span = span.apply_mark(self.0, self.1)
|
*span = span.apply_mark(self.0, self.1)
|
||||||
}
|
}
|
||||||
|
@ -277,7 +281,7 @@ pub(super) fn transcribe<'a>(
|
||||||
// preserve syntax context.
|
// preserve syntax context.
|
||||||
mbe::TokenTree::Token(token) => {
|
mbe::TokenTree::Token(token) => {
|
||||||
let mut tt = TokenTree::Token(token);
|
let mut tt = TokenTree::Token(token);
|
||||||
marker.visit_tt(&mut tt);
|
mut_visit::visit_tt(&mut tt, &mut marker);
|
||||||
result.push(tt.into());
|
result.push(tt.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,9 @@ fn fake_print_crate(s: &mut pprust::State<'_>, krate: &ast::Crate) {
|
||||||
struct ToZzIdentMutVisitor;
|
struct ToZzIdentMutVisitor;
|
||||||
|
|
||||||
impl MutVisitor for ToZzIdentMutVisitor {
|
impl MutVisitor for ToZzIdentMutVisitor {
|
||||||
|
fn token_visiting_enabled(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
fn visit_ident(&mut self, ident: &mut Ident) {
|
fn visit_ident(&mut self, ident: &mut Ident) {
|
||||||
*ident = Ident::from_str("zz");
|
*ident = Ident::from_str("zz");
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@ use crate::{
|
||||||
};
|
};
|
||||||
use crate::{Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, Segment, ToNameBinding};
|
use crate::{Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, Segment, ToNameBinding};
|
||||||
|
|
||||||
use rustc_ast::token::{self, Token};
|
|
||||||
use rustc_ast::visit::{self, AssocCtxt, Visitor};
|
use rustc_ast::visit::{self, AssocCtxt, Visitor};
|
||||||
use rustc_ast::{self as ast, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId};
|
use rustc_ast::{self as ast, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId};
|
||||||
use rustc_ast::{AssocItem, AssocItemKind, MetaItemKind, StmtKind};
|
use rustc_ast::{AssocItem, AssocItemKind, MetaItemKind, StmtKind};
|
||||||
|
@ -1395,16 +1394,6 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
|
||||||
visit::walk_assoc_item(self, item, ctxt);
|
visit::walk_assoc_item(self, item, ctxt);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_token(&mut self, t: Token) {
|
|
||||||
if let token::Interpolated(nt) = t.kind {
|
|
||||||
if let token::NtExpr(ref expr) = *nt {
|
|
||||||
if let ast::ExprKind::MacCall(..) = expr.kind {
|
|
||||||
self.visit_invoc(expr.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_attribute(&mut self, attr: &'b ast::Attribute) {
|
fn visit_attribute(&mut self, attr: &'b ast::Attribute) {
|
||||||
if !attr.is_doc_comment() && attr::is_builtin_attr(attr) {
|
if !attr.is_doc_comment() && attr::is_builtin_attr(attr) {
|
||||||
self.r
|
self.r
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use crate::Resolver;
|
use crate::Resolver;
|
||||||
use rustc_ast::token::{self, Token};
|
|
||||||
use rustc_ast::visit::{self, FnKind};
|
use rustc_ast::visit::{self, FnKind};
|
||||||
use rustc_ast::walk_list;
|
use rustc_ast::walk_list;
|
||||||
use rustc_ast::*;
|
use rustc_ast::*;
|
||||||
|
@ -256,16 +255,6 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_token(&mut self, t: Token) {
|
|
||||||
if let token::Interpolated(nt) = t.kind {
|
|
||||||
if let token::NtExpr(ref expr) = *nt {
|
|
||||||
if let ExprKind::MacCall(..) = expr.kind {
|
|
||||||
self.visit_macro_invoc(expr.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_arm(&mut self, arm: &'a Arm) {
|
fn visit_arm(&mut self, arm: &'a Arm) {
|
||||||
if arm.is_placeholder { self.visit_macro_invoc(arm.id) } else { visit::walk_arm(self, arm) }
|
if arm.is_placeholder { self.visit_macro_invoc(arm.id) } else { visit::walk_arm(self, arm) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -2275,64 +2275,56 @@ atomic_int! {
|
||||||
"AtomicU128::new(0)",
|
"AtomicU128::new(0)",
|
||||||
u128 AtomicU128 ATOMIC_U128_INIT
|
u128 AtomicU128 ATOMIC_U128_INIT
|
||||||
}
|
}
|
||||||
#[cfg(target_has_atomic_load_store = "ptr")]
|
|
||||||
#[cfg(target_pointer_width = "16")]
|
macro_rules! atomic_int_ptr_sized {
|
||||||
macro_rules! ptr_width {
|
( $($target_pointer_width:literal $align:literal)* ) => { $(
|
||||||
() => {
|
#[cfg(target_has_atomic_load_store = "ptr")]
|
||||||
2
|
#[cfg(target_pointer_width = $target_pointer_width)]
|
||||||
};
|
atomic_int! {
|
||||||
|
cfg(target_has_atomic = "ptr"),
|
||||||
|
cfg(target_has_atomic_equal_alignment = "ptr"),
|
||||||
|
stable(feature = "rust1", since = "1.0.0"),
|
||||||
|
stable(feature = "extended_compare_and_swap", since = "1.10.0"),
|
||||||
|
stable(feature = "atomic_debug", since = "1.3.0"),
|
||||||
|
stable(feature = "atomic_access", since = "1.15.0"),
|
||||||
|
stable(feature = "atomic_from", since = "1.23.0"),
|
||||||
|
stable(feature = "atomic_nand", since = "1.27.0"),
|
||||||
|
rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
||||||
|
stable(feature = "rust1", since = "1.0.0"),
|
||||||
|
"isize", "../../../std/primitive.isize.html",
|
||||||
|
"",
|
||||||
|
atomic_min, atomic_max,
|
||||||
|
$align,
|
||||||
|
"AtomicIsize::new(0)",
|
||||||
|
isize AtomicIsize ATOMIC_ISIZE_INIT
|
||||||
|
}
|
||||||
|
#[cfg(target_has_atomic_load_store = "ptr")]
|
||||||
|
#[cfg(target_pointer_width = $target_pointer_width)]
|
||||||
|
atomic_int! {
|
||||||
|
cfg(target_has_atomic = "ptr"),
|
||||||
|
cfg(target_has_atomic_equal_alignment = "ptr"),
|
||||||
|
stable(feature = "rust1", since = "1.0.0"),
|
||||||
|
stable(feature = "extended_compare_and_swap", since = "1.10.0"),
|
||||||
|
stable(feature = "atomic_debug", since = "1.3.0"),
|
||||||
|
stable(feature = "atomic_access", since = "1.15.0"),
|
||||||
|
stable(feature = "atomic_from", since = "1.23.0"),
|
||||||
|
stable(feature = "atomic_nand", since = "1.27.0"),
|
||||||
|
rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
||||||
|
stable(feature = "rust1", since = "1.0.0"),
|
||||||
|
"usize", "../../../std/primitive.usize.html",
|
||||||
|
"",
|
||||||
|
atomic_umin, atomic_umax,
|
||||||
|
$align,
|
||||||
|
"AtomicUsize::new(0)",
|
||||||
|
usize AtomicUsize ATOMIC_USIZE_INIT
|
||||||
|
}
|
||||||
|
)* };
|
||||||
}
|
}
|
||||||
#[cfg(target_has_atomic_load_store = "ptr")]
|
|
||||||
#[cfg(target_pointer_width = "32")]
|
atomic_int_ptr_sized! {
|
||||||
macro_rules! ptr_width {
|
"16" 2
|
||||||
() => {
|
"32" 4
|
||||||
4
|
"64" 8
|
||||||
};
|
|
||||||
}
|
|
||||||
#[cfg(target_has_atomic_load_store = "ptr")]
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
|
||||||
macro_rules! ptr_width {
|
|
||||||
() => {
|
|
||||||
8
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#[cfg(target_has_atomic_load_store = "ptr")]
|
|
||||||
atomic_int! {
|
|
||||||
cfg(target_has_atomic = "ptr"),
|
|
||||||
cfg(target_has_atomic_equal_alignment = "ptr"),
|
|
||||||
stable(feature = "rust1", since = "1.0.0"),
|
|
||||||
stable(feature = "extended_compare_and_swap", since = "1.10.0"),
|
|
||||||
stable(feature = "atomic_debug", since = "1.3.0"),
|
|
||||||
stable(feature = "atomic_access", since = "1.15.0"),
|
|
||||||
stable(feature = "atomic_from", since = "1.23.0"),
|
|
||||||
stable(feature = "atomic_nand", since = "1.27.0"),
|
|
||||||
rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
|
||||||
stable(feature = "rust1", since = "1.0.0"),
|
|
||||||
"isize", "../../../std/primitive.isize.html",
|
|
||||||
"",
|
|
||||||
atomic_min, atomic_max,
|
|
||||||
ptr_width!(),
|
|
||||||
"AtomicIsize::new(0)",
|
|
||||||
isize AtomicIsize ATOMIC_ISIZE_INIT
|
|
||||||
}
|
|
||||||
#[cfg(target_has_atomic_load_store = "ptr")]
|
|
||||||
atomic_int! {
|
|
||||||
cfg(target_has_atomic = "ptr"),
|
|
||||||
cfg(target_has_atomic_equal_alignment = "ptr"),
|
|
||||||
stable(feature = "rust1", since = "1.0.0"),
|
|
||||||
stable(feature = "extended_compare_and_swap", since = "1.10.0"),
|
|
||||||
stable(feature = "atomic_debug", since = "1.3.0"),
|
|
||||||
stable(feature = "atomic_access", since = "1.15.0"),
|
|
||||||
stable(feature = "atomic_from", since = "1.23.0"),
|
|
||||||
stable(feature = "atomic_nand", since = "1.27.0"),
|
|
||||||
rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
|
||||||
stable(feature = "rust1", since = "1.0.0"),
|
|
||||||
"usize", "../../../std/primitive.usize.html",
|
|
||||||
"",
|
|
||||||
atomic_umin, atomic_umax,
|
|
||||||
ptr_width!(),
|
|
||||||
"AtomicUsize::new(0)",
|
|
||||||
usize AtomicUsize ATOMIC_USIZE_INIT
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
12
src/test/ui/attributes/auxiliary/key-value-expansion.rs
Normal file
12
src/test/ui/attributes/auxiliary/key-value-expansion.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
// force-host
|
||||||
|
// no-prefer-dynamic
|
||||||
|
|
||||||
|
#![crate_type = "proc-macro"]
|
||||||
|
|
||||||
|
extern crate proc_macro;
|
||||||
|
use proc_macro::*;
|
||||||
|
|
||||||
|
#[proc_macro_derive(EthabiContract, attributes(ethabi_contract_options))]
|
||||||
|
pub fn ethabi_derive(input: TokenStream) -> TokenStream {
|
||||||
|
Default::default()
|
||||||
|
}
|
55
src/test/ui/attributes/key-value-expansion.rs
Normal file
55
src/test/ui/attributes/key-value-expansion.rs
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
// Regression tests for issue #55414, expansion happens in the value of a key-value attribute,
|
||||||
|
// and the expanded expression is more complex than simply a macro call.
|
||||||
|
|
||||||
|
// aux-build:key-value-expansion.rs
|
||||||
|
|
||||||
|
#![feature(rustc_attrs)]
|
||||||
|
|
||||||
|
extern crate key_value_expansion;
|
||||||
|
|
||||||
|
// Minimized test case.
|
||||||
|
|
||||||
|
macro_rules! bug {
|
||||||
|
($expr:expr) => {
|
||||||
|
#[rustc_dummy = $expr] // Any key-value attribute, not necessarily `doc`
|
||||||
|
//~^ ERROR unexpected token: `(7u32)`
|
||||||
|
struct S;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any expressions containing macro call `X` that's more complex than `X` itself.
|
||||||
|
// Parentheses will work.
|
||||||
|
bug!((column!()));
|
||||||
|
|
||||||
|
// Original test case.
|
||||||
|
|
||||||
|
macro_rules! bug {
|
||||||
|
() => {
|
||||||
|
bug!("bug" + stringify!(found));
|
||||||
|
};
|
||||||
|
($test:expr) => {
|
||||||
|
#[doc = $test] //~ ERROR unexpected token: `"bug" + "found"`
|
||||||
|
struct Test {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
bug!();
|
||||||
|
|
||||||
|
// Test case from #66804.
|
||||||
|
|
||||||
|
macro_rules! doc_comment {
|
||||||
|
($x:expr) => {
|
||||||
|
#[doc = $x] //~ ERROR unexpected token: `{
|
||||||
|
extern {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! some_macro {
|
||||||
|
($t1: ty) => {
|
||||||
|
doc_comment! {format!("{coor}", coor = stringify!($t1)).as_str()}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
some_macro!(u8);
|
||||||
|
|
||||||
|
fn main() {}
|
44
src/test/ui/attributes/key-value-expansion.stderr
Normal file
44
src/test/ui/attributes/key-value-expansion.stderr
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
error: unexpected token: `(7u32)`
|
||||||
|
--> $DIR/key-value-expansion.rs:14:25
|
||||||
|
|
|
||||||
|
LL | #[rustc_dummy = $expr] // Any key-value attribute, not necessarily `doc`
|
||||||
|
| ^^^^^
|
||||||
|
...
|
||||||
|
LL | bug!((column!()));
|
||||||
|
| ------------------ in this macro invocation
|
||||||
|
|
|
||||||
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: unexpected token: `"bug" + "found"`
|
||||||
|
--> $DIR/key-value-expansion.rs:31:17
|
||||||
|
|
|
||||||
|
LL | #[doc = $test]
|
||||||
|
| ^^^^^
|
||||||
|
...
|
||||||
|
LL | bug!();
|
||||||
|
| ------- in this macro invocation
|
||||||
|
|
|
||||||
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: unexpected token: `{
|
||||||
|
let res =
|
||||||
|
::alloc::fmt::format(::core::fmt::Arguments::new_v1(&[""],
|
||||||
|
&match (&"u8",) {
|
||||||
|
(arg0,) =>
|
||||||
|
[::core::fmt::ArgumentV1::new(arg0,
|
||||||
|
::core::fmt::Display::fmt)],
|
||||||
|
}));
|
||||||
|
res
|
||||||
|
}.as_str()`
|
||||||
|
--> $DIR/key-value-expansion.rs:42:17
|
||||||
|
|
|
||||||
|
LL | #[doc = $x]
|
||||||
|
| ^^
|
||||||
|
...
|
||||||
|
LL | some_macro!(u8);
|
||||||
|
| ---------------- in this macro invocation
|
||||||
|
|
|
||||||
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
17
src/test/ui/attributes/nonterminal-expansion.rs
Normal file
17
src/test/ui/attributes/nonterminal-expansion.rs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// Macros were previously expanded in `Expr` nonterminal tokens, now they are not.
|
||||||
|
|
||||||
|
macro_rules! pass_nonterminal {
|
||||||
|
($n:expr) => {
|
||||||
|
#[repr(align($n))] //~ ERROR expected unsuffixed literal or identifier, found `n!()`
|
||||||
|
//~| ERROR unrecognized representation hint
|
||||||
|
struct S;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! n {
|
||||||
|
() => { 32 };
|
||||||
|
}
|
||||||
|
|
||||||
|
pass_nonterminal!(n!());
|
||||||
|
|
||||||
|
fn main() {}
|
25
src/test/ui/attributes/nonterminal-expansion.stderr
Normal file
25
src/test/ui/attributes/nonterminal-expansion.stderr
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
error: expected unsuffixed literal or identifier, found `n!()`
|
||||||
|
--> $DIR/nonterminal-expansion.rs:5:22
|
||||||
|
|
|
||||||
|
LL | #[repr(align($n))]
|
||||||
|
| ^^
|
||||||
|
...
|
||||||
|
LL | pass_nonterminal!(n!());
|
||||||
|
| ------------------------ in this macro invocation
|
||||||
|
|
|
||||||
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error[E0552]: unrecognized representation hint
|
||||||
|
--> $DIR/nonterminal-expansion.rs:5:16
|
||||||
|
|
|
||||||
|
LL | #[repr(align($n))]
|
||||||
|
| ^^^^^^^^^
|
||||||
|
...
|
||||||
|
LL | pass_nonterminal!(n!());
|
||||||
|
| ------------------------ in this macro invocation
|
||||||
|
|
|
||||||
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0552`.
|
|
@ -29,6 +29,7 @@ macro_rules! generate_s10 {
|
||||||
($expr: expr) => {
|
($expr: expr) => {
|
||||||
#[cfg(feature = $expr)]
|
#[cfg(feature = $expr)]
|
||||||
//~^ ERROR expected unsuffixed literal or identifier, found `concat!("nonexistent")`
|
//~^ ERROR expected unsuffixed literal or identifier, found `concat!("nonexistent")`
|
||||||
|
//~| ERROR expected unsuffixed literal or identifier, found `concat!("nonexistent")`
|
||||||
struct S10;
|
struct S10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,18 @@ LL | generate_s10!(concat!("nonexistent"));
|
||||||
|
|
|
|
||||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: aborting due to 10 previous errors
|
error: expected unsuffixed literal or identifier, found `concat!("nonexistent")`
|
||||||
|
--> $DIR/cfg-attr-syntax-validation.rs:30:25
|
||||||
|
|
|
||||||
|
LL | #[cfg(feature = $expr)]
|
||||||
|
| ^^^^^
|
||||||
|
...
|
||||||
|
LL | generate_s10!(concat!("nonexistent"));
|
||||||
|
| -------------------------------------- in this macro invocation
|
||||||
|
|
|
||||||
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: aborting due to 11 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0537, E0565.
|
Some errors have detailed explanations: E0537, E0565.
|
||||||
For more information about an error, try `rustc --explain E0537`.
|
For more information about an error, try `rustc --explain E0537`.
|
||||||
|
|
|
@ -112,6 +112,12 @@ pub fn print_attr(_: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
print_helper(input, "ATTR")
|
print_helper(input, "ATTR")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn print_attr_args(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
|
print_helper(args, "ATTR_ARGS");
|
||||||
|
input
|
||||||
|
}
|
||||||
|
|
||||||
#[proc_macro_derive(Print, attributes(print_helper))]
|
#[proc_macro_derive(Print, attributes(print_helper))]
|
||||||
pub fn print_derive(input: TokenStream) -> TokenStream {
|
pub fn print_derive(input: TokenStream) -> TokenStream {
|
||||||
print_helper(input, "DERIVE");
|
print_helper(input, "DERIVE");
|
||||||
|
|
37
src/test/ui/proc-macro/nonterminal-expansion.rs
Normal file
37
src/test/ui/proc-macro/nonterminal-expansion.rs
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
// check-pass
|
||||||
|
// compile-flags: -Z span-debug
|
||||||
|
// aux-build:test-macros.rs
|
||||||
|
|
||||||
|
#![no_std] // Don't load unnecessary hygiene information from std
|
||||||
|
extern crate std;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate test_macros;
|
||||||
|
|
||||||
|
macro_rules! pass_nonterminal {
|
||||||
|
($line:expr) => {
|
||||||
|
#[print_attr_args(a, $line, b)]
|
||||||
|
struct S;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// `line!()` is not expanded before it's passed to the proc macro.
|
||||||
|
pass_nonterminal!(line!());
|
||||||
|
|
||||||
|
// Test case from #43860.
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! use_contract {
|
||||||
|
($name: ident, $path: expr) => {
|
||||||
|
#[derive(Empty)]
|
||||||
|
#[empty_helper(path = $path)] // OK
|
||||||
|
pub struct $name<T, C> {
|
||||||
|
api: T,
|
||||||
|
contract: C,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
use_contract!(ContractName, file!());
|
||||||
|
|
||||||
|
fn main() {}
|
42
src/test/ui/proc-macro/nonterminal-expansion.stdout
Normal file
42
src/test/ui/proc-macro/nonterminal-expansion.stdout
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
PRINT-ATTR_ARGS INPUT (DISPLAY): a, line!(), b
|
||||||
|
PRINT-ATTR_ARGS RE-COLLECTED (DISPLAY): a, line ! (), b
|
||||||
|
PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
|
||||||
|
Ident {
|
||||||
|
ident: "a",
|
||||||
|
span: $DIR/nonterminal-expansion.rs:13:27: 13:28 (#4),
|
||||||
|
},
|
||||||
|
Punct {
|
||||||
|
ch: ',',
|
||||||
|
spacing: Alone,
|
||||||
|
span: $DIR/nonterminal-expansion.rs:13:28: 13:29 (#4),
|
||||||
|
},
|
||||||
|
Group {
|
||||||
|
delimiter: None,
|
||||||
|
stream: TokenStream [
|
||||||
|
Ident {
|
||||||
|
ident: "line",
|
||||||
|
span: $DIR/nonterminal-expansion.rs:19:19: 19:23 (#0),
|
||||||
|
},
|
||||||
|
Punct {
|
||||||
|
ch: '!',
|
||||||
|
spacing: Alone,
|
||||||
|
span: $DIR/nonterminal-expansion.rs:19:23: 19:24 (#0),
|
||||||
|
},
|
||||||
|
Group {
|
||||||
|
delimiter: Parenthesis,
|
||||||
|
stream: TokenStream [],
|
||||||
|
span: $DIR/nonterminal-expansion.rs:19:24: 19:26 (#0),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
span: $DIR/nonterminal-expansion.rs:13:30: 13:35 (#4),
|
||||||
|
},
|
||||||
|
Punct {
|
||||||
|
ch: ',',
|
||||||
|
spacing: Alone,
|
||||||
|
span: $DIR/nonterminal-expansion.rs:13:35: 13:36 (#4),
|
||||||
|
},
|
||||||
|
Ident {
|
||||||
|
ident: "b",
|
||||||
|
span: $DIR/nonterminal-expansion.rs:13:37: 13:38 (#4),
|
||||||
|
},
|
||||||
|
]
|
Loading…
Add table
Add a link
Reference in a new issue