Repository: tokio-rs/tracing (Rust)

Issue:
v0.1.20 causes issues with Tonic
## Bug Report

### Version

* tracing v0.1.20

### Crates

* tracing

### Description

Upgrading from tracing 0.1.19 to 0.1.20 causes tonic to no longer build with the following error:

Reproduction steps:

```
$ cargo new example && cd example
$ cargo add tonic
$ cargo add tracing
$ cargo build
```

Build output:

```
~/.cargo/registry/src/github.com-1ecc6299db9ec823/tower-balance-0.3.0/src/pool/mod.rs:407:21
    |
399 |         let discover = self.balance.discover_mut().as_mut().project();
    |                        ------------ mutable borrow occurs here
...
407 |                     tracing::trace!({ ewma = %self.ewma }, "pool is under-provisioned");
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |                     |                         |
    |                     |                         second borrow occurs due to use of `self` in closure
    |                     immutable borrow occurs here
408 |                 }
409 |                 *discover.load = Level::High;
    |                 ---------------------------- mutable borrow later used here
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

```


Discussion:
Thanks. I think this is not specific to `tonic` but potentially an issue with the way closures are now used to capture values in #943. This might be an interaction with the code generated by pin-project, or just something we missed with the tests for various kinds of macro invocations.

I went ahead and yanked 0.1.20 so we don't break any more builds until this is fixed.



Patch:
diff --git a/tracing/src/lib.rs b/tracing/src/lib.rs
index 6ae17e085a..ea6e1fb5a8 100644
--- a/tracing/src/lib.rs
+++ b/tracing/src/lib.rs
@@ -1000,12 +1000,9 @@ pub mod __macro_support {
             }
         }
 
