1 use crate::base::{self, *};
2 use crate::proc_macro_server;
7 use rustc_ast::tokenstream::{TokenStream, TokenTree};
8 use rustc_data_structures::sync::Lrc;
9 use rustc_errors::ErrorGuaranteed;
10 use rustc_parse::parser::ForceCollect;
11 use rustc_span::profiling::SpannedEventArgRecorder;
12 use rustc_span::{Span, DUMMY_SP};
14 const EXEC_STRATEGY: pm::bridge::server::SameThread = pm::bridge::server::SameThread;
16 pub struct BangProcMacro {
17 pub client: pm::bridge::client::Client<pm::TokenStream, pm::TokenStream>,
20 impl base::BangProcMacro for BangProcMacro {
23 ecx: &'cx mut ExtCtxt<'_>,
26 ) -> Result<TokenStream, ErrorGuaranteed> {
28 ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| {
29 recorder.record_arg_with_span(ecx.expansion_descr(), span);
32 let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
33 let server = proc_macro_server::Rustc::new(ecx);
34 self.client.run(&EXEC_STRATEGY, server, input, proc_macro_backtrace).map_err(|e| {
35 let mut err = ecx.struct_span_err(span, "proc macro panicked");
36 if let Some(s) = e.as_str() {
37 err.help(&format!("message: {}", s));
44 pub struct AttrProcMacro {
45 pub client: pm::bridge::client::Client<(pm::TokenStream, pm::TokenStream), pm::TokenStream>,
48 impl base::AttrProcMacro for AttrProcMacro {
51 ecx: &'cx mut ExtCtxt<'_>,
53 annotation: TokenStream,
54 annotated: TokenStream,
55 ) -> Result<TokenStream, ErrorGuaranteed> {
57 ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| {
58 recorder.record_arg_with_span(ecx.expansion_descr(), span);
61 let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
62 let server = proc_macro_server::Rustc::new(ecx);
64 .run(&EXEC_STRATEGY, server, annotation, annotated, proc_macro_backtrace)
66 let mut err = ecx.struct_span_err(span, "custom attribute panicked");
67 if let Some(s) = e.as_str() {
68 err.help(&format!("message: {}", s));
75 pub struct DeriveProcMacro {
76 pub client: pm::bridge::client::Client<pm::TokenStream, pm::TokenStream>,
79 impl MultiItemModifier for DeriveProcMacro {
82 ecx: &mut ExtCtxt<'_>,
84 _meta_item: &ast::MetaItem,
86 ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
87 // We need special handling for statement items
88 // (e.g. `fn foo() { #[derive(Debug)] struct Bar; }`)
89 let is_stmt = matches!(item, Annotatable::Stmt(..));
90 let hack = crate::base::ann_pretty_printing_compatibility_hack(&item, &ecx.sess.parse_sess);
93 Annotatable::Item(item) => token::NtItem(item),
94 Annotatable::Stmt(stmt) => token::NtStmt(stmt),
97 TokenTree::token(token::Interpolated(Lrc::new(nt)), DUMMY_SP).into()
104 ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| {
105 recorder.record_arg_with_span(ecx.expansion_descr(), span);
107 let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
108 let server = proc_macro_server::Rustc::new(ecx);
109 match self.client.run(&EXEC_STRATEGY, server, input, proc_macro_backtrace) {
110 Ok(stream) => stream,
112 let mut err = ecx.struct_span_err(span, "proc-macro derive panicked");
113 if let Some(s) = e.as_str() {
114 err.help(&format!("message: {}", s));
117 return ExpandResult::Ready(vec![]);
122 let error_count_before = ecx.sess.parse_sess.span_diagnostic.err_count();
124 rustc_parse::stream_to_parser(&ecx.sess.parse_sess, stream, Some("proc-macro derive"));
125 let mut items = vec![];
128 match parser.parse_item(ForceCollect::No) {
132 items.push(Annotatable::Stmt(P(ecx.stmt_item(span, item))));
134 items.push(Annotatable::Item(item));
144 // fail if there have been errors emitted
145 if ecx.sess.parse_sess.span_diagnostic.err_count() > error_count_before {
146 ecx.struct_span_err(span, "proc-macro derive produced unparseable tokens").emit();
149 ExpandResult::Ready(items)