about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2023-09-06 18:00:30 +0200
committerLukas Wirth <lukastw97@gmail.com>2023-09-06 18:08:20 +0200
commitc0e402637eeff7dea29082f983f26be4ef2e317c (patch)
treed910cd14cdfc323f48063875ceb910f3c3071692
parent5fdd1e36e358019e2d58e64483717d533c04d7e7 (diff)
downloadrust-c0e402637eeff7dea29082f983f26be4ef2e317c.tar.gz
rust-c0e402637eeff7dea29082f983f26be4ef2e317c.zip
Emit builtin#format_args in builtin format_args expander
-rw-r--r--crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs39
-rw-r--r--crates/hir-def/src/macro_expansion_tests/mbe.rs6
-rw-r--r--crates/hir-def/src/macro_expansion_tests/mbe/regression.rs12
-rw-r--r--crates/hir-expand/src/builtin_fn_macro.rs160
-rw-r--r--crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs97
-rw-r--r--crates/ide-assists/src/tests/generated.rs15
-rw-r--r--crates/ide-completion/src/completions/format_string.rs22
-rw-r--r--crates/ide-db/src/syntax_helpers/format_string.rs20
-rw-r--r--crates/ide/src/hover/tests.rs20
-rw-r--r--crates/ide/src/inlay_hints/chaining.rs12
-rw-r--r--crates/ide/src/syntax_highlighting/format.rs1
-rw-r--r--crates/ide/src/syntax_highlighting/highlight.rs1
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_strings.html52
-rw-r--r--crates/ide/src/syntax_highlighting/tests.rs13
-rw-r--r--crates/test-utils/src/minicore.rs17
15 files changed, 146 insertions, 341 deletions
diff --git a/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
index a350511c7a1..4aedb22c6bc 100644
--- a/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
+++ b/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
@@ -240,7 +240,7 @@ macro_rules! format_args {
 }
 
 fn main() {
-    ::core::fmt::Arguments::new_v1(&["", " ", ], &[::core::fmt::ArgumentV1::new(&(arg1(a, b, c)), ::core::fmt::Display::fmt), ::core::fmt::ArgumentV1::new(&(arg2), ::core::fmt::Debug::fmt), ]);
+    builtin #format_args ("{} {:?}", arg1(a, b, c), arg2);
 }
 "##]],
     );
@@ -258,10 +258,10 @@ macro_rules! format_args {
 
 fn main() {
     format_args!(x = 2);
-    format_args!(x =);
-    format_args!(x =, x = 2);
-    format_args!("{}", x =);
-    format_args!(=, "{}", x =);
+    format_args!/*+errors*/(x =);
+    format_args!/*+errors*/(x =, x = 2);
+    format_args!/*+errors*/("{}", x =);
+    format_args!/*+errors*/(=, "{}", x =);
     format_args!(x = 2, "{}", 5);
 }
 "#,
@@ -273,12 +273,19 @@ macro_rules! format_args {
 }
 
 fn main() {
-    /* error: no rule matches input tokens */;
-    /* error: expected expression */;
-    /* error: expected expression, expected COMMA */;
-    /* error: expected expression */::core::fmt::Arguments::new_v1(&["", ], &[::core::fmt::ArgumentV1::new(&(), ::core::fmt::Display::fmt), ]);
-    /* error: expected expression, expected R_PAREN */;
-    ::core::fmt::Arguments::new_v1(&["", ], &[::core::fmt::ArgumentV1::new(&(5), ::core::fmt::Display::fmt), ]);
+    builtin #format_args (x = 2);
+    /* parse error: expected expression */
+builtin #format_args (x = );
+    /* parse error: expected expression */
+/* parse error: expected R_PAREN */
+/* parse error: expected expression, item or let statement */
+builtin #format_args (x = , x = 2);
+    /* parse error: expected expression */
+builtin #format_args ("{}", x = );
+    /* parse error: expected expression */
+/* parse error: expected expression */
+builtin #format_args ( = , "{}", x = );
+    builtin #format_args (x = 2, "{}", 5);
 }
 "##]],
     );
@@ -306,7 +313,7 @@ macro_rules! format_args {
 }
 
 fn main() {
-    ::core::fmt::Arguments::new_v1(&["", " ", ], &[::core::fmt::ArgumentV1::new(&(a::<A, B>()), ::core::fmt::Display::fmt), ::core::fmt::ArgumentV1::new(&(b), ::core::fmt::Debug::fmt), ]);
+    builtin #format_args ("{} {:?}", a::<A, B>(), b);
 }
 "##]],
     );
@@ -339,7 +346,7 @@ macro_rules! format_args {
 }
 
 fn main() {
-    ::core::fmt::Arguments::new_v1(&[r#""#, r#",mismatch,""#, r#"",""#, r#"""#, ], &[::core::fmt::ArgumentV1::new(&(location_csv_pat(db, &analysis, vfs, &sm, pat_id)), ::core::fmt::Display::fmt), ::core::fmt::ArgumentV1::new(&(mismatch.expected.display(db)), ::core::fmt::Display::fmt), ::core::fmt::ArgumentV1::new(&(mismatch.actual.display(db)), ::core::fmt::Display::fmt), ]);
+    builtin #format_args (r#"{},mismatch,"{}","{}""#, location_csv_pat(db, &analysis, vfs, &sm, pat_id), mismatch.expected.display(db), mismatch.actual.display(db));
 }
 "##]],
     );
@@ -373,7 +380,7 @@ macro_rules! format_args {
 }
 
 fn main() {
-    ::core::fmt::Arguments::new_v1(&["xxx", "y", "zzz", ], &[::core::fmt::ArgumentV1::new(&(2), ::core::fmt::Display::fmt), ::core::fmt::ArgumentV1::new(&(b), ::core::fmt::Debug::fmt), ]);
+    builtin #format_args (concat!("xxx{}y", "{:?}zzz"), 2, b);
 }
 "##]],
     );