-        pub fn dispatch_event(&'static self, interest: Interest, f: impl FnOnce(&crate::Dispatch)) {
-            tracing_core::dispatcher::get_current(|current| {
-                if interest.is_always() || current.enabled(self.meta) {
-                    f(current)
-                }
-            });
+        pub fn is_enabled(&self, interest: Interest) -> bool {
+            interest.is_always()
+                || crate::dispatcher::get_default(|default| default.enabled(self.meta))
         }
 
         #[inline]
@@ -1019,24 +1016,6 @@ pub mod __macro_support {
         pub fn disabled_span(&self) -> crate::Span {
             crate::Span::none()
         }
-
-        pub fn dispatch_span(
-            &'static self,
-            interest: Interest,
-            f: impl FnOnce(&crate::Dispatch) -> crate::Span,
-        ) -> crate::Span {
-            if interest.is_never() {
-                return self.disabled_span();
-            }
-
-            tracing_core::dispatcher::get_current(|current| {
-                if interest.is_always() || current.enabled(self.meta) {
-                    return f(current);
-                }
-                self.disabled_span()
-            })
-            .unwrap_or_else(|| self.disabled_span())
-        }
     }
 
     impl Callsite for MacroCallsite {
diff --git a/tracing/src/macros.rs b/tracing/src/macros.rs
index a3e646d4d8..6d2c1707db 100644
--- a/tracing/src/macros.rs
+++ b/tracing/src/macros.rs
@@ -32,17 +32,17 @@ macro_rules! span {
                 fields: $($fields)*
             };
             let mut interest = $crate::subscriber::Interest::never();
-            if $crate::level_enabled!($lvl) && { interest = CALLSITE.interest(); !interest.is_never() }{
-                CALLSITE.dispatch_span(interest, |current| {
-                    let meta = CALLSITE.metadata();
-                    // span with parent
-                    $crate::Span::child_of_with(
-                        $parent,
-                        meta,
-                        &$crate::valueset!(CALLSITE.metadata().fields(), $($fields)*),
-                        current,
-                    )
-                })
+            if $crate::level_enabled!($lvl)
+                && { interest = CALLSITE.interest(); !interest.is_never() }
+                && CALLSITE.is_enabled(interest)
+            {
+                let meta = CALLSITE.metadata();
+                // span with explicit parent
+                $crate::Span::child_of(
+                    $parent,
+                    meta,
+                    &$crate::valueset!(meta.fields(), $($fields)*),
+                )
             } else {
                 let span = CALLSITE.disabled_span();
                 $crate::if_log_enabled! {{
@@ -63,15 +63,16 @@ macro_rules! span {
                 fields: $($fields)*
             };
             let mut interest = $crate::subscriber::Interest::never();
-            if $crate::level_enabled!($lvl) && { interest = CALLSITE.interest(); !interest.is_never() }{
-                CALLSITE.dispatch_span(interest, |current| {
-                    let meta = CALLSITE.metadata();
-                    $crate::Span::new_with(
-                        meta,
-                        &$crate::valueset!(CALLSITE.metadata().fields(), $($fields)*),
-                        current,
-                    )
-                })
+            if $crate::level_enabled!($lvl)
+                && { interest = CALLSITE.interest(); !interest.is_never() }
+                && CALLSITE.is_enabled(interest)
+            {
+                let meta = CALLSITE.metadata();
+                // span with contextual parent
+                $crate::Span::new(
+                    meta,
+                    &$crate::valueset!(meta.fields(), $($fields)*),
+                )
             } else {
                 let span = CALLSITE.disabled_span();
                 $crate::if_log_enabled! {{
@@ -605,11 +606,14 @@ macro_rules! event {
                 fields: $($fields)*
             };
             let interest = CALLSITE.interest();
-            if !interest.is_never() {
-                CALLSITE.dispatch_event(interest, |current| {
-                    let meta = CALLSITE.metadata();
-                    current.event(&$crate::Event::new_child_of($parent, meta, &$crate::valueset!(meta.fields(), $($fields)*)))
-                });
+            if !interest.is_never() && CALLSITE.is_enabled(interest)  {
+                let meta = CALLSITE.metadata();
+                // event with explicit parent
+                $crate::Event::child_of(
+                    $parent,
+                    meta,
+                    &$crate::valueset!(meta.fields(), $($fields)*)
+                );
             }
         }
     );
@@ -649,11 +653,13 @@ macro_rules! event {
                 fields: $($fields)*
             };
             let interest = CALLSITE.interest();
-            if !interest.is_never() {
-                CALLSITE.dispatch_event(interest, |current| {
-                    let meta = CALLSITE.metadata();
-                    current.event(&$crate::Event::new(meta, &$crate::valueset!(meta.fields(), $($fields)*)));
-                });
+            if !interest.is_never() && CALLSITE.is_enabled(interest)  {
+                let meta = CALLSITE.metadata();
+                // event with contextual parent
+                $crate::Event::dispatch(
+                    meta,
+                    &$crate::valueset!(meta.fields(), $($fields)*)
+                );
             }
         }
     });


Test patch:
diff --git a/tracing/tests/macros.rs b/tracing/tests/macros.rs
index 33ef33e9d7..39642667f7 100644
--- a/tracing/tests/macros.rs
+++ b/tracing/tests/macros.rs
@@ -836,6 +836,34 @@ fn field_shorthand_only() {
     event!(Level::TRACE, ?pos.x, ?pos.y);
 }
 
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
+#[test]
+fn borrow_val_events() {
+    // Reproduces https://github.com/tokio-rs/tracing/issues/954
+    let mut foo = (String::new(), String::new());
+    let zero = &mut foo.0;
+    trace!(one = ?foo.1);
+    debug!(one = ?foo.1);
+    info!(one = ?foo.1);
+    warn!(one = ?foo.1);
+    error!(one = ?foo.1);
+    zero.push_str("hello world");
+}
+
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
+#[test]
+fn borrow_val_spans() {
+    // Reproduces https://github.com/tokio-rs/tracing/issues/954
+    let mut foo = (String::new(), String::new());
+    let zero = &mut foo.0;
+    let _span = trace_span!("span", one = ?foo.1);
+    let _span = debug_span!("span", one = ?foo.1);
+    let _span = info_span!("span", one = ?foo.1);
+    let _span = warn_span!("span", one = ?foo.1);
+    let _span = error_span!("span", one = ?foo.1);
+    zero.push_str("hello world");
+}
+
 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
 #[test]
 fn callsite_macro_api() {