Skip to content

Commit

Permalink
macros: allow field path segments to be keywords (#2925)
Browse files Browse the repository at this point in the history
## Motivation

Currently, a keyword like `type` fails compilation as (a path segment of) a field name, for no clear reason. Trying to use `r#type` instead leads to the `r#` being part of the field name, which is unhelpful¹. 

## Solution

Don't require the field path to match a `macro_rules!` `expr`, use repeated `tt` instead. I can't tell why this was ever required: The internal stringify macro was introduced in 55091c9#diff-315c02cd05738da173861537577d159833f70f79cfda8cd7cf1a0d7a28ace31b with an `expr` matcher without any explanation, and no tests are failing from making it match upstream's `stringify!` input format.

Special thanks to whoever implemented the unstable `macro-backtrace` feature in rustc, otherwise this would have been nigh impossible to track down!

¹ this can likely be fixed too by some sort of "unraw" macro that turns `r#foo` into `foo`, but that's a separate change not made in this PR
  • Loading branch information
svix-jplatte committed Jul 5, 2024
1 parent ba387dd commit 44861ca
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 2 deletions.
13 changes: 13 additions & 0 deletions tracing-attributes/tests/fields.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ fn fn_string(s: String) {
let _ = s;
}

#[instrument(fields(keywords.impl.type.fn = _arg), skip(_arg))]
fn fn_keyword_ident_in_field(_arg: &str) {}

#[derive(Debug)]
struct HasField {
my_field: &'static str,
Expand Down Expand Up @@ -146,6 +149,16 @@ fn string_field() {
});
}

#[test]
fn keyword_ident_in_field_name() {
let span = expect::span().with_fields(
expect::field("keywords.impl.type.fn")
.with_value(&"test")
.only(),
);
run_test(span, || fn_keyword_ident_in_field("test"));
}

fn run_test<F: FnOnce() -> T, T>(span: NewSpan, fun: F) {
let (collector, handle) = collector::mock()
.new_span(span)
Expand Down
4 changes: 2 additions & 2 deletions tracing/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3069,8 +3069,8 @@ macro_rules! level_to_log {
#[doc(hidden)]
#[macro_export]
macro_rules! __tracing_stringify {
($s:expr) => {
stringify!($s)
($($t:tt)*) => {
stringify!($($t)*)
};
}

Expand Down
12 changes: 12 additions & 0 deletions tracing/tests/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,3 +497,15 @@ fn constant_field_name() {

handle.assert_finished();
}

#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
#[test]
fn keyword_ident_in_field_name() {
let (collector, handle) = collector::mock()
.event(expect::event().with_fields(expect::field("crate").with_value(&"tracing")))
.only()
.run_with_handle();

with_default(collector, || error!(crate = "tracing", "message"));
handle.assert_finished();
}
18 changes: 18 additions & 0 deletions tracing/tests/span.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::thread;

use tracing::{
collect::with_default,
error_span,
field::{debug, display},
Level, Span,
};
Expand Down Expand Up @@ -866,3 +867,20 @@ fn constant_field_name() {

handle.assert_finished();
}

#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
#[test]
fn keyword_ident_in_field_name_span_macro() {
#[derive(Debug)]
struct Foo;

let (collector, handle) = collector::mock()
.new_span(expect::span().with_fields(expect::field("self").with_value(&debug(Foo)).only()))
.only()
.run_with_handle();

with_default(collector, || {
error_span!("span", self = ?Foo);
});
handle.assert_finished();
}

0 comments on commit 44861ca

Please sign in to comment.