@@ -403,8 +410,8 @@ macro_rules! format_args {
 
 fn main() {
     let _ =
-        /* error: expected field name or number *//* parse error: expected field name or number */
-::core::fmt::Arguments::new_v1(&["", " ", ], &[::core::fmt::ArgumentV1::new(&(a.), ::core::fmt::Display::fmt), ::core::fmt::ArgumentV1::new(&(), ::core::fmt::Debug::fmt), ]);
+        /* parse error: expected field name or number */
+builtin #format_args ("{} {:?}", a.);
 }
 "##]],
     );
diff --git a/crates/hir-def/src/macro_expansion_tests/mbe.rs b/crates/hir-def/src/macro_expansion_tests/mbe.rs
index 2170cadcf83..d0906213243 100644
--- a/crates/hir-def/src/macro_expansion_tests/mbe.rs
+++ b/crates/hir-def/src/macro_expansion_tests/mbe.rs
@@ -117,7 +117,7 @@ fn main(foo: ()) {
 macro_rules! format_args {}
 
 fn main(foo: ()) {
-    /* error: unresolved macro identity */::core::fmt::Arguments::new_v1(&["", " ", " ", ], &[::core::fmt::ArgumentV1::new(&(::core::fmt::Arguments::new_v1(&["", ], &[::core::fmt::ArgumentV1::new(&(0), ::core::fmt::Display::fmt), ])), ::core::fmt::Display::fmt), ::core::fmt::ArgumentV1::new(&(foo), ::core::fmt::Display::fmt), ::core::fmt::ArgumentV1::new(&(identity!(10)), ::core::fmt::Display::fmt), ])
+    builtin #format_args ("{} {} {}", format_args!("{}", 0), foo, identity!(10), "bar")
 }
 "##]],
     );
@@ -150,8 +150,8 @@ macro_rules! identity {
 }
 
 fn main(foo: ()) {
-    // format_args/*+tokenids*/!("{} {} {}"#1,#3 format_args!("{}", 0#10),#12 foo#13,#14 identity!(10#18),#21 "bar"#22)
-::core#4294967295::fmt#4294967295::Arguments#4294967295::new_v1#4294967295(&#4294967295[#4294967295""#4294967295,#4294967295 " "#4294967295,#4294967295 " "#4294967295,#4294967295 ]#4294967295,#4294967295 &#4294967295[::core#4294967295::fmt#4294967295::ArgumentV1#4294967295::new#4294967295(&#4294967295(::core#4294967295::fmt#4294967295::Arguments#4294967295::new_v1#4294967295(&#4294967295[#4294967295""#4294967295,#4294967295 ]#4294967295,#4294967295 &#4294967295[::core#4294967295::fmt#4294967295::ArgumentV1#4294967295::new#4294967295(&#4294967295(#42949672950#10)#4294967295,#4294967295 ::core#4294967295::fmt#4294967295::Display#4294967295::fmt#4294967295)#4294967295,#4294967295 ]#4294967295)#4294967295)#4294967295,#4294967295 ::core#4294967295::fmt#4294967295::Display#4294967295::fmt#4294967295)#4294967295,#4294967295 ::core#4294967295::fmt#4294967295::ArgumentV1#4294967295::new#4294967295(&#4294967295(#4294967295foo#13)#4294967295,#4294967295 ::core#4294967295::fmt#4294967295::Display#4294967295::fmt#4294967295)#4294967295,#4294967295 ::core#4294967295::fmt#4294967295::ArgumentV1#4294967295::new#4294967295(&#4294967295(#429496729510#18)#4294967295,#4294967295 ::core#4294967295::fmt#4294967295::Display#4294967295::fmt#4294967295)#4294967295,#4294967295 ]#4294967295)#4294967295
+    // format_args/*+tokenids*/!("{} {} {}"#1,#2 format_args#3!#4("{}"#6,#7 0#8),#9 foo#10,#11 identity#12!#13(10#15),#16 "bar"#17)
+builtin#4294967295 ##4294967295format_args#4294967295 (#0"{} {} {}"#1,#2 format_args#3!#4(#5"{}"#6,#7 0#8)#5,#9 foo#10,#11 identity#12!#13(#1410#15)#14,#16 "bar"#17)#0
 }
 
 "##]],
