Discussion: Adding grammar information to Procedural Macros for proper custom syntax support in the toolchain

Actually, it's already the case that a macro invoked as macro!() will have its arguments formatted if they look like fully syntactically valid Rust code. (Though the exact rules as to what syntax is allowed can be a little opaque.) Invocations as macro!{} get left as-is. I don't see/use macro![] enough to determine what heuristics it uses for when to format its arguments.

I've been bit by rustfmt deciding to remove a for<T> from a macro invocation for some reason before. It quietly just works most of the time and its only really noticable when things go wrong or suddenly change.

Try running rustfmt on this example.

input
macro_rules! m {($($t:tt)*) => {}}

m!(
    fn f ( ) -> i32 { 0 }
);

m!{
    fn f ( ) -> i32 { 0 }
}

m![
    fn f ( ) -> i32 { 0 }
];
output
macro_rules! m {
    ($($t:tt)*) => {};
}

m!(
    fn f() -> i32 {
        0
    }
);

m! {
    fn f ( ) -> i32 { 0 }
}

m![
    fn f() -> i32 {
        0
    }
];
2 Likes

For Slint, I have developed at LSP server. Some editors such as vscode support having several language servers for the same file. So rust-analyzer takes care of everything, while slint-lsp takes care of what is in the slint! macro.

Oh, interesting... thanks for clarifying that for me.

I'd somehow convinced myself that it was the case that eprintln! wasn't formatted correctly, but others are, but now that I'm actually testing that hypothesis I see that I was wrong.

... I guess I'll have to keep a closer eye on when rustfmt doesn't do anything. I didn't think we used brace-style macros in our code that much, but maybe we do more than I realize.

For a small (or even a complex, self-contained) DSL such as JSON or Slint, this approach of using a separate formatter makes a great deal of sense. For something like impl_scope! (essentially just Rust with a couple of tweaks), it doesn't.

This approach would be simpler and likely be sufficient for impl_scope! (some macro input might be rejected by a strict Rust parser, but most would not be).