rustfmt
                                
                                 rustfmt copied to clipboard
                                
                                    rustfmt copied to clipboard
                            
                            
                            
                        Failing when macro has `%` in it, e.g. Tracing
Here's a sample code:
            TraceLayer::new_for_http()
                .make_span_with(|request: &Request<Body>| {
                    tracing::info_span!(
                        "request",
                        method = %request.method(),
                        uri = %request.uri(), status = tracing::field::Empty,
                        latency = tracing::field::Empty,
                    )
                })
this uses a macro from tracing to create the Span. However the % in there makes rustfmt fail.
Thanks for reaching out.  What version of rustfmt are you using? (run rustfmt --version to find out). I'm using rustfmt 1.5.1-nightly (38659ec6 2022-08-18), and can't reproduce any issues. Are you using any non default config options? Could you please post the larger code snippet.
$ rustfmt --version
rustfmt 1.5.1-stable (4b91a6e 2022-08-08)
reproducible examples: (add tracing = "0.1.36" to Cargo.toml)
fn main() {
    let span = tracing::info_span!("request", method = %request.method(), uri = %request.uri(), status = tracing::field::Empty, latency = tracing::field::Empty,);
}
fn main() {
    let span = tracing::info_span!(
        "request",
        method = %request.method(),
        uri = %request.uri(), status = tracing::field::Empty,
        latency = tracing::field::Empty,
    );
}
expected output:
fn main() {
    let span = tracing::info_span!(
        "request",
        method = %request.method(),
        uri = %request.uri(),
        status = tracing::field::Empty,
        latency = tracing::field::Empty,
    );
}
If you remove the % in examples, you'll get the same output as "expected", obviously without the %. Otherwise, rustfmt doesn't make any change to the two examples.
We actually don't need to to add tracing = "0.1.36" to Cargo.toml to reproduce. I understand now that the issue is that we're not formatting the macro at all, and unfortunately as things currently stand there's not much we can do. You're correct that the % are causing the issue.
Formatting macros is tricky as they can contain arbitrary tokens and in this case the % prevents us from parsing the macro args as valid rust code so we just emit the macro as is. rustfmt isn't programmed to handle cases where macro args don't parse as valid rust code e.g %request.
The only way to handle this would be to special case the info_span! macro and customize how we parse and format its args. Given the team's backlog this is an extremely low priority item.
I'm not familiar with the tracing::info_span! macro, and found some more details on the % by reading the Recorder Fields section of the docs. Looks like ? is also used sometimes.
I'lll just add that while ? is also used, it behaves slightly differently.
One can use any of the following with the first three being equivalent and the fourth through sixth being equivalent.
- o tracing::info!(?x, "text")
- x tracing::info!(x = ?x, "text")
- o tracing::info!(x = format!("{x:?}"), "text")
- x tracing::info!(%x, "text")
- x tracing::info!(x = %x, "text")
- o tracing::info!(x = format!("{x}"), "text")
Only the first, third, and sixth (with o in front of them) are being considered by rustfmt. I am somewhat surprised by the first one since that does not seem like valid rust syntax either.
In case this is done by making exception for the tracing macros, these are the macros I know of where this syntax is permissible:
List of macros
- span!
- debug_span!
- info_span!
- warn_span!
- error_span!
- event!
- debug!
- info!
- warn!
- error!
I'm seeing this issue on rustfmt 1.7.0-nightly (f9b16149 2024-04-19), mainly with the ? sigil rather than the %. It seems like not only does the macro itself not get formatted, neither does any of the surrounding code.
@saffaffi the Issues with ? and % are the same. rustfmt can only format a macro calls if it's able to parse their arguments as valid rust syntax. The ?x in the macro call tracing::info!(?x) isn't valid rust.
You won't notice the impact of rustfmt failing to format tracing::info!(?x) because you probably already expect that's how it should be formatted, however, in other cases failing to format a long macro could lead to surrounding code being left unformatted.
It would be best for you to open a new issue and provide a minimal code example that demonstrates the problem you're currently experiencing.