Upgrade tracing-core to 0.1.32 am: 745770d77e

Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/tracing-core/+/2950688

Change-Id: Ib94ef9a62fab5dd93118f81da31751d39c8efbb8
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
new file mode 100644
index 0000000..351e2f9
--- /dev/null
+++ b/.cargo_vcs_info.json
@@ -0,0 +1,6 @@
+{
+  "git": {
+    "sha1": "c4b2a56937dd40aaa2e2991636eca6748353201f"
+  },
+  "path_in_vcs": "tracing-core"
+}
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index 2f39599..dc4e580 100644
--- a/Android.bp
+++ b/Android.bp
@@ -23,7 +23,7 @@
     host_supported: true,
     crate_name: "tracing_core",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.1.30",
+    cargo_pkg_version: "0.1.32",
     srcs: ["src/lib.rs"],
     edition: "2018",
     features: [
@@ -46,7 +46,7 @@
     host_supported: true,
     crate_name: "tracing_core",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.1.30",
+    cargo_pkg_version: "0.1.32",
     srcs: ["src/lib.rs"],
     test_suites: ["general-tests"],
     auto_gen_config: true,
@@ -68,7 +68,7 @@
     host_supported: true,
     crate_name: "dispatch",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.1.30",
+    cargo_pkg_version: "0.1.32",
     srcs: ["tests/dispatch.rs"],
     test_suites: ["general-tests"],
     auto_gen_config: true,
@@ -93,7 +93,7 @@
     host_supported: true,
     crate_name: "global_dispatch",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.1.30",
+    cargo_pkg_version: "0.1.32",
     srcs: ["tests/global_dispatch.rs"],
     test_suites: ["general-tests"],
     auto_gen_config: true,
@@ -114,11 +114,36 @@
 }
 
 rust_test {
+    name: "tracing-core_test_tests_local_dispatch_before_init",
+    host_supported: true,
+    crate_name: "local_dispatch_before_init",
+    cargo_env_compat: true,
+    cargo_pkg_version: "0.1.32",
+    srcs: ["tests/local_dispatch_before_init.rs"],
+    test_suites: ["general-tests"],
+    auto_gen_config: true,
+    test_options: {
+        unit_test: true,
+    },
+    edition: "2018",
+    features: [
+        "default",
+        "once_cell",
+        "std",
+        "valuable",
+    ],
+    rustlibs: [
+        "libonce_cell",
+        "libtracing_core",
+    ],
+}
+
+rust_test {
     name: "tracing-core_test_tests_macros",
     host_supported: true,
     crate_name: "macros",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.1.30",
+    cargo_pkg_version: "0.1.32",
     srcs: ["tests/macros.rs"],
     test_suites: ["general-tests"],
     auto_gen_config: true,
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cf0d8e3..2e92f74 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,49 @@
+# 0.1.32 (October 13, 2023)
+
+### Documented
+
+- Fix typo in `field` docs ([#2611])
+- Remove duplicate wording ([#2674])
+
+### Changed
+
+- Allow `ValueSet`s of any length ([#2508])
+
+[#2611]: https://github.com/tokio-rs/tracing/pull/2611
+[#2674]: https://github.com/tokio-rs/tracing/pull/2674
+[#2508]: https://github.com/tokio-rs/tracing/pull/2508
+
+# 0.1.31 (May 11, 2023)
+
+This release of `tracing-core` fixes a bug that caused threads which call
+`dispatcher::get_default` _before_ a global default subscriber is set to never
+see the global default once it is set. In addition, it includes improvements for
+instrumentation performance in some cases, especially when using a global
+default dispatcher.
+
+### Fixed
+
+- Fixed incorrect thread-local caching of `Dispatch::none` if
+  `dispatcher::get_default` is called before `dispatcher::set_global_default`
+  ([#2593])
+
+### Changed
+
+- Cloning a `Dispatch` that points at a global default subscriber no longer
+  requires an `Arc` reference count increment, improving performance
+  substantially ([#2593])
+- `dispatcher::get_default` no longer attempts to access a thread local if the
+  scoped dispatcher is not in use, improving performance when the default
+  dispatcher is global ([#2593])
+- Added `#[inline]` annotations called by the `event!` and `span!` macros to
+  reduce the size of macro-generated code and improve recording performance
+  ([#2555])
+
+Thanks to new contributor @ldm0 for contributing to this release!
+
+[#2593]: https://github.com/tokio-rs/tracing/pull/2593
+[#2555]: https://github.com/tokio-rs/tracing/pull/2555
+
 # 0.1.30 (October 6, 2022)
 
 This release of `tracing-core` adds a new `on_register_dispatch` method to the
diff --git a/Cargo.toml b/Cargo.toml
index 8060061..961b391 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,9 +11,9 @@
 
 [package]
 edition = "2018"
-rust-version = "1.49.0"
+rust-version = "1.56.0"
 name = "tracing-core"
-version = "0.1.30"
+version = "0.1.32"
 authors = ["Tokio Contributors <team@tokio.rs>"]
 description = """
 Core primitives for application-level tracing.
@@ -35,13 +35,13 @@
 
 [package.metadata.docs.rs]
 all-features = true
-rustdoc-args = [
-    "--cfg",
-    "docsrs",
+rustc-args = [
     "--cfg",
     "tracing_unstable",
 ]
-rustc-args = [
+rustdoc-args = [
+    "--cfg",
+    "docsrs",
     "--cfg",
     "tracing_unstable",
 ]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index aacd334..a9ed02f 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -8,7 +8,7 @@
 #   - README.md
 # - Update CHANGELOG.md.
 # - Create "v0.1.x" git tag.
-version = "0.1.30"
+version = "0.1.32"
 authors = ["Tokio Contributors <team@tokio.rs>"]
 license = "MIT"
 readme = "README.md"
@@ -24,7 +24,7 @@
 ]
 keywords = ["logging", "tracing", "profiling"]
 edition = "2018"
-rust-version = "1.49.0"
+rust-version = "1.56.0"
 
 [features]
 default = ["std", "valuable/std"]
diff --git a/METADATA b/METADATA
index 374df14..6993fb6 100644
--- a/METADATA
+++ b/METADATA
@@ -1,19 +1,20 @@
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update external/rust/crates/tracing-core
+# For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md
+
 name: "tracing-core"
 description: "Core primitives for application-level tracing."
 third_party {
-  url {
-    type: HOMEPAGE
-    value: "https://crates.io/crates/tracing-core"
-  }
-  url {
-    type: ARCHIVE
-    value: "https://static.crates.io/crates/tracing-core/tracing-core-0.1.30.crate"
-  }
-  version: "0.1.30"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2023
-    month: 3
-    day: 3
+    year: 2024
+    month: 2
+    day: 6
+  }
+  homepage: "https://crates.io/crates/tracing-core"
+  identifier {
+    type: "Archive"
+    value: "https://static.crates.io/crates/tracing-core/tracing-core-0.1.32.crate"
+    version: "0.1.32"
   }
 }
diff --git a/README.md b/README.md
index f06c760..3655948 100644
--- a/README.md
+++ b/README.md
@@ -16,9 +16,9 @@
 [Documentation][docs-url] | [Chat][discord-url]
 
 [crates-badge]: https://img.shields.io/crates/v/tracing-core.svg
-[crates-url]: https://crates.io/crates/tracing-core/0.1.30
+[crates-url]: https://crates.io/crates/tracing-core/0.1.31
 [docs-badge]: https://docs.rs/tracing-core/badge.svg
-[docs-url]: https://docs.rs/tracing-core/0.1.30
+[docs-url]: https://docs.rs/tracing-core/0.1.31
 [docs-master-badge]: https://img.shields.io/badge/docs-master-blue
 [docs-master-url]: https://tracing-rs.netlify.com/tracing_core
 [mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
@@ -53,7 +53,7 @@
 In addition, it defines the global callsite registry and per-thread current
 dispatcher which other components of the tracing system rely on.
 
-*Compiler support: [requires `rustc` 1.49+][msrv]*
+*Compiler support: [requires `rustc` 1.56+][msrv]*
 
 [msrv]: #supported-rust-versions
 
@@ -79,34 +79,34 @@
 
   ```toml
   [dependencies]
-  tracing-core = { version = "0.1.30", default-features = false }
+  tracing-core = { version = "0.1.31", default-features = false }
   ```
 
   **Note**:`tracing-core`'s `no_std` support requires `liballoc`.
 
 [`tracing`]: ../tracing
-[`span::Id`]: https://docs.rs/tracing-core/0.1.30/tracing_core/span/struct.Id.html
-[`Event`]: https://docs.rs/tracing-core/0.1.30/tracing_core/event/struct.Event.html
-[`Subscriber`]: https://docs.rs/tracing-core/0.1.30/tracing_core/subscriber/trait.Subscriber.html
-[`Metadata`]: https://docs.rs/tracing-core/0.1.30/tracing_core/metadata/struct.Metadata.html
-[`Callsite`]: https://docs.rs/tracing-core/0.1.30/tracing_core/callsite/trait.Callsite.html
-[`Field`]: https://docs.rs/tracing-core/0.1.30/tracing_core/field/struct.Field.html
-[`FieldSet`]: https://docs.rs/tracing-core/0.1.30/tracing_core/field/struct.FieldSet.html
-[`Value`]: https://docs.rs/tracing-core/0.1.30/tracing_core/field/trait.Value.html
-[`ValueSet`]: https://docs.rs/tracing-core/0.1.30/tracing_core/field/struct.ValueSet.html
-[`Dispatch`]: https://docs.rs/tracing-core/0.1.30/tracing_core/dispatcher/struct.Dispatch.html
+[`span::Id`]: https://docs.rs/tracing-core/0.1.31/tracing_core/span/struct.Id.html
+[`Event`]: https://docs.rs/tracing-core/0.1.31/tracing_core/event/struct.Event.html
+[`Subscriber`]: https://docs.rs/tracing-core/0.1.31/tracing_core/subscriber/trait.Subscriber.html
+[`Metadata`]: https://docs.rs/tracing-core/0.1.31/tracing_core/metadata/struct.Metadata.html
+[`Callsite`]: https://docs.rs/tracing-core/0.1.31/tracing_core/callsite/trait.Callsite.html
+[`Field`]: https://docs.rs/tracing-core/0.1.31/tracing_core/field/struct.Field.html
+[`FieldSet`]: https://docs.rs/tracing-core/0.1.31/tracing_core/field/struct.FieldSet.html
+[`Value`]: https://docs.rs/tracing-core/0.1.31/tracing_core/field/trait.Value.html
+[`ValueSet`]: https://docs.rs/tracing-core/0.1.31/tracing_core/field/struct.ValueSet.html
+[`Dispatch`]: https://docs.rs/tracing-core/0.1.31/tracing_core/dispatcher/struct.Dispatch.html
 
 ## Supported Rust Versions
 
 Tracing is built against the latest stable release. The minimum supported
-version is 1.49. The current Tracing version is not guaranteed to build on Rust
+version is 1.56. The current Tracing version is not guaranteed to build on Rust
 versions earlier than the minimum supported version.
 
 Tracing follows the same compiler support policies as the rest of the Tokio
 project. The current stable Rust compiler and the three most recent minor
 versions before it will always be supported. For example, if the current stable
-compiler version is 1.45, the minimum supported version will not be increased
-past 1.42, three minor versions prior. Increasing the minimum supported compiler
+compiler version is 1.69, the minimum supported version will not be increased
+past 1.69, three minor versions prior. Increasing the minimum supported compiler
 version is not considered a semver breaking change as long as doing so complies
 with this policy.
 
diff --git a/src/callsite.rs b/src/callsite.rs
index f887132..62fa8c4 100644
--- a/src/callsite.rs
+++ b/src/callsite.rs
@@ -9,9 +9,7 @@
 //! * Storing the span or event's [`Metadata`],
 //! * Uniquely [identifying](Identifier) the span or event definition,
 //! * Caching the subscriber's [`Interest`][^1] in that span or event, to avoid
-//!   re-evaluating filters,
-//! * Storing a [`Registration`] that allows the callsite to be part of a global
-//!   list of all callsites in the program.
+//!   re-evaluating filters.
 //!
 //! # Registering Callsites
 //!
diff --git a/src/dispatcher.rs b/src/dispatcher.rs
index 36b3cfd..de02afb 100644
--- a/src/dispatcher.rs
+++ b/src/dispatcher.rs
@@ -140,7 +140,7 @@
 
 #[cfg(feature = "std")]
 use crate::stdlib::{
-    cell::{Cell, RefCell, RefMut},
+    cell::{Cell, Ref, RefCell},
     error,
 };
 
@@ -153,7 +153,7 @@
 /// `Dispatch` trace data to a [`Subscriber`].
 #[derive(Clone)]
 pub struct Dispatch {
-    subscriber: Arc<dyn Subscriber + Send + Sync>,
+    subscriber: Kind<Arc<dyn Subscriber + Send + Sync>>,
 }
 
 /// `WeakDispatch` is a version of [`Dispatch`] that holds a non-owning reference
@@ -176,13 +176,12 @@
 /// [here]: Subscriber#avoiding-memory-leaks
 #[derive(Clone)]
 pub struct WeakDispatch {
-    subscriber: Weak<dyn Subscriber + Send + Sync>,
+    subscriber: Kind<Weak<dyn Subscriber + Send + Sync>>,
 }
 
-#[cfg(feature = "alloc")]
 #[derive(Clone)]
 enum Kind<T> {
-    Global(&'static (dyn Collect + Send + Sync)),
+    Global(&'static (dyn Subscriber + Send + Sync)),
     Scoped(T),
 }
 
@@ -197,11 +196,20 @@
 static EXISTS: AtomicBool = AtomicBool::new(false);
 static GLOBAL_INIT: AtomicUsize = AtomicUsize::new(UNINITIALIZED);
 
+#[cfg(feature = "std")]
+static SCOPED_COUNT: AtomicUsize = AtomicUsize::new(0);
+
 const UNINITIALIZED: usize = 0;
 const INITIALIZING: usize = 1;
 const INITIALIZED: usize = 2;
 
-static mut GLOBAL_DISPATCH: Option<Dispatch> = None;
+static mut GLOBAL_DISPATCH: Dispatch = Dispatch {
+    subscriber: Kind::Global(&NO_SUBSCRIBER),
+};
+static NONE: Dispatch = Dispatch {
+    subscriber: Kind::Global(&NO_SUBSCRIBER),
+};
+static NO_SUBSCRIBER: NoSubscriber = NoSubscriber::new();
 
 /// The dispatch state of a thread.
 #[cfg(feature = "std")]
@@ -305,8 +313,20 @@
         )
         .is_ok()
     {
+        let subscriber = {
+            let subscriber = match dispatcher.subscriber {
+                Kind::Global(s) => s,
+                Kind::Scoped(s) => unsafe {
+                    // safety: this leaks the subscriber onto the heap. the
+                    // reference count will always be at least 1, because the
+                    // global default will never be dropped.
+                    &*Arc::into_raw(s)
+                },
+            };
+            Kind::Global(subscriber)
+        };
         unsafe {
-            GLOBAL_DISPATCH = Some(dispatcher);
+            GLOBAL_DISPATCH = Dispatch { subscriber };
         }
         GLOBAL_INIT.store(INITIALIZED, Ordering::SeqCst);
         EXISTS.store(true, Ordering::Release);
@@ -365,15 +385,21 @@
 where
     F: FnMut(&Dispatch) -> T,
 {
+    if SCOPED_COUNT.load(Ordering::Acquire) == 0 {
+        // fast path if no scoped dispatcher has been set; just use the global
+        // default.
+        return f(get_global());
+    }
+
     CURRENT_STATE
         .try_with(|state| {
             if let Some(entered) = state.enter() {
-                return f(&*entered.current());
+                return f(&entered.current());
             }
 
-            f(&Dispatch::none())
+            f(&NONE)
         })
-        .unwrap_or_else(|_| f(&Dispatch::none()))
+        .unwrap_or_else(|_| f(&NONE))
 }
 
 /// Executes a closure with a reference to this thread's current [dispatcher].
@@ -387,10 +413,16 @@
 #[doc(hidden)]
 #[inline(never)]
 pub fn get_current<T>(f: impl FnOnce(&Dispatch) -> T) -> Option<T> {
+    if SCOPED_COUNT.load(Ordering::Acquire) == 0 {
+        // fast path if no scoped dispatcher has been set; just use the global
+        // default.
+        return Some(f(get_global()));
+    }
+
     CURRENT_STATE
         .try_with(|state| {
             let entered = state.enter()?;
-            Some(f(&*entered.current()))
+            Some(f(&entered.current()))
         })
         .ok()?
 }
@@ -401,8 +433,7 @@
 #[cfg(not(feature = "std"))]
 #[doc(hidden)]
 pub fn get_current<T>(f: impl FnOnce(&Dispatch) -> T) -> Option<T> {
-    let dispatch = get_global()?;
-    Some(f(&dispatch))
+    Some(f(get_global()))
 }
 
 /// Executes a closure with a reference to the current [dispatcher].
@@ -413,35 +444,30 @@
 where
     F: FnMut(&Dispatch) -> T,
 {
-    if let Some(d) = get_global() {
-        f(d)
-    } else {
-        f(&Dispatch::none())
-    }
+    f(&get_global())
 }
 
-fn get_global() -> Option<&'static Dispatch> {
+#[inline]
+fn get_global() -> &'static Dispatch {
     if GLOBAL_INIT.load(Ordering::SeqCst) != INITIALIZED {
-        return None;
+        return &NONE;
     }
     unsafe {
         // This is safe given the invariant that setting the global dispatcher
         // also sets `GLOBAL_INIT` to `INITIALIZED`.
-        Some(GLOBAL_DISPATCH.as_ref().expect(
-            "invariant violated: GLOBAL_DISPATCH must be initialized before GLOBAL_INIT is set",
-        ))
+        &GLOBAL_DISPATCH
     }
 }
 
 #[cfg(feature = "std")]
-pub(crate) struct Registrar(Weak<dyn Subscriber + Send + Sync>);
+pub(crate) struct Registrar(Kind<Weak<dyn Subscriber + Send + Sync>>);
 
 impl Dispatch {
     /// Returns a new `Dispatch` that discards events and spans.
     #[inline]
     pub fn none() -> Self {
         Dispatch {
-            subscriber: Arc::new(NoSubscriber::default()),
+            subscriber: Kind::Global(&NO_SUBSCRIBER),
         }
     }
 
@@ -453,7 +479,7 @@
         S: Subscriber + Send + Sync + 'static,
     {
         let me = Dispatch {
-            subscriber: Arc::new(subscriber),
+            subscriber: Kind::Scoped(Arc::new(subscriber)),
         };
         callsite::register_dispatch(&me);
         me
@@ -461,7 +487,7 @@
 
     #[cfg(feature = "std")]
     pub(crate) fn registrar(&self) -> Registrar {
-        Registrar(Arc::downgrade(&self.subscriber))
+        Registrar(self.subscriber.downgrade())
     }
 
     /// Creates a [`WeakDispatch`] from this `Dispatch`.
@@ -480,18 +506,20 @@
     /// [here]: Subscriber#avoiding-memory-leaks
     pub fn downgrade(&self) -> WeakDispatch {
         WeakDispatch {
-            subscriber: Arc::downgrade(&self.subscriber),
+            subscriber: self.subscriber.downgrade(),
         }
     }
 
     #[inline(always)]
-    #[cfg(not(feature = "alloc"))]
     pub(crate) fn subscriber(&self) -> &(dyn Subscriber + Send + Sync) {
-        &self.subscriber
+        match self.subscriber {
+            Kind::Global(s) => s,
+            Kind::Scoped(ref s) => s.as_ref(),
+        }
     }
 
-    /// Registers a new callsite with this collector, returning whether or not
-    /// the collector is interested in being notified about the callsite.
+    /// Registers a new callsite with this subscriber, returning whether or not
+    /// the subscriber is interested in being notified about the callsite.
     ///
     /// This calls the [`register_callsite`] function on the [`Subscriber`]
     /// that this `Dispatch` forwards to.
@@ -500,7 +528,7 @@
     /// [`register_callsite`]: super::subscriber::Subscriber::register_callsite
     #[inline]
     pub fn register_callsite(&self, metadata: &'static Metadata<'static>) -> subscriber::Interest {
-        self.subscriber.register_callsite(metadata)
+        self.subscriber().register_callsite(metadata)
     }
 
     /// Returns the highest [verbosity level][level] that this [`Subscriber`] will
@@ -516,7 +544,7 @@
     // TODO(eliza): consider making this a public API?
     #[inline]
     pub(crate) fn max_level_hint(&self) -> Option<LevelFilter> {
-        self.subscriber.max_level_hint()
+        self.subscriber().max_level_hint()
     }
 
     /// Record the construction of a new span, returning a new [ID] for the
@@ -530,7 +558,7 @@
     /// [`new_span`]: super::subscriber::Subscriber::new_span
     #[inline]
     pub fn new_span(&self, span: &span::Attributes<'_>) -> span::Id {
-        self.subscriber.new_span(span)
+        self.subscriber().new_span(span)
     }
 
     /// Record a set of values on a span.
@@ -542,7 +570,7 @@
     /// [`record`]: super::subscriber::Subscriber::record
     #[inline]
     pub fn record(&self, span: &span::Id, values: &span::Record<'_>) {
-        self.subscriber.record(span, values)
+        self.subscriber().record(span, values)
     }
 
     /// Adds an indication that `span` follows from the span with the id
@@ -555,7 +583,7 @@
     /// [`record_follows_from`]: super::subscriber::Subscriber::record_follows_from
     #[inline]
     pub fn record_follows_from(&self, span: &span::Id, follows: &span::Id) {
-        self.subscriber.record_follows_from(span, follows)
+        self.subscriber().record_follows_from(span, follows)
     }
 
     /// Returns true if a span with the specified [metadata] would be
@@ -569,7 +597,7 @@
     /// [`enabled`]: super::subscriber::Subscriber::enabled
     #[inline]
     pub fn enabled(&self, metadata: &Metadata<'_>) -> bool {
-        self.subscriber.enabled(metadata)
+        self.subscriber().enabled(metadata)
     }
 
     /// Records that an [`Event`] has occurred.
@@ -582,8 +610,9 @@
     /// [`event`]: super::subscriber::Subscriber::event
     #[inline]
     pub fn event(&self, event: &Event<'_>) {
-        if self.subscriber.event_enabled(event) {
-            self.subscriber.event(event);
+        let subscriber = self.subscriber();
+        if subscriber.event_enabled(event) {
+            subscriber.event(event);
         }
     }
 
@@ -595,7 +624,7 @@
     /// [`Subscriber`]: super::subscriber::Subscriber
     /// [`enter`]: super::subscriber::Subscriber::enter
     pub fn enter(&self, span: &span::Id) {
-        self.subscriber.enter(span);
+        self.subscriber().enter(span);
     }
 
     /// Records that a span has been exited.
@@ -606,7 +635,7 @@
     /// [`Subscriber`]: super::subscriber::Subscriber
     /// [`exit`]: super::subscriber::Subscriber::exit
     pub fn exit(&self, span: &span::Id) {
-        self.subscriber.exit(span);
+        self.subscriber().exit(span);
     }
 
     /// Notifies the subscriber that a [span ID] has been cloned.
@@ -625,7 +654,7 @@
     /// [`new_span`]: super::subscriber::Subscriber::new_span
     #[inline]
     pub fn clone_span(&self, id: &span::Id) -> span::Id {
-        self.subscriber.clone_span(id)
+        self.subscriber().clone_span(id)
     }
 
     /// Notifies the subscriber that a [span ID] has been dropped.
@@ -654,7 +683,7 @@
     #[deprecated(since = "0.1.2", note = "use `Dispatch::try_close` instead")]
     pub fn drop_span(&self, id: span::Id) {
         #[allow(deprecated)]
-        self.subscriber.drop_span(id);
+        self.subscriber().drop_span(id);
     }
 
     /// Notifies the subscriber that a [span ID] has been dropped, and returns
@@ -673,7 +702,7 @@
     /// [`try_close`]: super::subscriber::Subscriber::try_close
     /// [`new_span`]: super::subscriber::Subscriber::new_span
     pub fn try_close(&self, id: span::Id) -> bool {
-        self.subscriber.try_close(id)
+        self.subscriber().try_close(id)
     }
 
     /// Returns a type representing this subscriber's view of the current span.
@@ -684,21 +713,21 @@
     /// [`current`]: super::subscriber::Subscriber::current_span
     #[inline]
     pub fn current_span(&self) -> span::Current {
-        self.subscriber.current_span()
+        self.subscriber().current_span()
     }
 
     /// Returns `true` if this `Dispatch` forwards to a `Subscriber` of type
     /// `T`.
     #[inline]
     pub fn is<T: Any>(&self) -> bool {
-        <dyn Subscriber>::is::<T>(&self.subscriber)
+        <dyn Subscriber>::is::<T>(self.subscriber())
     }
 
     /// Returns some reference to the `Subscriber` this `Dispatch` forwards to
     /// if it is of type `T`, or `None` if it isn't.
     #[inline]
     pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
-        <dyn Subscriber>::downcast_ref(&self.subscriber)
+        <dyn Subscriber>::downcast_ref(self.subscriber())
     }
 }
 
@@ -711,9 +740,16 @@
 
 impl fmt::Debug for Dispatch {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_tuple("Dispatch")
-            .field(&format_args!("{:p}", self.subscriber))
-            .finish()
+        match self.subscriber {
+            Kind::Scoped(ref s) => f
+                .debug_tuple("Dispatch::Scoped")
+                .field(&format_args!("{:p}", s))
+                .finish(),
+            Kind::Global(s) => f
+                .debug_tuple("Dispatch::Global")
+                .field(&format_args!("{:p}", s))
+                .finish(),
+        }
     }
 }
 
@@ -757,12 +793,16 @@
 
 impl fmt::Debug for WeakDispatch {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let mut tuple = f.debug_tuple("WeakDispatch");
-        match self.subscriber.upgrade() {
-            Some(subscriber) => tuple.field(&format_args!("Some({:p})", subscriber)),
-            None => tuple.field(&format_args!("None")),
-        };
-        tuple.finish()
+        match self.subscriber {
+            Kind::Scoped(ref s) => f
+                .debug_tuple("WeakDispatch::Scoped")
+                .field(&format_args!("{:p}", s))
+                .finish(),
+            Kind::Global(s) => f
+                .debug_tuple("WeakDispatch::Global")
+                .field(&format_args!("{:p}", s))
+                .finish(),
+        }
     }
 }
 
@@ -775,6 +815,26 @@
 
 // ===== impl State =====
 
+impl Kind<Arc<dyn Subscriber + Send + Sync>> {
+    fn downgrade(&self) -> Kind<Weak<dyn Subscriber + Send + Sync>> {
+        match self {
+            Kind::Global(s) => Kind::Global(*s),
+            Kind::Scoped(ref s) => Kind::Scoped(Arc::downgrade(s)),
+        }
+    }
+}
+
+impl Kind<Weak<dyn Subscriber + Send + Sync>> {
+    fn upgrade(&self) -> Option<Kind<Arc<dyn Subscriber + Send + Sync>>> {
+        match self {
+            Kind::Global(s) => Some(Kind::Global(*s)),
+            Kind::Scoped(ref s) => Some(Kind::Scoped(s.upgrade()?)),
+        }
+    }
+}
+
+// ===== impl State =====
+
 #[cfg(feature = "std")]
 impl State {
     /// Replaces the current default dispatcher on this thread with the provided
@@ -792,6 +852,7 @@
             .ok()
             .flatten();
         EXISTS.store(true, Ordering::Release);
+        SCOPED_COUNT.fetch_add(1, Ordering::Release);
         DefaultGuard(prior)
     }
 
@@ -810,10 +871,11 @@
 #[cfg(feature = "std")]
 impl<'a> Entered<'a> {
     #[inline]
-    fn current(&self) -> RefMut<'a, Dispatch> {
-        let default = self.0.default.borrow_mut();
-        RefMut::map(default, |default| {
-            default.get_or_insert_with(|| get_global().cloned().unwrap_or_else(Dispatch::none))
+    fn current(&self) -> Ref<'a, Dispatch> {
+        let default = self.0.default.borrow();
+        Ref::map(default, |default| match default {
+            Some(default) => default,
+            None => get_global(),
         })
     }
 }
@@ -838,6 +900,7 @@
         // could then also attempt to access the same thread local
         // state -- causing a clash.
         let prev = CURRENT_STATE.try_with(|state| state.default.replace(self.0.take()));
+        SCOPED_COUNT.fetch_sub(1, Ordering::Release);
         drop(prev)
     }
 }
diff --git a/src/field.rs b/src/field.rs
index e103c75..90c4eaa 100644
--- a/src/field.rs
+++ b/src/field.rs
@@ -1,13 +1,13 @@
 //! `Span` and `Event` key-value data.
 //!
-//! Spans and events may be annotated with key-value data, referred to as known
-//! as _fields_. These fields consist of a mapping from a key (corresponding to
-//! a `&str` but represented internally as an array index) to a [`Value`].
+//! Spans and events may be annotated with key-value data, known as _fields_.
+//! These fields consist of a mapping from a key (corresponding to a `&str` but
+//! represented internally as an array index) to a [`Value`].
 //!
 //! # `Value`s and `Subscriber`s
 //!
 //! `Subscriber`s consume `Value`s as fields attached to [span]s or [`Event`]s.
-//! The set of field keys on a given span or is defined on its [`Metadata`].
+//! The set of field keys on a given span or event is defined on its [`Metadata`].
 //! When a span is created, it provides [`Attributes`] to the `Subscriber`'s
 //! [`new_span`] method, containing any fields whose values were provided when
 //! the span was created; and may call the `Subscriber`'s [`record`] method
@@ -315,6 +315,7 @@
     /// <strong>Note</strong>: This is only enabled when the Rust standard library is
     /// present.
     /// </pre>
+    /// </div>
     #[cfg(feature = "std")]
     #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
     fn record_error(&mut self, field: &Field, value: &(dyn std::error::Error + 'static)) {
@@ -469,6 +470,10 @@
         impl $crate::sealed::Sealed for $value_ty {}
         impl $crate::field::Value for $value_ty {
             fn record(&self, key: &$crate::field::Field, visitor: &mut dyn $crate::field::Visit) {
+                // `op` is always a function; the closure is used because
+                // sometimes there isn't a real function corresponding to that
+                // operation. the clippy warning is not that useful here.
+                #[allow(clippy::redundant_closure_call)]
                 visitor.$record(key, $op(*self))
             }
         }
@@ -484,6 +489,10 @@
         impl $crate::sealed::Sealed for ty_to_nonzero!($value_ty) {}
         impl $crate::field::Value for ty_to_nonzero!($value_ty) {
             fn record(&self, key: &$crate::field::Field, visitor: &mut dyn $crate::field::Visit) {
+                // `op` is always a function; the closure is used because
+                // sometimes there isn't a real function corresponding to that
+                // operation. the clippy warning is not that useful here.
+                #[allow(clippy::redundant_closure_call)]
                 visitor.$record(key, $op(self.get()))
             }
         }
@@ -819,6 +828,7 @@
     ///
     /// [`Identifier`]: super::callsite::Identifier
     /// [`Callsite`]: super::callsite::Callsite
+    #[inline]
     pub(crate) fn callsite(&self) -> callsite::Identifier {
         callsite::Identifier(self.callsite.0)
     }
@@ -856,6 +866,7 @@
     }
 
     /// Returns an iterator over the `Field`s in this `FieldSet`.
+    #[inline]
     pub fn iter(&self) -> Iter {
         let idxs = 0..self.len();
         Iter {
@@ -868,9 +879,6 @@
     }
 
     /// Returns a new `ValueSet` with entries for this `FieldSet`'s values.
-    ///
-    /// Note that a `ValueSet` may not be constructed with arrays of over 32
-    /// elements.
     #[doc(hidden)]
     pub fn value_set<'v, V>(&'v self, values: &'v V) -> ValueSet<'v>
     where
@@ -959,6 +967,7 @@
 
 impl Iterator for Iter {
     type Item = Field;
+    #[inline]
     fn next(&mut self) -> Option<Field> {
         let i = self.idxs.next()?;
         Some(Field {
@@ -1068,28 +1077,10 @@
 mod private {
     use super::*;
 
-    /// Marker trait implemented by arrays which are of valid length to
-    /// construct a `ValueSet`.
-    ///
-    /// `ValueSet`s may only be constructed from arrays containing 32 or fewer
-    /// elements, to ensure the array is small enough to always be allocated on the
-    /// stack. This trait is only implemented by arrays of an appropriate length,
-    /// ensuring that the correct size arrays are used at compile-time.
+    /// Restrictions on `ValueSet` lengths were removed in #2508 but this type remains for backwards compatibility.
     pub trait ValidLen<'a>: Borrow<[(&'a Field, Option<&'a (dyn Value + 'a)>)]> {}
-}
 
-macro_rules! impl_valid_len {
-    ( $( $len:tt ),+ ) => {
-        $(
-            impl<'a> private::ValidLen<'a> for
-                [(&'a Field, Option<&'a (dyn Value + 'a)>); $len] {}
-        )+
-    }
-}
-
-impl_valid_len! {
-    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
-    21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
+    impl<'a, const N: usize> ValidLen<'a> for [(&'a Field, Option<&'a (dyn Value + 'a)>); N] {}
 }
 
 #[cfg(test)]
@@ -1098,8 +1089,9 @@
     use crate::metadata::{Kind, Level, Metadata};
     use crate::stdlib::{borrow::ToOwned, string::String};
 
-    struct TestCallsite1;
-    static TEST_CALLSITE_1: TestCallsite1 = TestCallsite1;
+    // Make sure TEST_CALLSITE_* have non-zero size, so they can't be located at the same address.
+    struct TestCallsite1(u8);
+    static TEST_CALLSITE_1: TestCallsite1 = TestCallsite1(0);
     static TEST_META_1: Metadata<'static> = metadata! {
         name: "field_test1",
         target: module_path!(),
@@ -1119,8 +1111,8 @@
         }
     }
 
-    struct TestCallsite2;
-    static TEST_CALLSITE_2: TestCallsite2 = TestCallsite2;
+    struct TestCallsite2(u8);
+    static TEST_CALLSITE_2: TestCallsite2 = TestCallsite2(0);
     static TEST_META_2: Metadata<'static> = metadata! {
         name: "field_test2",
         target: module_path!(),
diff --git a/src/lib.rs b/src/lib.rs
index c1f87b2..d43a6b8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -23,7 +23,7 @@
 //! In addition, it defines the global callsite registry and per-thread current
 //! dispatcher which other components of the tracing system rely on.
 //!
-//! *Compiler support: [requires `rustc` 1.49+][msrv]*
+//! *Compiler support: [requires `rustc` 1.56+][msrv]*
 //!
 //! [msrv]: #supported-rust-versions
 //!
@@ -92,14 +92,14 @@
 //! ## Supported Rust Versions
 //!
 //! Tracing is built against the latest stable release. The minimum supported
-//! version is 1.49. The current Tracing version is not guaranteed to build on
+//! version is 1.56. The current Tracing version is not guaranteed to build on
 //! Rust versions earlier than the minimum supported version.
 //!
 //! Tracing follows the same compiler support policies as the rest of the Tokio
 //! project. The current stable Rust compiler and the three most recent minor
 //! versions before it will always be supported. For example, if the current
-//! stable compiler version is 1.45, the minimum supported version will not be
-//! increased past 1.42, three minor versions prior. Increasing the minimum
+//! stable compiler version is 1.69, the minimum supported version will not be
+//! increased past 1.66, three minor versions prior. Increasing the minimum
 //! supported compiler version is not considered a semver breaking change as
 //! long as doing so complies with this policy.
 //!
@@ -116,7 +116,6 @@
 //! [`Dispatch`]: dispatcher::Dispatch
 //! [`tokio-rs/tracing`]: https://github.com/tokio-rs/tracing
 //! [`tracing`]: https://crates.io/crates/tracing
-#![doc(html_root_url = "https://docs.rs/tracing-core/0.1.22")]
 #![doc(
     html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png",
     issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/"
@@ -129,7 +128,6 @@
     rust_2018_idioms,
     unreachable_pub,
     bad_style,
-    const_err,
     dead_code,
     improper_ctypes,
     non_shorthand_field_patterns,
@@ -245,9 +243,9 @@
             $name,
             $target,
             $level,
-            Some(file!()),
-            Some(line!()),
-            Some(module_path!()),
+            ::core::option::Option::Some(file!()),
+            ::core::option::Option::Some(line!()),
+            ::core::option::Option::Some(module_path!()),
             $crate::field::FieldSet::new($fields, $crate::identify_callsite!($callsite)),
             $kind,
         )
diff --git a/src/metadata.rs b/src/metadata.rs
index a154419..5e475c1 100644
--- a/src/metadata.rs
+++ b/src/metadata.rs
@@ -273,6 +273,7 @@
     }
 
     /// Returns the names of the fields on the described span or event.
+    #[inline]
     pub fn fields(&self) -> &field::FieldSet {
         &self.fields
     }
diff --git a/src/subscriber.rs b/src/subscriber.rs
index e8f4441..17b6316 100644
--- a/src/subscriber.rs
+++ b/src/subscriber.rs
@@ -699,6 +699,14 @@
     fn exit(&self, _span: &span::Id) {}
 }
 
+impl NoSubscriber {
+    /// Returns a new `NoSubscriber`.
+    #[must_use]
+    pub const fn new() -> Self {
+        Self(())
+    }
+}
+
 impl<S> Subscriber for Box<S>
 where
     S: Subscriber + ?Sized,
diff --git a/tests/local_dispatch_before_init.rs b/tests/local_dispatch_before_init.rs
new file mode 100644
index 0000000..71b67f8
--- /dev/null
+++ b/tests/local_dispatch_before_init.rs
@@ -0,0 +1,43 @@
+mod common;
+
+use common::*;
+use tracing_core::{
+    dispatcher::{self, Dispatch},
+    subscriber::NoSubscriber,
+};
+
+/// This test reproduces the following issues:
+/// - https://github.com/tokio-rs/tracing/issues/2587
+/// - https://github.com/tokio-rs/tracing/issues/2411
+/// - https://github.com/tokio-rs/tracing/issues/2436
+#[test]
+fn local_dispatch_before_init() {
+    dispatcher::get_default(|current| assert!(dbg!(current).is::<NoSubscriber>()));
+
+    // Temporarily override the default dispatcher with a scoped dispatcher.
+    // Using a scoped dispatcher makes the thread local state attempt to cache
+    // the scoped default.
+    #[cfg(feature = "std")]
+    {
+        dispatcher::with_default(&Dispatch::new(TestSubscriberB), || {
+            dispatcher::get_default(|current| {
+                assert!(
+                    dbg!(current).is::<TestSubscriberB>(),
+                    "overriden subscriber not set",
+                );
+            })
+        })
+    }
+
+    dispatcher::get_default(|current| assert!(current.is::<NoSubscriber>()));
+
+    dispatcher::set_global_default(Dispatch::new(TestSubscriberA))
+        .expect("set global dispatch failed");
+
+    dispatcher::get_default(|current| {
+        assert!(
+            dbg!(current).is::<TestSubscriberA>(),
+            "default subscriber not set"
+        );
+    });
+}