Skip to content

Commit 3e018ce

Browse files
committed
Auto merge of #87264 - mystor:expand_literal, r=petrochenkov
proc_macro: Add an expand_expr method to TokenStream This feature is aimed at giving proc macros access to powers similar to those used by builtin macros such as `format_args!` or `concat!`. These macros are able to accept macros in place of string literal parameters, such as the format string, as they perform recursive macro expansion while being expanded. This can be especially useful in many cases thanks to helper macros like `concat!`, `stringify!` and `include_str!` which are often used to construct string literals at compile-time in user code. For now, this method only allows expanding macros which produce literals, although more expressions will be supported before the method is stabilized. In earlier versions of this PR, this method exclusively returned `Literal`, and spans on returned literals were stripped of expansion context before being returned to be as conservative as possible about permission leakage. The method's naming has been generalized to eventually support arbitrary expressions, and the context stripping has been removed (#87264 (comment)), which should allow for more general APIs like "format_args_implicits" (#67984) to be supported as well. ## API Surface ```rust impl TokenStream { pub fn expand_expr(&self) -> Result<TokenStream, ExpandError>; } #[non_exhaustive] pub struct ExpandError; impl Debug for ExpandError { ... } impl Display for ExpandError { ... } impl Error for ExpandError {} impl !Send for ExpandError {} impl !Sync for ExpandError {} ```
2 parents 7594067 + 3e4d3d2 commit 3e018ce

File tree

8 files changed

+421
-75
lines changed

8 files changed

+421
-75
lines changed

compiler/rustc_expand/src/proc_macro.rs

+15-13
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ impl base::ProcMacro for BangProcMacro {
2424
span: Span,
2525
input: TokenStream,
2626
) -> Result<TokenStream, ErrorReported> {
27+
let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
2728
let server = proc_macro_server::Rustc::new(ecx);
28-
self.client.run(&EXEC_STRATEGY, server, input, ecx.ecfg.proc_macro_backtrace).map_err(|e| {
29+
self.client.run(&EXEC_STRATEGY, server, input, proc_macro_backtrace).map_err(|e| {
2930
let mut err = ecx.struct_span_err(span, "proc macro panicked");
3031
if let Some(s) = e.as_str() {
3132
err.help(&format!("message: {}", s));
@@ -48,9 +49,10 @@ impl base::AttrProcMacro for AttrProcMacro {
4849
annotation: TokenStream,
4950
annotated: TokenStream,
5051
) -> Result<TokenStream, ErrorReported> {
52+
let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
5153
let server = proc_macro_server::Rustc::new(ecx);
5254
self.client
53-
.run(&EXEC_STRATEGY, server, annotation, annotated, ecx.ecfg.proc_macro_backtrace)
55+
.run(&EXEC_STRATEGY, server, annotation, annotated, proc_macro_backtrace)
5456
.map_err(|e| {
5557
let mut err = ecx.struct_span_err(span, "custom attribute panicked");
5658
if let Some(s) = e.as_str() {
@@ -97,19 +99,19 @@ impl MultiItemModifier for ProcMacroDerive {
9799
nt_to_tokenstream(&item, &ecx.sess.parse_sess, CanSynthesizeMissingTokens::No)
98100
};
99101

102+
let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
100103
let server = proc_macro_server::Rustc::new(ecx);
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![]);
104+
let stream = match self.client.run(&EXEC_STRATEGY, server, input, proc_macro_backtrace) {
105+
Ok(stream) => stream,
106+
Err(e) => {
107+
let mut err = ecx.struct_span_err(span, "proc-macro derive panicked");
108+
if let Some(s) = e.as_str() {
109+
err.help(&format!("message: {}", s));
111110
}
112-
};
111+
err.emit();
112+
return ExpandResult::Ready(vec![]);
113+
}
114+
};
113115

114116
let error_count_before = ecx.sess.parse_sess.span_diagnostic.err_count();
115117
let mut parser =

0 commit comments

Comments
 (0)