Rollup merge of #91313 - petrochenkov:cratexp, r=Aaron1011
expand: Turn `ast::Crate` into a first class expansion target And stop creating a fake `mod` item for the crate root when expanding a crate, thus addressing FIXMEs left in https://github.com/rust-lang/rust/pull/82238, and making a step towards a proper support for crate-level macro attributes (cc #54726). I haven't added token collection support for the whole crate in this PR, maybe later. r? `@Aaron1011`
This commit is contained in:
commit
519a842c50
20 changed files with 203 additions and 159 deletions
|
@ -517,6 +517,8 @@ pub struct Crate {
|
||||||
pub attrs: Vec<Attribute>,
|
pub attrs: Vec<Attribute>,
|
||||||
pub items: Vec<P<Item>>,
|
pub items: Vec<P<Item>>,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
// Placeholder ID if the crate node is a macro placeholder.
|
||||||
|
pub is_placeholder: Option<NodeId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Possible values inside of compile-time attribute lists.
|
/// Possible values inside of compile-time attribute lists.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use super::ptr::P;
|
use super::ptr::P;
|
||||||
use super::token::Nonterminal;
|
use super::token::Nonterminal;
|
||||||
use super::tokenstream::LazyTokenStream;
|
use super::tokenstream::LazyTokenStream;
|
||||||
use super::{Arm, ExprField, FieldDef, GenericParam, Param, PatField, Variant};
|
use super::{Arm, Crate, ExprField, FieldDef, GenericParam, Param, PatField, Variant};
|
||||||
use super::{AssocItem, Expr, ForeignItem, Item, Local, MacCallStmt};
|
use super::{AssocItem, Expr, ForeignItem, Item, Local, MacCallStmt};
|
||||||
use super::{AttrItem, AttrKind, Block, Pat, Path, Ty, Visibility};
|
use super::{AttrItem, AttrKind, Block, Pat, Path, Ty, Visibility};
|
||||||
use super::{AttrVec, Attribute, Stmt, StmtKind};
|
use super::{AttrVec, Attribute, Stmt, StmtKind};
|
||||||
|
@ -276,7 +276,7 @@ derive_has_tokens_and_attrs! {
|
||||||
// These ast nodes only support inert attributes, so they don't
|
// These ast nodes only support inert attributes, so they don't
|
||||||
// store tokens (since nothing can observe them)
|
// store tokens (since nothing can observe them)
|
||||||
derive_has_attrs_no_tokens! {
|
derive_has_attrs_no_tokens! {
|
||||||
FieldDef, Arm, ExprField, PatField, Variant, Param, GenericParam
|
FieldDef, Arm, ExprField, PatField, Variant, Param, GenericParam, Crate
|
||||||
}
|
}
|
||||||
|
|
||||||
// These AST nodes don't support attributes, but can
|
// These AST nodes don't support attributes, but can
|
||||||
|
|
|
@ -284,6 +284,10 @@ pub trait MutVisitor: Sized {
|
||||||
/// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful
|
/// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful
|
||||||
/// when using a `flat_map_*` or `filter_map_*` method within a `visit_`
|
/// when using a `flat_map_*` or `filter_map_*` method within a `visit_`
|
||||||
/// method. Abort the program if the closure panics.
|
/// method. Abort the program if the closure panics.
|
||||||
|
///
|
||||||
|
/// FIXME: Abort on panic means that any fatal error inside `visit_clobber` will abort the compiler.
|
||||||
|
/// Instead of aborting on catching a panic we need to reset the visited node to some valid but
|
||||||
|
/// possibly meaningless value and rethrow the panic.
|
||||||
//
|
//
|
||||||
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
|
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
|
||||||
pub fn visit_clobber<T, F>(t: &mut T, f: F)
|
pub fn visit_clobber<T, F>(t: &mut T, f: F)
|
||||||
|
@ -1105,36 +1109,11 @@ pub fn noop_visit_fn_header<T: MutVisitor>(header: &mut FnHeader, vis: &mut T) {
|
||||||
visit_unsafety(unsafety, vis);
|
visit_unsafety(unsafety, vis);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Avoid visiting the crate as a `Mod` item, flat map only the inner items if possible,
|
|
||||||
// or make crate visiting first class if necessary.
|
|
||||||
pub fn noop_visit_crate<T: MutVisitor>(krate: &mut Crate, vis: &mut T) {
|
pub fn noop_visit_crate<T: MutVisitor>(krate: &mut Crate, vis: &mut T) {
|
||||||
visit_clobber(krate, |Crate { attrs, items, span }| {
|
let Crate { attrs, items, span, is_placeholder: _ } = krate;
|
||||||
let item_vis =
|
visit_attrs(attrs, vis);
|
||||||
Visibility { kind: VisibilityKind::Public, span: span.shrink_to_lo(), tokens: None };
|
items.flat_map_in_place(|item| vis.flat_map_item(item));
|
||||||
let item = P(Item {
|
vis.visit_span(span);
|
||||||
ident: Ident::empty(),
|
|
||||||
attrs,
|
|
||||||
id: DUMMY_NODE_ID,
|
|
||||||
vis: item_vis,
|
|
||||||
span,
|
|
||||||
kind: ItemKind::Mod(Unsafe::No, ModKind::Loaded(items, Inline::Yes, span)),
|
|
||||||
tokens: None,
|
|
||||||
});
|
|
||||||
let items = vis.flat_map_item(item);
|
|
||||||
|
|
||||||
let len = items.len();
|
|
||||||
if len == 0 {
|
|
||||||
Crate { attrs: vec![], items: vec![], span }
|
|
||||||
} else if len == 1 {
|
|
||||||
let Item { attrs, span, kind, .. } = items.into_iter().next().unwrap().into_inner();
|
|
||||||
match kind {
|
|
||||||
ItemKind::Mod(_, ModKind::Loaded(items, ..)) => Crate { attrs, items, span },
|
|
||||||
_ => panic!("visitor converted a module to not a module"),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
panic!("a crate cannot expand to more than one item");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mutates one item into possibly many items.
|
// Mutates one item into possibly many items.
|
||||||
|
|
|
@ -211,6 +211,9 @@ pub trait Visitor<'ast>: Sized {
|
||||||
fn visit_pat_field(&mut self, fp: &'ast PatField) {
|
fn visit_pat_field(&mut self, fp: &'ast PatField) {
|
||||||
walk_pat_field(self, fp)
|
walk_pat_field(self, fp)
|
||||||
}
|
}
|
||||||
|
fn visit_crate(&mut self, krate: &'ast Crate) {
|
||||||
|
walk_crate(self, krate)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
|
|
@ -75,3 +75,12 @@ pub fn attribute_to_string(attr: &ast::Attribute) -> String {
|
||||||
pub fn to_string(f: impl FnOnce(&mut State<'_>)) -> String {
|
pub fn to_string(f: impl FnOnce(&mut State<'_>)) -> String {
|
||||||
State::new().to_string(f)
|
State::new().to_string(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn crate_to_string_for_macros(krate: &ast::Crate) -> String {
|
||||||
|
State::new().to_string(|s| {
|
||||||
|
s.print_inner_attributes(&krate.attrs);
|
||||||
|
for item in &krate.items {
|
||||||
|
s.print_item(item);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -77,6 +77,10 @@ fn flat_map_annotatable(
|
||||||
Annotatable::Param(param) => vis.flat_map_param(param).pop().map(Annotatable::Param),
|
Annotatable::Param(param) => vis.flat_map_param(param).pop().map(Annotatable::Param),
|
||||||
Annotatable::FieldDef(sf) => vis.flat_map_field_def(sf).pop().map(Annotatable::FieldDef),
|
Annotatable::FieldDef(sf) => vis.flat_map_field_def(sf).pop().map(Annotatable::FieldDef),
|
||||||
Annotatable::Variant(v) => vis.flat_map_variant(v).pop().map(Annotatable::Variant),
|
Annotatable::Variant(v) => vis.flat_map_variant(v).pop().map(Annotatable::Variant),
|
||||||
|
Annotatable::Crate(mut krate) => {
|
||||||
|
vis.visit_crate(&mut krate);
|
||||||
|
Some(Annotatable::Crate(krate))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,6 +105,7 @@ impl CfgFinder {
|
||||||
Annotatable::Param(param) => finder.visit_param(¶m),
|
Annotatable::Param(param) => finder.visit_param(¶m),
|
||||||
Annotatable::FieldDef(field) => finder.visit_field_def(&field),
|
Annotatable::FieldDef(field) => finder.visit_field_def(&field),
|
||||||
Annotatable::Variant(variant) => finder.visit_variant(&variant),
|
Annotatable::Variant(variant) => finder.visit_variant(&variant),
|
||||||
|
Annotatable::Crate(krate) => finder.visit_crate(krate),
|
||||||
};
|
};
|
||||||
finder.has_cfg_or_cfg_attr
|
finder.has_cfg_or_cfg_attr
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,9 +84,35 @@ struct TestHarnessGenerator<'a> {
|
||||||
tests: Vec<Test>,
|
tests: Vec<Test>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TestHarnessGenerator<'_> {
|
||||||
|
fn add_test_cases(&mut self, node_id: ast::NodeId, span: Span, prev_tests: Vec<Test>) {
|
||||||
|
let mut tests = mem::replace(&mut self.tests, prev_tests);
|
||||||
|
|
||||||
|
if !tests.is_empty() {
|
||||||
|
// Create an identifier that will hygienically resolve the test
|
||||||
|
// case name, even in another module.
|
||||||
|
let expn_id = self.cx.ext_cx.resolver.expansion_for_ast_pass(
|
||||||
|
span,
|
||||||
|
AstPass::TestHarness,
|
||||||
|
&[],
|
||||||
|
Some(node_id),
|
||||||
|
);
|
||||||
|
for test in &mut tests {
|
||||||
|
// See the comment on `mk_main` for why we're using
|
||||||
|
// `apply_mark` directly.
|
||||||
|
test.ident.span =
|
||||||
|
test.ident.span.apply_mark(expn_id.to_expn_id(), Transparency::Opaque);
|
||||||
|
}
|
||||||
|
self.cx.test_cases.extend(tests);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> MutVisitor for TestHarnessGenerator<'a> {
|
impl<'a> MutVisitor for TestHarnessGenerator<'a> {
|
||||||
fn visit_crate(&mut self, c: &mut ast::Crate) {
|
fn visit_crate(&mut self, c: &mut ast::Crate) {
|
||||||
|
let prev_tests = mem::take(&mut self.tests);
|
||||||
noop_visit_crate(c, self);
|
noop_visit_crate(c, self);
|
||||||
|
self.add_test_cases(ast::CRATE_NODE_ID, c.span, prev_tests);
|
||||||
|
|
||||||
// Create a main function to run our tests
|
// Create a main function to run our tests
|
||||||
c.items.push(mk_main(&mut self.cx));
|
c.items.push(mk_main(&mut self.cx));
|
||||||
|
@ -103,34 +129,10 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
|
||||||
|
|
||||||
// We don't want to recurse into anything other than mods, since
|
// We don't want to recurse into anything other than mods, since
|
||||||
// mods or tests inside of functions will break things
|
// mods or tests inside of functions will break things
|
||||||
if let ast::ItemKind::Mod(..) = item.kind {
|
if let ast::ItemKind::Mod(_, ModKind::Loaded(.., span)) = item.kind {
|
||||||
let tests = mem::take(&mut self.tests);
|
let prev_tests = mem::take(&mut self.tests);
|
||||||
noop_visit_item_kind(&mut item.kind, self);
|
noop_visit_item_kind(&mut item.kind, self);
|
||||||
let mut tests = mem::replace(&mut self.tests, tests);
|
self.add_test_cases(item.id, span, prev_tests);
|
||||||
|
|
||||||
if !tests.is_empty() {
|
|
||||||
let parent =
|
|
||||||
if item.id == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { item.id };
|
|
||||||
// Create an identifier that will hygienically resolve the test
|
|
||||||
// case name, even in another module.
|
|
||||||
let inner_span = match item.kind {
|
|
||||||
ast::ItemKind::Mod(_, ModKind::Loaded(.., span)) => span,
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
let expn_id = self.cx.ext_cx.resolver.expansion_for_ast_pass(
|
|
||||||
inner_span,
|
|
||||||
AstPass::TestHarness,
|
|
||||||
&[],
|
|
||||||
Some(parent),
|
|
||||||
);
|
|
||||||
for test in &mut tests {
|
|
||||||
// See the comment on `mk_main` for why we're using
|
|
||||||
// `apply_mark` directly.
|
|
||||||
test.ident.span =
|
|
||||||
test.ident.span.apply_mark(expn_id.to_expn_id(), Transparency::Opaque);
|
|
||||||
}
|
|
||||||
self.cx.test_cases.extend(tests);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
smallvec![P(item)]
|
smallvec![P(item)]
|
||||||
}
|
}
|
||||||
|
@ -146,7 +148,7 @@ fn entry_point_type(sess: &Session, item: &ast::Item, depth: usize) -> EntryPoin
|
||||||
} else if sess.contains_name(&item.attrs, sym::rustc_main) {
|
} else if sess.contains_name(&item.attrs, sym::rustc_main) {
|
||||||
EntryPointType::MainAttr
|
EntryPointType::MainAttr
|
||||||
} else if item.ident.name == sym::main {
|
} else if item.ident.name == sym::main {
|
||||||
if depth == 1 {
|
if depth == 0 {
|
||||||
// This is a top-level function so can be 'main'
|
// This is a top-level function so can be 'main'
|
||||||
EntryPointType::MainNamed
|
EntryPointType::MainNamed
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -48,6 +48,7 @@ pub enum Annotatable {
|
||||||
Param(ast::Param),
|
Param(ast::Param),
|
||||||
FieldDef(ast::FieldDef),
|
FieldDef(ast::FieldDef),
|
||||||
Variant(ast::Variant),
|
Variant(ast::Variant),
|
||||||
|
Crate(ast::Crate),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Annotatable {
|
impl Annotatable {
|
||||||
|
@ -66,6 +67,7 @@ impl Annotatable {
|
||||||
Annotatable::Param(ref p) => p.span,
|
Annotatable::Param(ref p) => p.span,
|
||||||
Annotatable::FieldDef(ref sf) => sf.span,
|
Annotatable::FieldDef(ref sf) => sf.span,
|
||||||
Annotatable::Variant(ref v) => v.span,
|
Annotatable::Variant(ref v) => v.span,
|
||||||
|
Annotatable::Crate(ref c) => c.span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +86,7 @@ impl Annotatable {
|
||||||
Annotatable::Param(p) => p.visit_attrs(f),
|
Annotatable::Param(p) => p.visit_attrs(f),
|
||||||
Annotatable::FieldDef(sf) => sf.visit_attrs(f),
|
Annotatable::FieldDef(sf) => sf.visit_attrs(f),
|
||||||
Annotatable::Variant(v) => v.visit_attrs(f),
|
Annotatable::Variant(v) => v.visit_attrs(f),
|
||||||
|
Annotatable::Crate(c) => c.visit_attrs(f),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +105,7 @@ impl Annotatable {
|
||||||
Annotatable::Param(p) => visitor.visit_param(p),
|
Annotatable::Param(p) => visitor.visit_param(p),
|
||||||
Annotatable::FieldDef(sf) => visitor.visit_field_def(sf),
|
Annotatable::FieldDef(sf) => visitor.visit_field_def(sf),
|
||||||
Annotatable::Variant(v) => visitor.visit_variant(v),
|
Annotatable::Variant(v) => visitor.visit_variant(v),
|
||||||
|
Annotatable::Crate(c) => visitor.visit_crate(c),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +126,8 @@ impl Annotatable {
|
||||||
| Annotatable::GenericParam(..)
|
| Annotatable::GenericParam(..)
|
||||||
| Annotatable::Param(..)
|
| Annotatable::Param(..)
|
||||||
| Annotatable::FieldDef(..)
|
| Annotatable::FieldDef(..)
|
||||||
| Annotatable::Variant(..) => panic!("unexpected annotatable"),
|
| Annotatable::Variant(..)
|
||||||
|
| Annotatable::Crate(..) => panic!("unexpected annotatable"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,6 +225,13 @@ impl Annotatable {
|
||||||
_ => panic!("expected variant"),
|
_ => panic!("expected variant"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn expect_crate(self) -> ast::Crate {
|
||||||
|
match self {
|
||||||
|
Annotatable::Crate(krate) => krate,
|
||||||
|
_ => panic!("expected krate"),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Result of an expansion that may need to be retried.
|
/// Result of an expansion that may need to be retried.
|
||||||
|
@ -419,6 +431,11 @@ pub trait MacResult {
|
||||||
fn make_variants(self: Box<Self>) -> Option<SmallVec<[ast::Variant; 1]>> {
|
fn make_variants(self: Box<Self>) -> Option<SmallVec<[ast::Variant; 1]>> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_crate(self: Box<Self>) -> Option<ast::Crate> {
|
||||||
|
// Fn-like macros cannot produce a crate.
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! make_MacEager {
|
macro_rules! make_MacEager {
|
||||||
|
|
|
@ -14,13 +14,13 @@ use rustc_ast::tokenstream::TokenStream;
|
||||||
use rustc_ast::visit::{self, AssocCtxt, Visitor};
|
use rustc_ast::visit::{self, AssocCtxt, Visitor};
|
||||||
use rustc_ast::{AstLike, Block, Inline, ItemKind, MacArgs, MacCall};
|
use rustc_ast::{AstLike, Block, Inline, ItemKind, MacArgs, MacCall};
|
||||||
use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem};
|
use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem};
|
||||||
use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe};
|
use rustc_ast::{NodeId, PatKind, Path, StmtKind};
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_attr::is_builtin_attr;
|
use rustc_attr::is_builtin_attr;
|
||||||
use rustc_data_structures::map_in_place::MapInPlace;
|
use rustc_data_structures::map_in_place::MapInPlace;
|
||||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_errors::{Applicability, FatalError, PResult};
|
use rustc_errors::{Applicability, PResult};
|
||||||
use rustc_feature::Features;
|
use rustc_feature::Features;
|
||||||
use rustc_parse::parser::{
|
use rustc_parse::parser::{
|
||||||
AttemptLocalParseRecovery, ForceCollect, Parser, RecoverColon, RecoverComma,
|
AttemptLocalParseRecovery, ForceCollect, Parser, RecoverColon, RecoverComma,
|
||||||
|
@ -33,7 +33,7 @@ use rustc_session::Limit;
|
||||||
use rustc_span::symbol::{sym, Ident};
|
use rustc_span::symbol::{sym, Ident};
|
||||||
use rustc_span::{FileName, LocalExpnId, Span};
|
use rustc_span::{FileName, LocalExpnId, Span};
|
||||||
|
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::SmallVec;
|
||||||
use std::ops::DerefMut;
|
use std::ops::DerefMut;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -205,6 +205,7 @@ ast_fragments! {
|
||||||
Variants(SmallVec<[ast::Variant; 1]>) {
|
Variants(SmallVec<[ast::Variant; 1]>) {
|
||||||
"variant"; many fn flat_map_variant; fn visit_variant(); fn make_variants;
|
"variant"; many fn flat_map_variant; fn visit_variant(); fn make_variants;
|
||||||
}
|
}
|
||||||
|
Crate(ast::Crate) { "crate"; one fn visit_crate; fn visit_crate; fn make_crate; }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum SupportsMacroExpansion {
|
pub enum SupportsMacroExpansion {
|
||||||
|
@ -227,9 +228,8 @@ impl AstFragmentKind {
|
||||||
AstFragmentKind::Items
|
AstFragmentKind::Items
|
||||||
| AstFragmentKind::TraitItems
|
| AstFragmentKind::TraitItems
|
||||||
| AstFragmentKind::ImplItems
|
| AstFragmentKind::ImplItems
|
||||||
| AstFragmentKind::ForeignItems => {
|
| AstFragmentKind::ForeignItems
|
||||||
SupportsMacroExpansion::Yes { supports_inner_attrs: true }
|
| AstFragmentKind::Crate => SupportsMacroExpansion::Yes { supports_inner_attrs: true },
|
||||||
}
|
|
||||||
AstFragmentKind::Arms
|
AstFragmentKind::Arms
|
||||||
| AstFragmentKind::Fields
|
| AstFragmentKind::Fields
|
||||||
| AstFragmentKind::FieldPats
|
| AstFragmentKind::FieldPats
|
||||||
|
@ -288,6 +288,9 @@ impl AstFragmentKind {
|
||||||
AstFragmentKind::OptExpr => {
|
AstFragmentKind::OptExpr => {
|
||||||
AstFragment::OptExpr(items.next().map(Annotatable::expect_expr))
|
AstFragment::OptExpr(items.next().map(Annotatable::expect_expr))
|
||||||
}
|
}
|
||||||
|
AstFragmentKind::Crate => {
|
||||||
|
AstFragment::Crate(items.next().expect("expected exactly one crate").expect_crate())
|
||||||
|
}
|
||||||
AstFragmentKind::Pat | AstFragmentKind::Ty => {
|
AstFragmentKind::Pat | AstFragmentKind::Ty => {
|
||||||
panic!("patterns and types aren't annotatable")
|
panic!("patterns and types aren't annotatable")
|
||||||
}
|
}
|
||||||
|
@ -359,9 +362,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
MacroExpander { cx, monotonic }
|
MacroExpander { cx, monotonic }
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Avoid visiting the crate as a `Mod` item,
|
pub fn expand_crate(&mut self, krate: ast::Crate) -> ast::Crate {
|
||||||
// make crate a first class expansion target instead.
|
|
||||||
pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
|
|
||||||
let file_path = match self.cx.source_map().span_to_filename(krate.span) {
|
let file_path = match self.cx.source_map().span_to_filename(krate.span) {
|
||||||
FileName::Real(name) => name
|
FileName::Real(name) => name
|
||||||
.into_local_path()
|
.into_local_path()
|
||||||
|
@ -375,52 +376,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
file_path_stack: vec![file_path],
|
file_path_stack: vec![file_path],
|
||||||
dir_path,
|
dir_path,
|
||||||
});
|
});
|
||||||
|
let krate = self.fully_expand_fragment(AstFragment::Crate(krate)).make_crate();
|
||||||
let krate_item = AstFragment::Items(smallvec![P(ast::Item {
|
|
||||||
attrs: krate.attrs,
|
|
||||||
span: krate.span,
|
|
||||||
kind: ast::ItemKind::Mod(
|
|
||||||
Unsafe::No,
|
|
||||||
ModKind::Loaded(krate.items, Inline::Yes, krate.span)
|
|
||||||
),
|
|
||||||
ident: Ident::empty(),
|
|
||||||
id: ast::DUMMY_NODE_ID,
|
|
||||||
vis: ast::Visibility {
|
|
||||||
span: krate.span.shrink_to_lo(),
|
|
||||||
kind: ast::VisibilityKind::Public,
|
|
||||||
tokens: None,
|
|
||||||
},
|
|
||||||
tokens: None,
|
|
||||||
})]);
|
|
||||||
|
|
||||||
match self.fully_expand_fragment(krate_item).make_items().pop().map(P::into_inner) {
|
|
||||||
Some(ast::Item {
|
|
||||||
attrs,
|
|
||||||
kind: ast::ItemKind::Mod(_, ModKind::Loaded(items, ..)),
|
|
||||||
..
|
|
||||||
}) => {
|
|
||||||
krate.attrs = attrs;
|
|
||||||
krate.items = items;
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
// Resolution failed so we return an empty expansion
|
|
||||||
krate.attrs = vec![];
|
|
||||||
krate.items = vec![];
|
|
||||||
}
|
|
||||||
Some(ast::Item { span, kind, .. }) => {
|
|
||||||
krate.attrs = vec![];
|
|
||||||
krate.items = vec![];
|
|
||||||
self.cx.span_err(
|
|
||||||
span,
|
|
||||||
&format!(
|
|
||||||
"expected crate top-level item to be a module after macro expansion, found {} {}",
|
|
||||||
kind.article(), kind.descr()
|
|
||||||
),
|
|
||||||
);
|
|
||||||
// FIXME: this workaround issue #84569
|
|
||||||
FatalError.raise();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
self.cx.trace_macros_diag();
|
self.cx.trace_macros_diag();
|
||||||
krate
|
krate
|
||||||
}
|
}
|
||||||
|
@ -708,26 +664,32 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
SyntaxExtensionKind::Attr(expander) => {
|
SyntaxExtensionKind::Attr(expander) => {
|
||||||
self.gate_proc_macro_input(&item);
|
self.gate_proc_macro_input(&item);
|
||||||
self.gate_proc_macro_attr_item(span, &item);
|
self.gate_proc_macro_attr_item(span, &item);
|
||||||
let mut fake_tokens = false;
|
let tokens = match &item {
|
||||||
if let Annotatable::Item(item_inner) = &item {
|
// FIXME: Collect tokens and use them instead of generating
|
||||||
if let ItemKind::Mod(_, mod_kind) = &item_inner.kind {
|
// fake ones. These are unstable, so it needs to be
|
||||||
// FIXME: Collect tokens and use them instead of generating
|
// fixed prior to stabilization
|
||||||
// fake ones. These are unstable, so it needs to be
|
// Fake tokens when we are invoking an inner attribute, and
|
||||||
// fixed prior to stabilization
|
// we are invoking it on an out-of-line module or crate.
|
||||||
// Fake tokens when we are invoking an inner attribute, and:
|
Annotatable::Crate(krate) => rustc_parse::fake_token_stream_for_crate(
|
||||||
fake_tokens = matches!(attr.style, ast::AttrStyle::Inner) &&
|
|
||||||
// We are invoking an attribute on the crate root, or an outline
|
|
||||||
// module
|
|
||||||
(item_inner.ident.name.is_empty() || !matches!(mod_kind, ast::ModKind::Loaded(_, Inline::Yes, _)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let tokens = if fake_tokens {
|
|
||||||
rustc_parse::fake_token_stream(
|
|
||||||
&self.cx.sess.parse_sess,
|
&self.cx.sess.parse_sess,
|
||||||
&item.into_nonterminal(),
|
krate,
|
||||||
)
|
),
|
||||||
} else {
|
Annotatable::Item(item_inner)
|
||||||
item.into_tokens(&self.cx.sess.parse_sess)
|
if matches!(attr.style, ast::AttrStyle::Inner)
|
||||||
|
&& matches!(
|
||||||
|
item_inner.kind,
|
||||||
|
ItemKind::Mod(
|
||||||
|
_,
|
||||||
|
ModKind::Unloaded | ModKind::Loaded(_, Inline::No, _),
|
||||||
|
)
|
||||||
|
) =>
|
||||||
|
{
|
||||||
|
rustc_parse::fake_token_stream(
|
||||||
|
&self.cx.sess.parse_sess,
|
||||||
|
&item.into_nonterminal(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => item.into_tokens(&self.cx.sess.parse_sess),
|
||||||
};
|
};
|
||||||
let attr_item = attr.unwrap_normal_item();
|
let attr_item = attr.unwrap_normal_item();
|
||||||
if let MacArgs::Eq(..) = attr_item.args {
|
if let MacArgs::Eq(..) = attr_item.args {
|
||||||
|
@ -804,7 +766,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
Annotatable::Item(_)
|
Annotatable::Item(_)
|
||||||
| Annotatable::TraitItem(_)
|
| Annotatable::TraitItem(_)
|
||||||
| Annotatable::ImplItem(_)
|
| Annotatable::ImplItem(_)
|
||||||
| Annotatable::ForeignItem(_) => return,
|
| Annotatable::ForeignItem(_)
|
||||||
|
| Annotatable::Crate(..) => return,
|
||||||
Annotatable::Stmt(stmt) => {
|
Annotatable::Stmt(stmt) => {
|
||||||
// Attributes are stable on item statements,
|
// Attributes are stable on item statements,
|
||||||
// but unstable on all other kinds of statements
|
// but unstable on all other kinds of statements
|
||||||
|
@ -949,6 +912,7 @@ pub fn parse_ast_fragment<'a>(
|
||||||
RecoverComma::No,
|
RecoverComma::No,
|
||||||
RecoverColon::Yes,
|
RecoverColon::Yes,
|
||||||
)?),
|
)?),
|
||||||
|
AstFragmentKind::Crate => AstFragment::Crate(this.parse_crate_mod()?),
|
||||||
AstFragmentKind::Arms
|
AstFragmentKind::Arms
|
||||||
| AstFragmentKind::Fields
|
| AstFragmentKind::Fields
|
||||||
| AstFragmentKind::FieldPats
|
| AstFragmentKind::FieldPats
|
||||||
|
@ -1195,6 +1159,30 @@ macro_rules! assign_id {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
||||||
|
fn visit_crate(&mut self, krate: &mut ast::Crate) {
|
||||||
|
let span = krate.span;
|
||||||
|
let empty_crate =
|
||||||
|
|| ast::Crate { attrs: Vec::new(), items: Vec::new(), span, is_placeholder: None };
|
||||||
|
let mut fold_crate = |krate: ast::Crate| {
|
||||||
|
let mut krate = match self.configure(krate) {
|
||||||
|
Some(krate) => krate,
|
||||||
|
None => return empty_crate(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(attr) = self.take_first_attr(&mut krate) {
|
||||||
|
return self
|
||||||
|
.collect_attr(attr, Annotatable::Crate(krate), AstFragmentKind::Crate)
|
||||||
|
.make_crate();
|
||||||
|
}
|
||||||
|
|
||||||
|
noop_visit_crate(&mut krate, self);
|
||||||
|
krate
|
||||||
|
};
|
||||||
|
|
||||||
|
// Cannot use `visit_clobber` here, see the FIXME on it.
|
||||||
|
*krate = fold_crate(mem::replace(krate, empty_crate()));
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
|
fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
|
||||||
self.cfg.configure_expr(expr);
|
self.cfg.configure_expr(expr);
|
||||||
visit_clobber(expr.deref_mut(), |mut expr| {
|
visit_clobber(expr.deref_mut(), |mut expr| {
|
||||||
|
|
|
@ -46,6 +46,12 @@ pub fn placeholder(
|
||||||
|| P(ast::Pat { id, kind: ast::PatKind::MacCall(mac_placeholder()), span, tokens: None });
|
|| P(ast::Pat { id, kind: ast::PatKind::MacCall(mac_placeholder()), span, tokens: None });
|
||||||
|
|
||||||
match kind {
|
match kind {
|
||||||
|
AstFragmentKind::Crate => AstFragment::Crate(ast::Crate {
|
||||||
|
attrs: Default::default(),
|
||||||
|
items: Default::default(),
|
||||||
|
span,
|
||||||
|
is_placeholder: Some(id),
|
||||||
|
}),
|
||||||
AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
|
AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
|
||||||
AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())),
|
AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())),
|
||||||
AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item {
|
AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item {
|
||||||
|
@ -354,4 +360,12 @@ impl MutVisitor for PlaceholderExpander {
|
||||||
_ => noop_visit_ty(ty, self),
|
_ => noop_visit_ty(ty, self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_crate(&mut self, krate: &mut ast::Crate) {
|
||||||
|
if let Some(id) = krate.is_placeholder {
|
||||||
|
*krate = self.remove(id).make_crate();
|
||||||
|
} else {
|
||||||
|
noop_visit_crate(krate, self)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -323,7 +323,7 @@ pub fn configure_and_expand(
|
||||||
|
|
||||||
let crate_attrs = krate.attrs.clone();
|
let crate_attrs = krate.attrs.clone();
|
||||||
let extern_mod_loaded = |ident: Ident, attrs, items, span| {
|
let extern_mod_loaded = |ident: Ident, attrs, items, span| {
|
||||||
let krate = ast::Crate { attrs, items, span };
|
let krate = ast::Crate { attrs, items, span, is_placeholder: None };
|
||||||
pre_expansion_lint(sess, lint_store, &krate, &crate_attrs, &ident.name.as_str());
|
pre_expansion_lint(sess, lint_store, &krate, &crate_attrs, &ident.name.as_str());
|
||||||
(krate.attrs, krate.items)
|
(krate.attrs, krate.items)
|
||||||
};
|
};
|
||||||
|
|
|
@ -326,6 +326,12 @@ pub fn fake_token_stream(sess: &ParseSess, nt: &Nonterminal) -> TokenStream {
|
||||||
parse_stream_from_source_str(filename, source, sess, Some(nt.span()))
|
parse_stream_from_source_str(filename, source, sess, Some(nt.span()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn fake_token_stream_for_crate(sess: &ParseSess, krate: &ast::Crate) -> TokenStream {
|
||||||
|
let source = pprust::crate_to_string_for_macros(krate);
|
||||||
|
let filename = FileName::macro_expansion_source_code(&source);
|
||||||
|
parse_stream_from_source_str(filename, source, sess, Some(krate.span))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse_cfg_attr(
|
pub fn parse_cfg_attr(
|
||||||
attr: &Attribute,
|
attr: &Attribute,
|
||||||
parse_sess: &ParseSess,
|
parse_sess: &ParseSess,
|
||||||
|
|
|
@ -26,7 +26,7 @@ impl<'a> Parser<'a> {
|
||||||
/// Parses a source module as a crate. This is the main entry point for the parser.
|
/// Parses a source module as a crate. This is the main entry point for the parser.
|
||||||
pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> {
|
pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> {
|
||||||
let (attrs, items, span) = self.parse_mod(&token::Eof)?;
|
let (attrs, items, span) = self.parse_mod(&token::Eof)?;
|
||||||
Ok(ast::Crate { attrs, items, span })
|
Ok(ast::Crate { attrs, items, span, is_placeholder: None })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a `mod <foo> { ... }` or `mod <foo>;` item.
|
/// Parses a `mod <foo> { ... }` or `mod <foo>;` item.
|
||||||
|
|
|
@ -651,11 +651,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
||||||
|
|
||||||
/// Constructs the reduced graph for one item.
|
/// Constructs the reduced graph for one item.
|
||||||
fn build_reduced_graph_for_item(&mut self, item: &'b Item) {
|
fn build_reduced_graph_for_item(&mut self, item: &'b Item) {
|
||||||
if matches!(item.kind, ItemKind::Mod(..)) && item.ident.name == kw::Empty {
|
|
||||||
// Fake crate root item from expand.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let parent_scope = &self.parent_scope;
|
let parent_scope = &self.parent_scope;
|
||||||
let parent = parent_scope.module;
|
let parent = parent_scope.module;
|
||||||
let expansion = parent_scope.expansion;
|
let expansion = parent_scope.expansion;
|
||||||
|
@ -1499,4 +1494,13 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
|
||||||
|
|
||||||
visit::walk_variant(self, variant);
|
visit::walk_variant(self, variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_crate(&mut self, krate: &'b ast::Crate) {
|
||||||
|
if let Some(id) = krate.is_placeholder {
|
||||||
|
self.visit_invoc_in_module(id);
|
||||||
|
} else {
|
||||||
|
visit::walk_crate(self, krate);
|
||||||
|
self.contains_macro_use(&krate.attrs);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use rustc_expand::expand::AstFragment;
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_hir::definitions::*;
|
use rustc_hir::definitions::*;
|
||||||
use rustc_span::hygiene::LocalExpnId;
|
use rustc_span::hygiene::LocalExpnId;
|
||||||
use rustc_span::symbol::{kw, sym};
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
|
@ -92,10 +92,6 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
|
||||||
// information we encapsulate into, the better
|
// information we encapsulate into, the better
|
||||||
let def_data = match &i.kind {
|
let def_data = match &i.kind {
|
||||||
ItemKind::Impl { .. } => DefPathData::Impl,
|
ItemKind::Impl { .. } => DefPathData::Impl,
|
||||||
ItemKind::Mod(..) if i.ident.name == kw::Empty => {
|
|
||||||
// Fake crate root item from expand.
|
|
||||||
return visit::walk_item(self, i);
|
|
||||||
}
|
|
||||||
ItemKind::Mod(..)
|
ItemKind::Mod(..)
|
||||||
| ItemKind::Trait(..)
|
| ItemKind::Trait(..)
|
||||||
| ItemKind::TraitAlias(..)
|
| ItemKind::TraitAlias(..)
|
||||||
|
@ -346,4 +342,12 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
|
||||||
fn visit_field_def(&mut self, field: &'a FieldDef) {
|
fn visit_field_def(&mut self, field: &'a FieldDef) {
|
||||||
self.collect_field(field, None);
|
self.collect_field(field, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_crate(&mut self, krate: &'a Crate) {
|
||||||
|
if let Some(id) = krate.is_placeholder {
|
||||||
|
self.visit_macro_invoc(id)
|
||||||
|
} else {
|
||||||
|
visit::walk_crate(self, krate)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"span":{"lo":0,"hi":0}}
|
{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"span":{"lo":0,"hi":0},"is_placeholder":null}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"rust_2015","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"span":{"lo":0,"hi":0}}
|
{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"rust_2015","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"span":{"lo":0,"hi":0},"is_placeholder":null}
|
||||||
|
|
14
src/test/ui/proc-macro/crate-attrs-multiple.rs
Normal file
14
src/test/ui/proc-macro/crate-attrs-multiple.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// Multiple custom crate-level attributes, both inert and active.
|
||||||
|
|
||||||
|
// check-pass
|
||||||
|
// aux-crate:test_macros=test-macros.rs
|
||||||
|
|
||||||
|
#![feature(custom_inner_attributes)]
|
||||||
|
#![feature(prelude_import)]
|
||||||
|
|
||||||
|
#![test_macros::identity_attr]
|
||||||
|
#![rustfmt::skip]
|
||||||
|
#![test_macros::identity_attr]
|
||||||
|
#![rustfmt::skip]
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -1,7 +1,10 @@
|
||||||
// edition:2018
|
|
||||||
// aux-crate:issue_59191=issue-59191.rs
|
|
||||||
// Test that using a macro to replace the entire crate tree with a non-'mod' item errors out nicely.
|
// Test that using a macro to replace the entire crate tree with a non-'mod' item errors out nicely.
|
||||||
// `issue_59191::no_main` replaces whatever's passed in with `fn main() {}`.
|
// `issue_59191::no_main` replaces whatever's passed in with `fn main() {}`.
|
||||||
|
|
||||||
|
// edition:2018
|
||||||
|
// aux-crate:issue_59191=issue-59191.rs
|
||||||
|
// error-pattern: requires `sized` lang_item
|
||||||
|
|
||||||
#![feature(custom_inner_attributes)]
|
#![feature(custom_inner_attributes)]
|
||||||
#![issue_59191::no_main]
|
#![issue_59191::no_main]
|
||||||
//~^ ERROR expected crate top-level item to be a module after macro expansion, found a function
|
#![issue_59191::no_main]
|
||||||
|
|
|
@ -1,10 +1,4 @@
|
||||||
error: expected crate top-level item to be a module after macro expansion, found a function
|
error: requires `sized` lang_item
|
||||||
--> $DIR/issue-59191-replace-root-with-fn.rs:6:1
|
|
||||||
|
|
|
||||||
LL | #![issue_59191::no_main]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: this error originates in the attribute macro `issue_59191::no_main` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue