about summary refs log tree commit diff
path: root/compiler/rustc_builtin_macros/src/format.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_builtin_macros/src/format.rs')
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs121
1 files changed, 68 insertions, 53 deletions
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 385c90ff14b..6f031f270ca 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -9,7 +9,7 @@ use rustc_ast::{
 };
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{Applicability, Diag, MultiSpan, PResult, SingleLabelManySpans};
-use rustc_expand::base::{self, *};
+use rustc_expand::base::*;
 use rustc_parse::parser::Recovered;
 use rustc_parse_format as parse;
 use rustc_span::symbol::{Ident, Symbol};
@@ -40,6 +40,7 @@ use PositionUsedAs::*;
 
 use crate::errors;
 
+#[derive(Debug)]
 struct MacroInput {
     fmtstr: P<Expr>,
     args: FormatArguments,
@@ -160,54 +161,61 @@ fn make_format_args(
     ecx: &mut ExtCtxt<'_>,
     input: MacroInput,
     append_newline: bool,
-) -> Result<FormatArgs, ErrorGuaranteed> {
+) -> ExpandResult<Result<FormatArgs, ErrorGuaranteed>, ()> {
     let msg = "format argument must be a string literal";
     let unexpanded_fmt_span = input.fmtstr.span;
 
     let MacroInput { fmtstr: efmt, mut args, is_direct_literal } = input;
 
-    let (fmt_str, fmt_style, fmt_span) = match expr_to_spanned_string(ecx, efmt.clone(), msg) {
-        Ok(mut fmt) if append_newline => {
-            fmt.0 = Symbol::intern(&format!("{}\n", fmt.0));
-            fmt
-        }
-        Ok(fmt) => fmt,
-        Err(err) => {
-            let guar = match err {
-                Ok((mut err, suggested)) => {
-                    if !suggested {
-                        if let ExprKind::Block(block, None) = &efmt.kind
-                            && block.stmts.len() == 1
-                            && let StmtKind::Expr(expr) = &block.stmts[0].kind
-                            && let ExprKind::Path(None, path) = &expr.kind
-                            && path.is_potential_trivial_const_arg()
-                        {
-                            err.multipart_suggestion(
-                                "quote your inlined format argument to use as string literal",
-                                vec![
-                                    (unexpanded_fmt_span.shrink_to_hi(), "\"".to_string()),
-                                    (unexpanded_fmt_span.shrink_to_lo(), "\"".to_string()),
-                                ],
-                                Applicability::MaybeIncorrect,
-                            );
-                        } else {
-                            let sugg_fmt = match args.explicit_args().len() {
-                                0 => "{}".to_string(),
-                                _ => format!("{}{{}}", "{} ".repeat(args.explicit_args().len())),
-                            };
-                            err.span_suggestion(
-                                unexpanded_fmt_span.shrink_to_lo(),
-                                "you might be missing a string literal to format with",
-                                format!("\"{sugg_fmt}\", "),
-                                Applicability::MaybeIncorrect,
-                            );
+    let (fmt_str, fmt_style, fmt_span) = {
+        let ExpandResult::Ready(mac) = expr_to_spanned_string(ecx, efmt.clone(), msg) else {
+            return ExpandResult::Retry(());
+        };
+        match mac {
+            Ok(mut fmt) if append_newline => {
+                fmt.0 = Symbol::intern(&format!("{}\n", fmt.0));
+                fmt
+            }
+            Ok(fmt) => fmt,
+            Err(err) => {
+                let guar = match err {
+                    Ok((mut err, suggested)) => {
+                        if !suggested {
+                            if let ExprKind::Block(block, None) = &efmt.kind
+                                && block.stmts.len() == 1
+                                && let StmtKind::Expr(expr) = &block.stmts[0].kind
+                                && let ExprKind::Path(None, path) = &expr.kind
+                                && path.is_potential_trivial_const_arg()
+                            {
+                                err.multipart_suggestion(
+                                    "quote your inlined format argument to use as string literal",
+                                    vec![
+                                        (unexpanded_fmt_span.shrink_to_hi(), "\"".to_string()),
+                                        (unexpanded_fmt_span.shrink_to_lo(), "\"".to_string()),
+                                    ],
+                                    Applicability::MaybeIncorrect,
+                                );
+                            } else {
+                                let sugg_fmt = match args.explicit_args().len() {
+                                    0 => "{}".to_string(),
+                                    _ => {
+                                        format!("{}{{}}", "{} ".repeat(args.explicit_args().len()))
+                                    }
+                                };
+                                err.span_suggestion(
+                                    unexpanded_fmt_span.shrink_to_lo(),
+                                    "you might be missing a string literal to format with",
+                                    format!("\"{sugg_fmt}\", "),
+                                    Applicability::MaybeIncorrect,
+                                );
+                            }
                         }
+                        err.emit()
                     }
-                    err.emit()
-                }
-                Err(guar) => guar,
-            };
-            return Err(guar);
+                    Err(guar) => guar,
+                };
+                return ExpandResult::Ready(Err(guar));
+            }
         }
     };
 
@@ -297,7 +305,7 @@ fn make_format_args(
             }
         }
         let guar = ecx.dcx().emit_err(e);
-        return Err(guar);
+        return ExpandResult::Ready(Err(guar));
     }
 
     let to_span = |inner_span: rustc_parse_format::InnerSpan| {
@@ -564,7 +572,7 @@ fn make_format_args(
         }
     }
 
-    Ok(FormatArgs { span: fmt_span, template, arguments: args })
+    ExpandResult::Ready(Ok(FormatArgs { span: fmt_span, template, arguments: args }))
 }
 
 fn invalid_placeholder_type_error(
@@ -972,25 +980,32 @@ fn expand_format_args_impl<'cx>(
     mut sp: Span,
     tts: TokenStream,
     nl: bool,
-) -> Box<dyn base::MacResult + 'cx> {
+) -> MacroExpanderResult<'cx> {
     sp = ecx.with_def_site_ctxt(sp);
-    match parse_args(ecx, sp, tts) {
-        Ok(input) => match make_format_args(ecx, input, nl) {
-            Ok(format_args) => MacEager::expr(ecx.expr(sp, ExprKind::FormatArgs(P(format_args)))),
-            Err(guar) => MacEager::expr(DummyResult::raw_expr(sp, Some(guar))),
-        },
+    ExpandResult::Ready(match parse_args(ecx, sp, tts) {
+        Ok(input) => {
+            let ExpandResult::Ready(mac) = make_format_args(ecx, input, nl) else {
+                return ExpandResult::Retry(());
+            };
+            match mac {
+                Ok(format_args) => {
+                    MacEager::expr(ecx.expr(sp, ExprKind::FormatArgs(P(format_args))))
+                }
+                Err(guar) => MacEager::expr(DummyResult::raw_expr(sp, Some(guar))),
+            }
+        }
         Err(err) => {
             let guar = err.emit();
             DummyResult::any(sp, guar)
         }
-    }
+    })
 }
 
 pub fn expand_format_args<'cx>(
     ecx: &'cx mut ExtCtxt<'_>,
     sp: Span,
     tts: TokenStream,
-) -> Box<dyn base::MacResult + 'cx> {
+) -> MacroExpanderResult<'cx> {
     expand_format_args_impl(ecx, sp, tts, false)
 }
 
@@ -998,6 +1013,6 @@ pub fn expand_format_args_nl<'cx>(
     ecx: &'cx mut ExtCtxt<'_>,
     sp: Span,
     tts: TokenStream,
-) -> Box<dyn base::MacResult + 'cx> {
+) -> MacroExpanderResult<'cx> {
     expand_format_args_impl(ecx, sp, tts, true)
 }