]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_expand/src/proc_macro.rs
New upstream version 1.63.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;
04454e1e 7use rustc_ast::tokenstream::{TokenStream, TokenTree};
dfeec247 8use rustc_data_structures::sync::Lrc;
5e7ed085 9use rustc_errors::ErrorGuaranteed;
5869c6ff 10use rustc_parse::parser::ForceCollect;
04454e1e 11use rustc_span::profiling::SpannedEventArgRecorder;
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 {
923072b8 17 pub client: pm::bridge::client::Client<pm::TokenStream, pm::TokenStream>,
416331ca
XL
18}
19
923072b8 20impl base::BangProcMacro for BangProcMacro {
dfeec247
XL
21 fn expand<'cx>(
22 &self,
23 ecx: &'cx mut ExtCtxt<'_>,
24 span: Span,
25 input: TokenStream,
5e7ed085 26 ) -> Result<TokenStream, ErrorGuaranteed> {
04454e1e
FG
27 let _timer =
28 ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| {
29 recorder.record_arg_with_span(ecx.expansion_descr(), span);
30 });
31
3c0e092e 32 let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
136023e0 33 let server = proc_macro_server::Rustc::new(ecx);
3c0e092e 34 self.client.run(&EXEC_STRATEGY, server, input, proc_macro_backtrace).map_err(|e| {
ba9703b0
XL
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));
416331ca 38 }
5e7ed085 39 err.emit()
ba9703b0 40 })
416331ca
XL
41 }
42}
43
44pub struct AttrProcMacro {
923072b8 45 pub client: pm::bridge::client::Client<(pm::TokenStream, pm::TokenStream), pm::TokenStream>,
416331ca
XL
46}
47
48impl base::AttrProcMacro for AttrProcMacro {
dfeec247
XL
49 fn expand<'cx>(
50 &self,
51 ecx: &'cx mut ExtCtxt<'_>,
52 span: Span,
53 annotation: TokenStream,
54 annotated: TokenStream,
5e7ed085 55 ) -> Result<TokenStream, ErrorGuaranteed> {
04454e1e
FG
56 let _timer =
57 ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| {
58 recorder.record_arg_with_span(ecx.expansion_descr(), span);
59 });
60
3c0e092e 61 let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
136023e0 62 let server = proc_macro_server::Rustc::new(ecx);
1b1a35ee 63 self.client
3c0e092e 64 .run(&EXEC_STRATEGY, server, annotation, annotated, proc_macro_backtrace)
1b1a35ee
XL
65 .map_err(|e| {
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));
69 }
5e7ed085 70 err.emit()
1b1a35ee 71 })
416331ca
XL
72 }
73}
74
923072b8
FG
75pub struct DeriveProcMacro {
76 pub client: pm::bridge::client::Client<pm::TokenStream, pm::TokenStream>,
416331ca
XL
77}
78
923072b8 79impl MultiItemModifier for DeriveProcMacro {
dfeec247
XL
80 fn expand(
81 &self,
82 ecx: &mut ExtCtxt<'_>,
83 span: Span,
84 _meta_item: &ast::MetaItem,
85 item: Annotatable,
ba9703b0 86 ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
fc512014
XL
87 // We need special handling for statement items
88 // (e.g. `fn foo() { #[derive(Debug)] struct Bar; }`)
04454e1e
FG
89 let is_stmt = matches!(item, Annotatable::Stmt(..));
90 let hack = crate::base::ann_pretty_printing_compatibility_hack(&item, &ecx.sess.parse_sess);
91 let input = if hack {
92 let nt = match item {
93 Annotatable::Item(item) => token::NtItem(item),
94 Annotatable::Stmt(stmt) => token::NtStmt(stmt),
95 _ => unreachable!(),
96 };
97 TokenTree::token(token::Interpolated(Lrc::new(nt)), DUMMY_SP).into()
f035d41b 98 } else {
923072b8 99 item.to_tokens()
f035d41b 100 };
416331ca 101
04454e1e
FG
102 let stream = {
103 let _timer =
104 ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| {
105 recorder.record_arg_with_span(ecx.expansion_descr(), span);
106 });
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,
111 Err(e) => {
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));
115 }
116 err.emit();
117 return ExpandResult::Ready(vec![]);
416331ca 118 }
3c0e092e
XL
119 }
120 };
416331ca 121
3dfed10e 122 let error_count_before = ecx.sess.parse_sess.span_diagnostic.err_count();
dfeec247 123 let mut parser =
3dfed10e 124 rustc_parse::stream_to_parser(&ecx.sess.parse_sess, stream, Some("proc-macro derive"));
416331ca
XL
125 let mut items = vec![];
126
127 loop {
5869c6ff 128 match parser.parse_item(ForceCollect::No) {
416331ca 129 Ok(None) => break,
fc512014
XL
130 Ok(Some(item)) => {
131 if is_stmt {
132 items.push(Annotatable::Stmt(P(ecx.stmt_item(span, item))));
133 } else {
134 items.push(Annotatable::Item(item));
135 }
136 }
416331ca 137 Err(mut err) => {
ba9703b0
XL
138 err.emit();
139 break;
416331ca
XL
140 }
141 }
142 }
143
416331ca 144 // fail if there have been errors emitted
3dfed10e 145 if ecx.sess.parse_sess.span_diagnostic.err_count() > error_count_before {
ba9703b0 146 ecx.struct_span_err(span, "proc-macro derive produced unparseable tokens").emit();
416331ca
XL
147 }
148
ba9703b0 149 ExpandResult::Ready(items)
416331ca
XL
150 }
151}