diff --git a/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs b/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs
index 97554f93f1c..b416f45ff20 100644
--- a/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs
+++ b/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs
@@ -929,8 +929,8 @@ fn main() {
 macro_rules! format_args {}
 
 fn main() {
-    /* error: expected field name or number *//* parse error: expected field name or number */
-::core::fmt::Arguments::new_v1(&["", ], &[::core::fmt::ArgumentV1::new(&(line.1.), ::core::fmt::Display::fmt), ]);
+    /* parse error: expected field name or number */
+builtin #format_args ("{}", line.1.);
 }
 
 "##]],
@@ -956,19 +956,15 @@ fn main() {
 macro_rules! format_args {}
 
 fn main() {
-    /* error: expected COMMA, expected R_BRACK, expected COMMA, expected COMMA, expected expression, expected R_PAREN *//* parse error: expected COMMA */
+    /* parse error: expected COMMA */
 /* parse error: expected R_BRACK */
 /* parse error: expected COMMA */
 /* parse error: expected COMMA */
 /* parse error: expected expression */
 /* parse error: expected R_PAREN */
-/* parse error: expected R_PAREN */
-/* parse error: expected expression, item or let statement */
-/* parse error: expected expression, item or let statement */
-/* parse error: expected expression, item or let statement */
 /* parse error: expected expression, item or let statement */
 /* parse error: expected expression, item or let statement */
-::core::fmt::Arguments::new_v1(&["", ], &[::core::fmt::ArgumentV1::new(&(&[0 2]), ::core::fmt::Display::fmt), ]);
+builtin #format_args ("{}", &[0 2]);
 }
 
 "##]],
diff --git a/crates/hir-expand/src/builtin_fn_macro.rs b/crates/hir-expand/src/builtin_fn_macro.rs
index 00ee5e8b9d0..30b19b6e51b 100644
--- a/crates/hir-expand/src/builtin_fn_macro.rs
+++ b/crates/hir-expand/src/builtin_fn_macro.rs
@@ -1,13 +1,9 @@
 //! Builtin macro
 
-use std::mem;
-
-use ::tt::Ident;
 use base_db::{AnchoredPath, Edition, FileId};
 use cfg::CfgExpr;
 use either::Either;
 use mbe::{parse_exprs_with_sep, parse_to_token_tree, TokenMap};
-use rustc_hash::FxHashMap;
 use syntax::{
     ast::{self, AstToken},
     SmolStr,
@@ -97,11 +93,11 @@ register_builtin! {
     (unreachable, Unreachable) => unreachable_expand,
     (log_syntax, LogSyntax) => log_syntax_expand,
     (trace_macros, TraceMacros) => trace_macros_expand,
-
-    EAGER:
     (format_args, FormatArgs) => format_args_expand,
     (const_format_args, ConstFormatArgs) => format_args_expand,
     (format_args_nl, FormatArgsNl) => format_args_nl_expand,
+
+    EAGER:
     (compile_error, CompileError) => compile_error_expand,
     (concat, Concat) => concat_expand,
     (concat_idents, ConcatIdents) => concat_idents_expand,
@@ -247,151 +243,15 @@ fn format_args_expand_general(
     _db: &dyn ExpandDatabase,
     _id: MacroCallId,
     tt: &tt::Subtree,
-    end_string: &str,
+    // FIXME: Make use of this so that mir interpretation works properly
+    _end_string: &str,
 ) -> ExpandResult<tt::Subtree> {
-    let args = parse_exprs_with_sep(tt, ',');
-
-    let expand_error =
-        ExpandResult::new(tt::Subtree::empty(), mbe::ExpandError::NoMatchingRule.into());
-
-    let mut key_args = FxHashMap::default();
-    let mut args = args.into_iter().filter_map(|mut arg| {
-        // Remove `key =`.
-        if matches!(arg.token_trees.get(1), Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p))) if p.char == '=')
-        {
-            // but not with `==`
-            if !matches!(arg.token_trees.get(2), Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p))) if p.char == '=')
-            {
-                let key = arg.token_trees.drain(..2).next().unwrap();
-                key_args.insert(key.to_string(), arg);
-                return None;
-            }
-        }
-        Some(arg)
-    }).collect::<Vec<_>>().into_iter();
-    // ^^^^^^^ we need this collect, to enforce the side effect of the filter_map closure (building the `key_args`)
-    let Some(format_subtree) = args.next() else {
-        return expand_error;
-    };
-    let format_string = (|| {
-        let token_tree = format_subtree.token_trees.get(0)?;
-        match token_tree {
-            tt::TokenTree::Leaf(l) => match l {
-                tt::Leaf::Literal(l) => {
-                    if let Some(mut text) = l.text.strip_prefix('r') {
-                        let mut raw_sharps = String::new();
-                        while let Some(t) = text.strip_prefix('#') {
-                            text = t;
-                            raw_sharps.push('#');
-                        }
-                        text =
-                            text.strip_suffix(&raw_sharps)?.strip_prefix('"')?.strip_suffix('"')?;
-                        Some((text, l.span, Some(raw_sharps)))
-                    } else {
-                        let text = l.text.strip_prefix('"')?.strip_suffix('"')?;
-                        let span = l.span;
-                        Some((text, span, None))
-                    }
-                }
-                _ => None,
-            },
-            tt::TokenTree::Subtree(_) => None,
-        }
-    })();
-    let Some((format_string, _format_string_span, raw_sharps)) = format_string else {
-        return expand_error;
-    };
-    let mut format_iter = format_string.chars().peekable();
-    let mut parts = vec![];
-    let mut last_part = String::new();
-    let mut arg_tts = vec![];
-    let mut err = None;
-    while let Some(c) = format_iter.next() {
-        // Parsing the format string. See https://doc.rust-lang.org/std/fmt/index.html#syntax for the grammar and more info
-        match c {
-            '{' => {
-                if format_iter.peek() == Some(&'{') {
-                    format_iter.next();
-                    last_part.push('{');
-                    continue;
-                }
-                let mut argument = String::new();
-                while ![Some(&'}'), Some(&':')].contains(&format_iter.peek()) {
-                    argument.push(match format_iter.next() {
-                        Some(c) => c,
-                        None => return expand_error,
-                    });
-                }
-                let format_spec = match format_iter.next().unwrap() {
-                    '}' => "".to_owned(),
-                    ':' => {
-                        let mut s = String::new();
-                        while let Some(c) = format_iter.next() {
-                            if c == '}' {
-                                break;
-                            }
-                            s.push(c);
-                        }
-                        s
-                    }
-                    _ => unreachable!(),
-                };
-                parts.push(mem::take(&mut last_part));
-                let arg_tree = if argument.is_empty() {
-                    match args.next() {
-                        Some(it) => it,
-                        None => {
-                            err = Some(mbe::ExpandError::NoMatchingRule.into());
-                            tt::Subtree::empty()
-                        }
-                    }
-                } else if let Some(tree) = key_args.get(&argument) {
-                    tree.clone()
-                } else {
-                    // FIXME: we should pick the related substring of the `_format_string_span` as the span. You
-                    // can use `.char_indices()` instead of `.char()` for `format_iter` to find the substring interval.
-                    let ident = Ident::new(argument, tt::TokenId::unspecified());
-                    quote!(#ident)
-                };
-                let formatter = match &*format_spec {
-                    "?" => quote!(::core::fmt::Debug::fmt),
-                    "" => quote!(::core::fmt::Display::fmt),
-                    _ => {
-                        // FIXME: implement the rest and return expand error here
-                        quote!(::core::fmt::Display::fmt)
-                    }
-                };
-                arg_tts.push(quote! { ::core::fmt::ArgumentV1::new(&(#arg_tree), #formatter), });
-            }
-            '}' => {
-                if format_iter.peek() == Some(&'}') {
-                    format_iter.next();
-                    last_part.push('}');
-                } else {
-                    return expand_error;
-                }
-            }
-            _ => last_part.push(c),
-        }
-    }
-    last_part += end_string;
-    if !last_part.is_empty() {
-        parts.push(last_part);
-    }
-    let part_tts = parts.into_iter().map(|it| {
-        let text = if let Some(raw) = &raw_sharps {
-            format!("r{raw}\"{}\"{raw}", it).into()
-        } else {
-            format!("\"{}\"", it).into()
-        };
-        let l = tt::Literal { span: tt::TokenId::unspecified(), text };
-        quote!(#l ,)
+    let pound = quote! {@PUNCT '#'};
+    let mut tt = tt.clone();
+    tt.delimiter.kind = tt::DelimiterKind::Parenthesis;
+    return ExpandResult::ok(quote! {
+        builtin #pound format_args #tt
     });
-    let arg_tts = arg_tts.into_iter().flat_map(|arg| arg.token_trees);
-    let expanded = quote! {
-        ::core::fmt::Arguments::new_v1(&[##part_tts], &[##arg_tts])
-    };
-    ExpandResult { value: expanded, err }
 }
 
 fn asm_expand(
@@ -399,8 +259,6 @@ fn asm_expand(
     _id: MacroCallId,
     tt: &tt::Subtree,
 ) -> ExpandResult<tt::Subtree> {
-    // FIXME: parse asm here
-
     // We expand all assembly snippets to `format_args!` invocations to get format syntax
     // highlighting for them.
 
diff --git a/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs b/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs
index c3d925cb26c..25c4b49c945 100644
--- a/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs
+++ b/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs
@@ -15,26 +15,13 @@ use syntax::{ast, AstNode, AstToken, NodeOrToken, SyntaxKind::COMMA, TextRange};
 // Move an expression out of a format string.
 //
 // ```
-// macro_rules! format_args {
-//     ($lit:literal $(tt:tt)*) => { 0 },
-// }
-// macro_rules! print {
-//     ($($arg:tt)*) => (std::io::_print(format_args!($($arg)*)));
-// }
-//
+// # //- minicore: fmt
 // fn main() {
 //     print!("{var} {x + 1}$0");
 // }
 // ```
 // ->
 // ```
-// macro_rules! format_args {
-//     ($lit:literal $(tt:tt)*) => { 0 },
-// }
-// macro_rules! print {
-//     ($($arg:tt)*) => (std::io::_print(format_args!($($arg)*)));
-// }
-//
 // fn main() {
 //     print!("{var} {}"$0, x + 1);
 // }
@@ -47,17 +34,23 @@ pub(crate) fn extract_expressions_from_format_string(
     let fmt_string = ctx.find_token_at_offset::<ast::String>()?;
     let tt = fmt_string.syntax().parent().and_then(ast::TokenTree::cast)?;
 
+    dbg!();
     let expanded_t = ast::String::cast(
         ctx.sema.descend_into_macros_with_kind_preference(fmt_string.syntax().clone(), 0.into()),
     )?;
+    dbg!();
     if !is_format_string(&expanded_t) {
+        dbg!();
         return None;
     }
 
+    dbg!();
     let (new_fmt, extracted_args) = parse_format_exprs(fmt_string.text()).ok()?;
+    dbg!();
     if extracted_args.is_empty() {
         return None;
     }
+    dbg!();
 
     acc.add(
         AssistId(
@@ -158,37 +151,21 @@ mod tests {
     use super::*;
     use crate::tests::check_assist;
 
-    const MACRO_DECL: &'static str = r#"
-macro_rules! format_args {
-    ($lit:literal $(tt:tt)*) => { 0 },
-}
-macro_rules! print {
-    ($($arg:tt)*) => (std::io::_print(format_args!($($arg)*)));
-}
-"#;
-
-    fn add_macro_decl(s: &'static str) -> String {
-        MACRO_DECL.to_string() + s
-    }
-
     #[test]
     fn multiple_middle_arg() {
         check_assist(
             extract_expressions_from_format_string,
-            &add_macro_decl(
-                r#"
+            r#"
+//- minicore: fmt
 fn main() {
     print!("{} {x + 1:b} {}$0", y + 2, 2);
 }
 "#,
-            ),
-            &add_macro_decl(
-                r#"
+            r#"
 fn main() {
     print!("{} {:b} {}"$0, y + 2, x + 1, 2);
 }
 "#,
-            ),
         );
     }
 
@@ -196,20 +173,17 @@ fn main() {
     fn single_arg() {
         check_assist(
             extract_expressions_from_format_string,
-            &add_macro_decl(
-                r#"
+            r#"
+//- minicore: fmt
 fn main() {
     print!("{obj.value:b}$0",);
 }
 "#,
-            ),
-            &add_macro_decl(
-                r#"
+            r#"
 fn main() {
     print!("{:b}"$0, obj.value);
 }
 "#,
-            ),
         );
     }
 
@@ -217,20 +191,17 @@ fn main() {
     fn multiple_middle_placeholders_arg() {
         check_assist(
             extract_expressions_from_format_string,
-            &add_macro_decl(
-                r#"
+            r#"
+//- minicore: fmt
 fn main() {
     print!("{} {x + 1:b} {} {}$0", y + 2, 2);
 }
 "#,
-            ),
-            &add_macro_decl(
-                r#"
+            r#"
 fn main() {
     print!("{} {:b} {} {}"$0, y + 2, x + 1, 2, $1);
 }
 "#,
-            ),
         );
     }
 
@@ -238,20 +209,17 @@ fn main() {
     fn multiple_trailing_args() {
         check_assist(
             extract_expressions_from_format_string,
-            &add_macro_decl(
-                r#"
+            r#"
+//- minicore: fmt
 fn main() {
     print!("{:b} {x + 1:b} {Struct(1, 2)}$0", 1);
 }
 "#,
-            ),
-            &add_macro_decl(
-                r#"
+            r#"
 fn main() {
     print!("{:b} {:b} {}"$0, 1, x + 1, Struct(1, 2));
 }
 "#,
-            ),
         );
     }
 
@@ -259,20 +227,17 @@ fn main() {
     fn improper_commas() {
         check_assist(
             extract_expressions_from_format_string,
-            &add_macro_decl(
-                r#"
+            r#"
+//- minicore: fmt
 fn main() {
     print!("{} {x + 1:b} {Struct(1, 2)}$0", 1,);
 }
 "#,
-            ),
-            &add_macro_decl(
-                r#"
+            r#"
 fn main() {
     print!("{} {:b} {}"$0, 1, x + 1, Struct(1, 2));
 }
 "#,
-            ),
         );
     }
 
@@ -280,20 +245,17 @@ fn main() {
     fn nested_tt() {
         check_assist(
             extract_expressions_from_format_string,
-            &add_macro_decl(
-                r#"
+            r#"
+//- minicore: fmt
 fn main() {
     print!("My name is {} {x$0 + x}", stringify!(Paperino))
 }
 "#,
-            ),
-            &add_macro_decl(
-                r#"
+            r#"
 fn main() {
     print!("My name is {} {}"$0, stringify!(Paperino), x + x)
 }
 "#,
-            ),
         );
     }
 
@@ -301,22 +263,19 @@ fn main() {
     fn extract_only_expressions() {
         check_assist(
             extract_expressions_from_format_string,
-            &add_macro_decl(
-                r#"
+            r#"
+//- minicore: fmt
 fn main() {
     let var = 1 + 1;
     print!("foobar {var} {var:?} {x$0 + x}")
 }
 "#,
-            ),
-            &add_macro_decl(
-                r#"
+            r#"
 fn main() {
     let var = 1 + 1;
     print!("foobar {var} {var:?} {}"$0, x + x)
 }
 "#,
-            ),
         );
     }
 }
diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs
index 6eadc3dbcbc..8bd87e5f5db 100644
--- a/crates/ide-assists/src/tests/generated.rs
+++ b/crates/ide-assists/src/tests/generated.rs
@@ -694,25 +694,12 @@ fn doctest_extract_expressions_from_format_string() {
     check_doc_test(
         "extract_expressions_from_format_string",
         r#####"
-macro_rules! format_args {
-    ($lit:literal $(tt:tt)*) => { 0 },
-}
-macro_rules! print {
-    ($($arg:tt)*) => (std::io::_print(format_args!($($arg)*)));
-}
-
+//- minicore: fmt
 fn main() {
     print!("{var} {x + 1}$0");
 }
 "#####,
         r#####"
-macro_rules! format_args {
-    ($lit:literal $(tt:tt)*) => { 0 },
-}
-macro_rules! print {
-    ($($arg:tt)*) => (std::io::_print(format_args!($($arg)*)));
-}
-
 fn main() {
     print!("{var} {}"$0, x + 1);
 }
diff --git a/crates/ide-completion/src/completions/format_string.rs b/crates/ide-completion/src/completions/format_string.rs
index 8e904fd605a..cecbe75391d 100644
--- a/crates/ide-completion/src/completions/format_string.rs
+++ b/crates/ide-completion/src/completions/format_string.rs
@@ -51,9 +51,7 @@ mod tests {
     fn works_when_wrapped() {
         check(
             r#"
-macro_rules! format_args {
-    ($lit:literal $(tt:tt)*) => { 0 },
-}
+//- minicore: fmt
 macro_rules! print {
     ($($arg:tt)*) => (std::io::_print(format_args!($($arg)*)));
 }
@@ -70,9 +68,7 @@ fn main() {
     fn no_completion_without_brace() {
         check(
             r#"
-macro_rules! format_args {
-    ($lit:literal $(tt:tt)*) => { 0 },
-}
+//- minicore: fmt
 fn main() {
     let foobar = 1;
     format_args!("f$0");
@@ -87,18 +83,13 @@ fn main() {
         check_edit(
             "foobar",
             r#"
-macro_rules! format_args {
-    ($lit:literal $(tt:tt)*) => { 0 },
-}
+//- minicore: fmt
 fn main() {
     let foobar = 1;
     format_args!("{f$0");
 }
 "#,
             r#"
-macro_rules! format_args {
-    ($lit:literal $(tt:tt)*) => { 0 },
-}
 fn main() {
     let foobar = 1;
     format_args!("{foobar");
@@ -108,18 +99,13 @@ fn main() {
         check_edit(
             "foobar",
             r#"
-macro_rules! format_args {
-    ($lit:literal $(tt:tt)*) => { 0 },
-}
+//- minicore: fmt
 fn main() {
     let foobar = 1;
     format_args!("{$0");
 }
 "#,
             r#"
-macro_rules! format_args {
-    ($lit:literal $(tt:tt)*) => { 0 },
-}
 fn main() {
     let foobar = 1;
     format_args!("{foobar");
diff --git a/crates/ide-db/src/syntax_helpers/format_string.rs b/crates/ide-db/src/syntax_helpers/format_string.rs
index acf0a67de4a..8302b015dda 100644
--- a/crates/ide-db/src/syntax_helpers/format_string.rs
+++ b/crates/ide-db/src/syntax_helpers/format_string.rs
@@ -1,10 +1,10 @@
 //! Tools to work with format string literals for the `format_args!` family of macros.
-use crate::syntax_helpers::node_ext::macro_call_for_string_token;
 use syntax::{
     ast::{self, IsString},
-    TextRange, TextSize,
+    AstNode, AstToken, TextRange, TextSize,
 };
 
+// FIXME: This can probably be re-implemented via the HIR?
 pub fn is_format_string(string: &ast::String) -> bool {
     // Check if `string` is a format string argument of a macro invocation.
     // `string` is a string literal, mapped down into the innermost macro expansion.
@@ -15,19 +15,9 @@ pub fn is_format_string(string: &ast::String) -> bool {
     // This setup lets us correctly highlight the components of `concat!("{}", "bla")` format
     // strings. It still fails for `concat!("{", "}")`, but that is rare.
     (|| {
-        let name = macro_call_for_string_token(string)?.path()?.segment()?.name_ref()?;
-
-        if !matches!(
-            name.text().as_str(),
-            "format_args" | "format_args_nl" | "const_format_args" | "panic_2015" | "panic_2021"
-        ) {
-            return None;
-        }
-
-        // NB: we match against `panic_2015`/`panic_2021` here because they have a special-cased arm for
-        // `"{}"`, which otherwise wouldn't get highlighted.
-
-        Some(())
+        let lit = string.syntax().parent().and_then(ast::Literal::cast)?;
+        let fa = lit.syntax().parent().and_then(ast::FormatArgsExpr::cast)?;
+        (fa.template()? == ast::Expr::Literal(lit)).then_some(|| ())
     })()
     .is_some()
 }
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index d0f9f7b0e16..81d6db564ff 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -6574,3 +6574,23 @@ fn test() {
         "#]],
     );
 }
+
+#[test]
+fn format_args_arg() {
+    check(
+        r#"
+//- minicore: fmt
+fn test() {
+    let foo = 0;
+    format_args!("{}", foo$0);
+}
+"#,
+        expect![[r#"
+            *foo*
+
+            ```rust
+            let foo: i32 // size = 4, align = 4
+            ```
+        "#]],
+    );
+}
diff --git a/crates/ide/src/inlay_hints/chaining.rs b/crates/ide/src/inlay_hints/chaining.rs
index b621a8dda7e..8207bec7e89 100644
--- a/crates/ide/src/inlay_hints/chaining.rs
+++ b/crates/ide/src/inlay_hints/chaining.rs
@@ -474,7 +474,7 @@ fn main() {
                                         file_id: FileId(
                                             1,
                                         ),
-                                        range: 9289..9297,
+                                        range: 10739..10747,
                                     },
                                 ),
                                 tooltip: "",
@@ -487,7 +487,7 @@ fn main() {
                                         file_id: FileId(
                                             1,
                                         ),
-                                        range: 9321..9325,
+                                        range: 10771..10775,
                                     },
                                 ),
                                 tooltip: "",
@@ -511,7 +511,7 @@ fn main() {
                                         file_id: FileId(
                                             1,
                                         ),
-                                        range: 9289..9297,
+                                        range: 10739..10747,
                                     },
                                 ),
                                 tooltip: "",
@@ -524,7 +524,7 @@ fn main() {
                                         file_id: FileId(
                                             1,
                                         ),
-                                        range: 9321..9325,
+                                        range: 10771..10775,
                                     },
                                 ),
                                 tooltip: "",
@@ -548,7 +548,7 @@ fn main() {
                                         file_id: FileId(
                                             1,
                                         ),
-                                        range: 9289..9297,
+                                        range: 10739..10747,
                                     },
                                 ),
                                 tooltip: "",
@@ -561,7 +561,7 @@ fn main() {
                                         file_id: FileId(
                                             1,
                                         ),
-                                        range: 9321..9325,
+                                        range: 10771..10775,
                                     },
                                 ),
                                 tooltip: "",
diff --git a/crates/ide/src/syntax_highlighting/format.rs b/crates/ide/src/syntax_highlighting/format.rs
index 2ed57e20130..2ef1315945a 100644
--- a/crates/ide/src/syntax_highlighting/format.rs
+++ b/crates/ide/src/syntax_highlighting/format.rs
@@ -17,6 +17,7 @@ pub(super) fn highlight_format_string(
         return;
     }
 
+    // FIXME: Replace this with the HIR info we have now.
     lex_format_specifiers(string, &mut |piece_range, kind| {
         if let Some(highlight) = highlight_format_specifier(kind) {
             stack.add(HlRange {
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs
index 8e96bfa01ad..7d00282fc14 100644
--- a/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/crates/ide/src/syntax_highlighting/highlight.rs
@@ -617,6 +617,7 @@ fn highlight_name_by_syntax(name: ast::Name) -> Highlight {
         CONST => SymbolKind::Const,
         STATIC => SymbolKind::Static,
         IDENT_PAT => SymbolKind::Local,
+        FORMAT_ARGS_ARG => SymbolKind::Local,
         _ => return default.into(),
     };
 
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
index 9c5c6d50ea7..64e614cecd2 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
@@ -45,17 +45,11 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 </style>
 <pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">println</span> <span class="brace">{</span>
     <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span><span class="brace">{</span>
-        <span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>io<span class="colon">:</span><span class="colon">:</span>_print<span class="parenthesis">(</span><span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>format_args_nl<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+        <span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>io<span class="colon">:</span><span class="colon">:</span>_print<span class="parenthesis">(</span>format_args_nl<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="brace">}</span><span class="parenthesis">)</span>
 <span class="brace">}</span>
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">rustc_builtin_macro</span><span class="attribute_bracket attribute">]</span>
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">macro_export</span><span class="attribute_bracket attribute">]</span>
-<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">format_args</span> <span class="brace">{</span><span class="brace">}</span>
-<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">rustc_builtin_macro</span><span class="attribute_bracket attribute">]</span>
-<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">macro_export</span><span class="attribute_bracket attribute">]</span>
-<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">const_format_args</span> <span class="brace">{</span><span class="brace">}</span>
-<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">rustc_builtin_macro</span><span class="attribute_bracket attribute">]</span>
-<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">macro_export</span><span class="attribute_bracket attribute">]</span>
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">format_args_nl</span> <span class="brace">{</span><span class="brace">}</span>
 
 <span class="keyword">mod</span> <span class="module declaration">panic</span> <span class="brace">{</span>
@@ -75,7 +69,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
             <span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panicking<span class="colon">:</span><span class="colon">:</span>panic_display<span class="parenthesis">(</span><span class="punctuation">&</span><span class="punctuation">$</span>arg<span class="parenthesis">)</span>
         <span class="parenthesis">)</span><span class="comma">,</span>
         <span class="parenthesis">(</span><span class="punctuation">$</span>fmt<span class="colon">:</span>expr<span class="comma">,</span> <span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">+</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span>
-            <span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panicking<span class="colon">:</span><span class="colon">:</span>panic_fmt<span class="parenthesis">(</span><span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>const_format_args<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span>fmt<span class="comma">,</span> <span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="parenthesis">)</span><span class="punctuation">+</span><span class="parenthesis">)</span><span class="parenthesis">)</span>
+            <span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panicking<span class="colon">:</span><span class="colon">:</span>panic_fmt<span class="parenthesis">(</span>const_format_args<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span>fmt<span class="comma">,</span> <span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="parenthesis">)</span><span class="punctuation">+</span><span class="parenthesis">)</span><span class="parenthesis">)</span>
         <span class="parenthesis">)</span><span class="comma">,</span>
     <span class="brace">}</span>
 <span class="brace">}</span>
@@ -92,7 +86,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">toho</span> <span class="brace">{</span>
     <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span><span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panic<span class="punctuation">!</span><span class="parenthesis">(</span><span class="string_literal">"not yet implemented"</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
-    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">+</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span><span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panic<span class="punctuation">!</span><span class="parenthesis">(</span><span class="string_literal">"not yet implemented: {}"</span><span class="comma">,</span> <span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>format_args<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="parenthesis">)</span><span class="punctuation">+</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">+</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span><span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panic<span class="punctuation">!</span><span class="parenthesis">(</span><span class="string_literal">"not yet implemented: {}"</span><span class="comma">,</span> format_args<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="parenthesis">)</span><span class="punctuation">+</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 
 <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
@@ -114,18 +108,18 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"world"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>   <span class="comment">// =&gt; "Hello, world!"</span>
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"The number is </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>   <span class="comment">// =&gt; "The number is 1"</span>
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">?</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="parenthesis macro">(</span><span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="numeric_literal macro">4</span><span class="parenthesis macro">)</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>          <span class="comment">// =&gt; "(3, 4)"</span>
-    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">value</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="none macro">value</span><span class="operator macro">=</span><span class="numeric_literal macro">4</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>      <span class="comment">// =&gt; "4"</span>
+    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">value</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">value</span><span class="operator macro">=</span><span class="numeric_literal macro">4</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>      <span class="comment">// =&gt; "4"</span>
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="comma macro">,</span> <span class="numeric_literal macro">2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>           <span class="comment">// =&gt; "1 2"</span>
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">4</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">42</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>             <span class="comment">// =&gt; "0042" with leading zerosV</span>
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="comma macro">,</span> <span class="numeric_literal macro">2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>   <span class="comment">// =&gt; "2 1 1 2"</span>
-    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">argument</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="none macro">argument</span> <span class="operator macro">=</span> <span class="string_literal macro">"test"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>   <span class="comment">// =&gt; "test"</span>
-    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="comma macro">,</span> <span class="none macro">name</span> <span class="operator macro">=</span> <span class="numeric_literal macro">2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>          <span class="comment">// =&gt; "2 1"</span>
-    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">a</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">c</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">b</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="none macro">a</span><span class="operator macro">=</span><span class="string_literal macro">"a"</span><span class="comma macro">,</span> <span class="none macro">b</span><span class="operator macro">=</span><span class="char_literal macro">'b'</span><span class="comma macro">,</span> <span class="none macro">c</span><span class="operator macro">=</span><span class="numeric_literal macro">3</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>  <span class="comment">// =&gt; "a 3 b"</span>
+    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">argument</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">argument</span> <span class="operator macro">=</span> <span class="string_literal macro">"test"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>   <span class="comment">// =&gt; "test"</span>
+    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span> <span class="operator macro">=</span> <span class="numeric_literal macro">2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>          <span class="comment">// =&gt; "2 1"</span>
+    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">a</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">c</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">b</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">a</span><span class="operator macro">=</span><span class="string_literal macro">"a"</span><span class="comma macro">,</span> <span class="variable declaration macro">b</span><span class="operator macro">=</span><span class="char_literal macro">'b'</span><span class="comma macro">,</span> <span class="variable declaration macro">c</span><span class="operator macro">=</span><span class="numeric_literal macro">3</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>  <span class="comment">// =&gt; "a 3 b"</span>
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>                       <span class="comment">// =&gt; "{2}"</span>
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">width</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="none macro">width</span> <span class="operator macro">=</span> <span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">width</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="variable declaration macro">width</span> <span class="operator macro">=</span> <span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">&lt;</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">-</span><span class="format_specifier">&lt;</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">^</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
@@ -140,10 +134,10 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span>    <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span>   <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="variable">number</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="variable">prec</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="none macro">prec</span> <span class="operator macro">=</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="none macro">number</span> <span class="operator macro">=</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 fractional digits"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="none macro">name</span><span class="operator macro">=</span><span class="numeric_literal macro">1234.56</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 characters"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="none macro">name</span><span class="operator macro">=</span><span class="string_literal macro">"1234.56"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">&gt;</span><span class="numeric_literal">8</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 right-aligned characters"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="none macro">name</span><span class="operator macro">=</span><span class="string_literal macro">"1234.56"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="variable">number</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="variable">prec</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="variable declaration macro">prec</span> <span class="operator macro">=</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="variable declaration macro">number</span> <span class="operator macro">=</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 fractional digits"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span><span class="operator macro">=</span><span class="numeric_literal macro">1234.56</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 characters"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span><span class="operator macro">=</span><span class="string_literal macro">"1234.56"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">&gt;</span><span class="numeric_literal">8</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 right-aligned characters"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span><span class="operator macro">=</span><span class="string_literal macro">"1234.56"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
 
     <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">"{}"</span>
     <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">"{{}}"</span><span class="semicolon">;</span>
@@ -167,24 +161,24 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">c"</span><span class="escape_sequence">\u{FF}</span><span class="escape_sequence">\xFF</span><span class="string_literal">"</span><span class="semicolon">;</span> <span class="comment">// valid bytes, valid unicodes</span>
     <span class="keyword">let</span> <span class="variable declaration reference">backslash</span> <span class="operator">=</span> <span class="string_literal">r"\\"</span><span class="semicolon">;</span>
 
-    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="escape_sequence">\x41</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="none macro">A</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">ничоси</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="none macro">ничоси</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="escape_sequence">\x41</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">A</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">ничоси</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">ничоси</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
 
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">x</span><span class="format_specifier">?</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> "</span><span class="comma macro">,</span> <span class="unresolved_reference macro">thingy</span><span class="comma macro">,</span> <span class="unresolved_reference macro">n2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro">panic</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro">panic</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"more </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro">assert</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="bool_literal macro">true</span><span class="comma macro">,</span> <span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro">assert</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="bool_literal macro">true</span><span class="comma macro">,</span> <span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> asdasd"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro">toho</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">fmt"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro">panic</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"{}"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro">panic</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"more {}"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro">assert</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="bool_literal macro">true</span><span class="comma macro">,</span> <span class="string_literal macro">"{}"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro">assert</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="bool_literal macro">true</span><span class="comma macro">,</span> <span class="string_literal macro">"{} asdasd"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro">toho</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"{}fmt"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
     <span class="keyword">let</span> <span class="variable declaration">i</span><span class="colon">:</span> <span class="builtin_type">u64</span> <span class="operator">=</span> <span class="numeric_literal">3</span><span class="semicolon">;</span>
     <span class="keyword">let</span> <span class="variable declaration">o</span><span class="colon">:</span> <span class="builtin_type">u64</span><span class="semicolon">;</span>
     <span class="macro unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>
-        <span class="string_literal macro">"mov </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro">, </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span>
-        <span class="string_literal macro">"add </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro">, 5"</span><span class="comma macro">,</span>
+        <span class="string_literal macro">"mov {0}, {1}"</span><span class="comma macro">,</span>
+        <span class="string_literal macro">"add {0}, 5"</span><span class="comma macro">,</span>
         <span class="none macro">out</span><span class="parenthesis macro">(</span><span class="none macro">reg</span><span class="parenthesis macro">)</span> <span class="none macro">o</span><span class="comma macro">,</span>
         <span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="none macro">reg</span><span class="parenthesis macro">)</span> <span class="none macro">i</span><span class="comma macro">,</span>
     <span class="parenthesis macro">)</span><span class="semicolon">;</span>
 
-    <span class="macro">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">concat</span><span class="punctuation macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="string_literal macro">"{}"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="comma macro">,</span> <span class="none macro">format_args</span><span class="punctuation macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="unresolved_reference macro">foo</span><span class="comma macro">,</span> <span class="string_literal macro">"bar"</span><span class="comma macro">,</span> <span class="none macro">toho</span><span class="punctuation macro">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="macro macro">concat</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"{}"</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="string_literal macro">"{}"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="comma macro">,</span> <span class="macro default_library library macro">format_args</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="unresolved_reference macro">foo</span><span class="comma macro">,</span> <span class="string_literal macro">"bar"</span><span class="comma macro">,</span> <span class="macro macro">toho</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
 <span class="brace">}</span></code></pre>
\ No newline at end of file
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs
index aacd57af589..542d8992531 100644
--- a/crates/ide/src/syntax_highlighting/tests.rs
+++ b/crates/ide/src/syntax_highlighting/tests.rs
@@ -401,19 +401,14 @@ fn test_string_highlighting() {
     // thus, we have to copy the macro definition from `std`
     check_highlighting(
         r#"
+//- minicore: fmt
 macro_rules! println {
     ($($arg:tt)*) => ({
-        $crate::io::_print($crate::format_args_nl!($($arg)*));
+        $crate::io::_print(format_args_nl!($($arg)*));
     })
 }
 #[rustc_builtin_macro]
 #[macro_export]
-macro_rules! format_args {}
-#[rustc_builtin_macro]
-#[macro_export]
-macro_rules! const_format_args {}
-#[rustc_builtin_macro]
-#[macro_export]
 macro_rules! format_args_nl {}
 
 mod panic {
@@ -433,7 +428,7 @@ mod panic {
             $crate::panicking::panic_display(&$arg)
         ),
         ($fmt:expr, $($arg:tt)+) => (
-            $crate::panicking::panic_fmt($crate::const_format_args!($fmt, $($arg)+))
+            $crate::panicking::panic_fmt(const_format_args!($fmt, $($arg)+))
         ),
     }
 }
@@ -450,7 +445,7 @@ macro_rules! concat {}
 
 macro_rules! toho {
     () => ($crate::panic!("not yet implemented"));
-    ($($arg:tt)+) => ($crate::panic!("not yet implemented: {}", $crate::format_args!($($arg)+)));
+    ($($arg:tt)+) => ($crate::panic!("not yet implemented: {}", format_args!($($arg)+)));
 }
 
 fn main() {
diff --git a/crates/test-utils/src/minicore.rs b/crates/test-utils/src/minicore.rs
index 0fc95635e66..573f56b003a 100644
--- a/crates/test-utils/src/minicore.rs
+++ b/crates/test-utils/src/minicore.rs
@@ -1352,8 +1352,6 @@ mod macros {
             /* compiler built-in */
         };
     }
-
-    pub(crate) use panic;
     // endregion:panic
 
     // region:fmt
@@ -1364,7 +1362,20 @@ mod macros {
         ($fmt:expr, $($args:tt)*) => {{ /* compiler built-in */ }};
     }
 
-    pub(crate) use const_format_args;
+    #[macro_export]
+    #[rustc_builtin_macro]
+    macro_rules! format_args {
+        ($fmt:expr) => {{ /* compiler built-in */ }};
+        ($fmt:expr, $($args:tt)*) => {{ /* compiler built-in */ }};
+    }
+
+    #[macro_export]
+    macro_rules! print {
+        ($($arg:tt)*) => {{
+            $crate::io::_print($crate::format_args!($($arg)*));
+        }};
+    }
+
     // endregion:fmt
 
     // region:derive