Remove pretty-print/reparse hack, and add derive-specific hack
This commit is contained in:
parent
2987785df3
commit
530a629635
8 changed files with 186 additions and 410 deletions
|
@ -2,8 +2,8 @@ use crate::expand::{self, AstFragment, Invocation};
|
|||
use crate::module::DirectoryOwnership;
|
||||
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::token::{self, Nonterminal};
|
||||
use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, TokenStream};
|
||||
use rustc_ast::visit::{AssocCtxt, Visitor};
|
||||
use rustc_ast::{self as ast, Attribute, NodeId, PatKind};
|
||||
use rustc_attr::{self as attr, Deprecation, HasAttrs, Stability};
|
||||
|
@ -119,8 +119,8 @@ impl Annotatable {
|
|||
}
|
||||
}
|
||||
|
||||
crate fn into_tokens(self, sess: &ParseSess) -> TokenStream {
|
||||
let nt = match self {
|
||||
crate fn into_nonterminal(self) -> Nonterminal {
|
||||
match self {
|
||||
Annotatable::Item(item) => token::NtItem(item),
|
||||
Annotatable::TraitItem(item) | Annotatable::ImplItem(item) => {
|
||||
token::NtItem(P(item.and_then(ast::AssocItem::into_item)))
|
||||
|
@ -137,8 +137,11 @@ impl Annotatable {
|
|||
| Annotatable::Param(..)
|
||||
| Annotatable::StructField(..)
|
||||
| Annotatable::Variant(..) => panic!("unexpected annotatable"),
|
||||
};
|
||||
nt_to_tokenstream(&nt, sess, DUMMY_SP)
|
||||
}
|
||||
}
|
||||
|
||||
crate fn into_tokens(self, sess: &ParseSess) -> TokenStream {
|
||||
nt_to_tokenstream(&self.into_nonterminal(), sess, DUMMY_SP, CanSynthesizeMissingTokens::No)
|
||||
}
|
||||
|
||||
pub fn expect_item(self) -> P<ast::Item> {
|
||||
|
|
|
@ -29,6 +29,7 @@ use smallvec::SmallVec;
|
|||
pub struct StripUnconfigured<'a> {
|
||||
pub sess: &'a Session,
|
||||
pub features: Option<&'a Features>,
|
||||
pub modified: bool,
|
||||
}
|
||||
|
||||
fn get_features(
|
||||
|
@ -199,7 +200,7 @@ fn get_features(
|
|||
|
||||
// `cfg_attr`-process the crate's attributes and compute the crate's features.
|
||||
pub fn features(sess: &Session, mut krate: ast::Crate) -> (ast::Crate, Features) {
|
||||
let mut strip_unconfigured = StripUnconfigured { sess, features: None };
|
||||
let mut strip_unconfigured = StripUnconfigured { sess, features: None, modified: false };
|
||||
|
||||
let unconfigured_attrs = krate.attrs.clone();
|
||||
let diag = &sess.parse_sess.span_diagnostic;
|
||||
|
@ -243,7 +244,12 @@ const CFG_ATTR_NOTE_REF: &str = "for more information, visit \
|
|||
impl<'a> StripUnconfigured<'a> {
|
||||
pub fn configure<T: HasAttrs>(&mut self, mut node: T) -> Option<T> {
|
||||
self.process_cfg_attrs(&mut node);
|
||||
self.in_cfg(node.attrs()).then_some(node)
|
||||
if self.in_cfg(node.attrs()) {
|
||||
Some(node)
|
||||
} else {
|
||||
self.modified = true;
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse and expand all `cfg_attr` attributes into a list of attributes
|
||||
|
@ -270,6 +276,9 @@ impl<'a> StripUnconfigured<'a> {
|
|||
return vec![attr];
|
||||
}
|
||||
|
||||
// A `#[cfg_attr]` either gets removed, or replaced with a new attribute
|
||||
self.modified = true;
|
||||
|
||||
let (cfg_predicate, expanded_attrs) = match self.parse_cfg_attr(&attr) {
|
||||
None => return vec![],
|
||||
Some(r) => r,
|
||||
|
|
|
@ -12,7 +12,7 @@ use rustc_ast::ptr::P;
|
|||
use rustc_ast::token;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::visit::{self, AssocCtxt, Visitor};
|
||||
use rustc_ast::{self as ast, AttrItem, Block, LitKind, NodeId, PatKind, Path};
|
||||
use rustc_ast::{self as ast, AttrItem, AttrStyle, Block, LitKind, NodeId, PatKind, Path};
|
||||
use rustc_ast::{ItemKind, MacArgs, MacCallStmt, MacStmtStyle, StmtKind, Unsafe};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_attr::{self as attr, is_builtin_attr, HasAttrs};
|
||||
|
@ -522,12 +522,29 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
item.visit_attrs(|attrs| attrs.retain(|a| !a.has_name(sym::derive)));
|
||||
(item, Vec::new())
|
||||
} else {
|
||||
let mut item = StripUnconfigured {
|
||||
let mut visitor = StripUnconfigured {
|
||||
sess: self.cx.sess,
|
||||
features: self.cx.ecfg.features,
|
||||
}
|
||||
.fully_configure(item);
|
||||
modified: false,
|
||||
};
|
||||
let mut item = visitor.fully_configure(item);
|
||||
item.visit_attrs(|attrs| attrs.retain(|a| !a.has_name(sym::derive)));
|
||||
if visitor.modified && !derives.is_empty() {
|
||||
// Erase the tokens if cfg-stripping modified the item
|
||||
// This will cause us to synthesize fake tokens
|
||||
// when `nt_to_tokenstream` is called on this item.
|
||||
match &mut item {
|
||||
Annotatable::Item(item) => item.tokens = None,
|
||||
Annotatable::Stmt(stmt) => {
|
||||
if let StmtKind::Item(item) = &mut stmt.kind {
|
||||
item.tokens = None
|
||||
} else {
|
||||
panic!("Unexpected stmt {:?}", stmt);
|
||||
}
|
||||
}
|
||||
_ => panic!("Unexpected annotatable {:?}", item),
|
||||
}
|
||||
}
|
||||
|
||||
invocations.reserve(derives.len());
|
||||
let derive_placeholders = derives
|
||||
|
@ -622,7 +639,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
|
||||
let invocations = {
|
||||
let mut collector = InvocationCollector {
|
||||
cfg: StripUnconfigured { sess: &self.cx.sess, features: self.cx.ecfg.features },
|
||||
cfg: StripUnconfigured {
|
||||
sess: &self.cx.sess,
|
||||
features: self.cx.ecfg.features,
|
||||
modified: false,
|
||||
},
|
||||
cx: self.cx,
|
||||
invocations: Vec::new(),
|
||||
monotonic: self.monotonic,
|
||||
|
@ -716,7 +737,15 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
SyntaxExtensionKind::Attr(expander) => {
|
||||
self.gate_proc_macro_input(&item);
|
||||
self.gate_proc_macro_attr_item(span, &item);
|
||||
let tokens = item.into_tokens(&self.cx.sess.parse_sess);
|
||||
let tokens = match attr.style {
|
||||
AttrStyle::Outer => item.into_tokens(&self.cx.sess.parse_sess),
|
||||
// FIXME: Properly collect tokens for inner attributes
|
||||
AttrStyle::Inner => rustc_parse::fake_token_stream(
|
||||
&self.cx.sess.parse_sess,
|
||||
&item.into_nonterminal(),
|
||||
span,
|
||||
),
|
||||
};
|
||||
let attr_item = attr.unwrap_normal_item();
|
||||
if let MacArgs::Eq(..) = attr_item.args {
|
||||
self.cx.span_err(span, "key-value macro attributes are not supported");
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::proc_macro_server;
|
|||
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token;
|
||||
use rustc_ast::tokenstream::{TokenStream, TokenTree};
|
||||
use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, TokenStream, TokenTree};
|
||||
use rustc_ast::{self as ast, *};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::{struct_span_err, Applicability, ErrorReported};
|
||||
|
@ -94,7 +94,12 @@ impl MultiItemModifier for ProcMacroDerive {
|
|||
let input = if item.pretty_printing_compatibility_hack() {
|
||||
TokenTree::token(token::Interpolated(Lrc::new(item)), DUMMY_SP).into()
|
||||
} else {
|
||||
nt_to_tokenstream(&item, &ecx.sess.parse_sess, DUMMY_SP)
|
||||
nt_to_tokenstream(
|
||||
&item,
|
||||
&ecx.sess.parse_sess,
|
||||
DUMMY_SP,
|
||||
CanSynthesizeMissingTokens::Yes,
|
||||
)
|
||||
};
|
||||
|
||||
let server = proc_macro_server::Rustc::new(ecx);
|
||||
|
|
|
@ -2,7 +2,8 @@ use crate::base::ExtCtxt;
|
|||
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::token;
|
||||
use rustc_ast::tokenstream::{self, DelimSpan, Spacing::*, TokenStream, TreeAndSpacing};
|
||||
use rustc_ast::tokenstream::{self, CanSynthesizeMissingTokens};
|
||||
use rustc_ast::tokenstream::{DelimSpan, Spacing::*, TokenStream, TreeAndSpacing};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::Diagnostic;
|
||||
|
@ -178,7 +179,7 @@ impl FromInternal<(TreeAndSpacing, &'_ ParseSess, &'_ mut Vec<Self>)>
|
|||
{
|
||||
TokenTree::Ident(Ident::new(sess, name.name, is_raw, name.span))
|
||||
} else {
|
||||
let stream = nt_to_tokenstream(&nt, sess, span);
|
||||
let stream = nt_to_tokenstream(&nt, sess, span, CanSynthesizeMissingTokens::No);
|
||||
TokenTree::Group(Group {
|
||||
delimiter: Delimiter::None,
|
||||
stream,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue