]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_expand/src/proc_macro.rs
New upstream version 1.53.0+dfsg1
[rustc.git] / compiler / rustc_expand / src / proc_macro.rs
CommitLineData
e74abb32
XL
1use crate::base::{self, *};
2use crate::proc_macro_server;
3
6a06907d 4use rustc_ast as ast;
fc512014 5use rustc_ast::ptr::P;
74b04a01 6use rustc_ast::token;
5869c6ff 7use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, TokenStream, TokenTree};
dfeec247 8use rustc_data_structures::sync::Lrc;
6a06907d 9use rustc_errors::ErrorReported;
f035d41b 10use rustc_parse::nt_to_tokenstream;
5869c6ff 11use rustc_parse::parser::ForceCollect;
dfeec247 12use rustc_span::{Span, DUMMY_SP};
416331ca 13
e74abb32 14const EXEC_STRATEGY: pm::bridge::server::SameThread = pm::bridge::server::SameThread;
416331ca
XL
15
16pub struct BangProcMacro {
dfeec247 17 pub client: pm::bridge::client::Client<fn(pm::TokenStream) -> pm::TokenStream>,
416331ca
XL
18}
19
20impl base::ProcMacro for BangProcMacro {
dfeec247
XL
21 fn expand<'cx>(
22 &self,
23 ecx: &'cx mut ExtCtxt<'_>,
24 span: Span,
25 input: TokenStream,
ba9703b0 26 ) -> Result<TokenStream, ErrorReported> {
416331ca 27 let server = proc_macro_server::Rustc::new(ecx);
1b1a35ee 28 self.client.run(&EXEC_STRATEGY, server, input, ecx.ecfg.proc_macro_backtrace).map_err(|e| {
ba9703b0
XL
29 let mut err = ecx.struct_span_err(span, "proc macro panicked");
30 if let Some(s) = e.as_str() {
31 err.help(&format!("message: {}", s));
416331ca 32 }
ba9703b0
XL
33 err.emit();
34 ErrorReported
35 })
416331ca
XL
36 }
37}
38
39pub struct AttrProcMacro {
e74abb32 40 pub client: pm::bridge::client::Client<fn(pm::TokenStream, pm::TokenStream) -> pm::TokenStream>,
416331ca
XL
41}
42
43impl base::AttrProcMacro for AttrProcMacro {
dfeec247
XL
44 fn expand<'cx>(
45 &self,
46 ecx: &'cx mut ExtCtxt<'_>,
47 span: Span,
48 annotation: TokenStream,
49 annotated: TokenStream,
ba9703b0 50 ) -> Result<TokenStream, ErrorReported> {
416331ca 51 let server = proc_macro_server::Rustc::new(ecx);
1b1a35ee
XL
52 self.client
53 .run(&EXEC_STRATEGY, server, annotation, annotated, ecx.ecfg.proc_macro_backtrace)
54 .map_err(|e| {
55 let mut err = ecx.struct_span_err(span, "custom attribute panicked");
56 if let Some(s) = e.as_str() {
57 err.help(&format!("message: {}", s));
58 }
59 err.emit();
60 ErrorReported
61 })
416331ca
XL
62 }
63}
64
65pub struct ProcMacroDerive {
e74abb32 66 pub client: pm::bridge::client::Client<fn(pm::TokenStream) -> pm::TokenStream>,
416331ca
XL
67}
68
69impl MultiItemModifier for ProcMacroDerive {
dfeec247
XL
70 fn expand(
71 &self,
72 ecx: &mut ExtCtxt<'_>,
73 span: Span,
74 _meta_item: &ast::MetaItem,
75 item: Annotatable,
ba9703b0 76 ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
fc512014
XL
77 // We need special handling for statement items
78 // (e.g. `fn foo() { #[derive(Debug)] struct Bar; }`)
79 let mut is_stmt = false;
416331ca 80 let item = match item {
fc512014
XL
81 Annotatable::Item(item) => token::NtItem(item),
82 Annotatable::Stmt(stmt) => {
83 is_stmt = true;
84 assert!(stmt.is_item());
85
86 // A proc macro can't observe the fact that we're passing
87 // them an `NtStmt` - it can only see the underlying tokens
88 // of the wrapped item
89 token::NtStmt(stmt.into_inner())
416331ca 90 }
fc512014 91 _ => unreachable!(),
416331ca 92 };
6a06907d
XL
93 let input = if crate::base::pretty_printing_compatibility_hack(&item, &ecx.sess.parse_sess)
94 {
f035d41b
XL
95 TokenTree::token(token::Interpolated(Lrc::new(item)), DUMMY_SP).into()
96 } else {
cdc7bbd5 97 nt_to_tokenstream(&item, &ecx.sess.parse_sess, CanSynthesizeMissingTokens::No)
f035d41b 98 };
416331ca
XL
99
100 let server = proc_macro_server::Rustc::new(ecx);
1b1a35ee
XL
101 let stream =
102 match self.client.run(&EXEC_STRATEGY, server, input, ecx.ecfg.proc_macro_backtrace) {
103 Ok(stream) => stream,
104 Err(e) => {
105 let mut err = ecx.struct_span_err(span, "proc-macro derive panicked");
106 if let Some(s) = e.as_str() {
107 err.help(&format!("message: {}", s));
108 }
109 err.emit();
110 return ExpandResult::Ready(vec![]);
416331ca 111 }
1b1a35ee 112 };
416331ca 113
3dfed10e 114 let error_count_before = ecx.sess.parse_sess.span_diagnostic.err_count();
dfeec247 115 let mut parser =
3dfed10e 116 rustc_parse::stream_to_parser(&ecx.sess.parse_sess, stream, Some("proc-macro derive"));
416331ca
XL
117 let mut items = vec![];
118
119 loop {
5869c6ff 120 match parser.parse_item(ForceCollect::No) {
416331ca 121 Ok(None) => break,
fc512014
XL
122 Ok(Some(item)) => {
123 if is_stmt {
124 items.push(Annotatable::Stmt(P(ecx.stmt_item(span, item))));
125 } else {
126 items.push(Annotatable::Item(item));
127 }
128 }
416331ca 129 Err(mut err) => {
ba9703b0
XL
130 err.emit();
131 break;
416331ca
XL
132 }
133 }
134 }
135
416331ca 136 // fail if there have been errors emitted
3dfed10e 137 if ecx.sess.parse_sess.span_diagnostic.err_count() > error_count_before {
ba9703b0 138 ecx.struct_span_err(span, "proc-macro derive produced unparseable tokens").emit();
416331ca
XL
139 }
140
ba9703b0 141 ExpandResult::Ready(items)
416331ca
XL
142 }
143}