]> git.proxmox.com Git - rustc.git/blobdiff - compiler/rustc_builtin_macros/src/format.rs
New upstream version 1.57.0+dfsg1
[rustc.git] / compiler / rustc_builtin_macros / src / format.rs
index 8508b3b7ae6edb9a273d9f05e16950b75096e030..f0056cb79766a49f4db2f34a68a81b93c5176063 100644 (file)
@@ -164,23 +164,22 @@ fn parse_args<'a>(
                 p.clear_expected_tokens();
             }
 
-            // `Parser::expect` tries to recover using the
-            // `Parser::unexpected_try_recover` function. This function is able
-            // to recover if the expected token is a closing delimiter.
-            //
-            // As `,` is not a closing delimiter, it will always return an `Err`
-            // variant.
-            let mut err = p.expect(&token::Comma).unwrap_err();
-
-            match token::TokenKind::Comma.similar_tokens() {
-                Some(tks) if tks.contains(&p.token.kind) => {
-                    // If a similar token is found, then it may be a typo. We
-                    // consider it as a comma, and continue parsing.
-                    err.emit();
-                    p.bump();
+            match p.expect(&token::Comma) {
+                Err(mut err) => {
+                    match token::TokenKind::Comma.similar_tokens() {
+                        Some(tks) if tks.contains(&p.token.kind) => {
+                            // If a similar token is found, then it may be a typo. We
+                            // consider it as a comma, and continue parsing.
+                            err.emit();
+                            p.bump();
+                        }
+                        // Otherwise stop the parsing and return the error.
+                        _ => return Err(err),
+                    }
+                }
+                Ok(recovered) => {
+                    assert!(recovered);
                 }
-                // Otherwise stop the parsing and return the error.
-                _ => return Err(err),
             }
         }
         first = false;
@@ -845,8 +844,7 @@ impl<'a, 'b> Context<'a, 'b> {
             self.ecx.expr_match(self.macsp, head, vec![arm])
         };
 
-        let ident = Ident::from_str_and_span("args", self.macsp);
-        let args_slice = self.ecx.expr_ident(self.macsp, ident);
+        let args_slice = self.ecx.expr_addr_of(self.macsp, args_match);
 
         // Now create the fmt::Arguments struct with all our locals we created.
         let (fn_name, fn_args) = if self.all_pieces_simple {
@@ -856,25 +854,22 @@ impl<'a, 'b> Context<'a, 'b> {
             // nonstandard placeholders, if there are any.
             let fmt = self.ecx.expr_vec_slice(self.macsp, self.pieces);
 
-            ("new_v1_formatted", vec![pieces, args_slice, fmt])
+            let path = self.ecx.std_path(&[sym::fmt, sym::UnsafeArg, sym::new]);
+            let unsafe_arg = self.ecx.expr_call_global(self.macsp, path, Vec::new());
+            let unsafe_expr = self.ecx.expr_block(P(ast::Block {
+                stmts: vec![self.ecx.stmt_expr(unsafe_arg)],
+                id: ast::DUMMY_NODE_ID,
+                rules: BlockCheckMode::Unsafe(UnsafeSource::CompilerGenerated),
+                span: self.macsp,
+                tokens: None,
+                could_be_bare_literal: false,
+            }));
+
+            ("new_v1_formatted", vec![pieces, args_slice, fmt, unsafe_expr])
         };
 
         let path = self.ecx.std_path(&[sym::fmt, sym::Arguments, Symbol::intern(fn_name)]);
-        let arguments = self.ecx.expr_call_global(self.macsp, path, fn_args);
-        let body = self.ecx.expr_block(P(ast::Block {
-            stmts: vec![self.ecx.stmt_expr(arguments)],
-            id: ast::DUMMY_NODE_ID,
-            rules: BlockCheckMode::Unsafe(UnsafeSource::CompilerGenerated),
-            span: self.macsp,
-            tokens: None,
-            could_be_bare_literal: false,
-        }));
-
-        let ident = Ident::from_str_and_span("args", self.macsp);
-        let binding_mode = ast::BindingMode::ByRef(ast::Mutability::Not);
-        let pat = self.ecx.pat_ident_binding_mode(self.macsp, ident, binding_mode);
-        let arm = self.ecx.arm(self.macsp, pat, body);
-        self.ecx.expr_match(self.macsp, args_match, vec![arm])
+        self.ecx.expr_call_global(self.macsp, path, fn_args)
     }
 
     fn format_arg(
@@ -964,17 +959,19 @@ pub fn expand_preparsed_format_args(
         }
         Ok(fmt) => fmt,
         Err(err) => {
-            if let Some(mut err) = err {
+            if let Some((mut err, suggested)) = err {
                 let sugg_fmt = match args.len() {
                     0 => "{}".to_string(),
                     _ => format!("{}{{}}", "{} ".repeat(args.len())),
                 };
-                err.span_suggestion(
-                    fmt_sp.shrink_to_lo(),
-                    "you might be missing a string literal to format with",
-                    format!("\"{}\", ", sugg_fmt),
-                    Applicability::MaybeIncorrect,
-                );
+                if !suggested {
+                    err.span_suggestion(
+                        fmt_sp.shrink_to_lo(),
+                        "you might be missing a string literal to format with",
+                        format!("\"{}\", ", sugg_fmt),
+                        Applicability::MaybeIncorrect,
+                    );
+                }
                 err.emit();
             }
             return DummyResult::raw_expr(sp, true);
@@ -1157,11 +1154,12 @@ pub fn expand_preparsed_format_args(
                     // account for `"` and account for raw strings `r#`
                     let padding = str_style.map(|i| i + 2).unwrap_or(1);
                     for sub in foreign::$kind::iter_subs(fmt_str, padding) {
-                        let trn = match sub.translate() {
-                            Some(trn) => trn,
+                        let (trn, success) = match sub.translate() {
+                            Ok(trn) => (trn, true),
+                            Err(Some(msg)) => (msg, false),
 
                             // If it has no translation, don't call it out specifically.
-                            None => continue,
+                            _ => continue,
                         };
 
                         let pos = sub.position();
@@ -1178,9 +1176,24 @@ pub fn expand_preparsed_format_args(
 
                         if let Some(inner_sp) = pos {
                             let sp = fmt_sp.from_inner(inner_sp);
-                            suggestions.push((sp, trn));
+
+                            if success {
+                                suggestions.push((sp, trn));
+                            } else {
+                                diag.span_note(
+                                    sp,
+                                    &format!("format specifiers use curly braces, and {}", trn),
+                                );
+                            }
                         } else {
-                            diag.help(&format!("`{}` should be written as `{}`", sub, trn));
+                            if success {
+                                diag.help(&format!("`{}` should be written as `{}`", sub, trn));
+                            } else {
+                                diag.note(&format!(
+                                    "`{}` should use curly braces, and {}",
+                                    sub, trn
+                                ));
+                            }
                         }
                     }