From ede7f08148d70cfee24b0ab22c964d3ec70b6c96 Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Wed, 22 Jun 2022 13:04:28 -0700 Subject: [PATCH 1/6] core: remove vendored `lazy_static` on no-std Currently, `no_std` targets use a vendored version of `lazy_static` that uses the `spin` crate's `Once` type, while the `std` target uses the `once_cell` crate's `Lazy` type. This is unfortunate, as the `lazy_static` macro has a different interface from the `Lazy` cell type. This increases the amount of code that differs based on whether or not `std` is enabled. This branch removes the vendored `lazy_static` macro and replaces it with a reimplementation of `once_cell::sync::Lazy` that uses `spin::Once` rather than `once_cell::sync::OnceCell` as the inner "once type". Now, all code can be written against a `Lazy` struct with the same interface, regardless of whether or not `std` is enabled. --- tracing-core/src/callsite.rs | 13 +--- tracing-core/src/lazy.rs | 85 ++++++++++++++++++++++ tracing-core/src/lazy_static/LICENSE | 26 ------- tracing-core/src/lazy_static/core_lazy.rs | 30 -------- tracing-core/src/lazy_static/mod.rs | 89 ----------------------- tracing-core/src/lib.rs | 5 +- 6 files changed, 89 insertions(+), 159 deletions(-) create mode 100644 tracing-core/src/lazy.rs delete mode 100644 tracing-core/src/lazy_static/LICENSE delete mode 100644 tracing-core/src/lazy_static/core_lazy.rs delete mode 100644 tracing-core/src/lazy_static/mod.rs diff --git a/tracing-core/src/callsite.rs b/tracing-core/src/callsite.rs index 87d084647b..d0fe1a3d6c 100644 --- a/tracing-core/src/callsite.rs +++ b/tracing-core/src/callsite.rs @@ -111,6 +111,7 @@ use crate::stdlib::{ }; use crate::{ dispatcher::Dispatch, + lazy::Lazy, metadata::{LevelFilter, Metadata}, subscriber::Interest, }; @@ -253,14 +254,7 @@ static CALLSITES: Callsites = Callsites { static DISPATCHERS: Dispatchers = Dispatchers::new(); -#[cfg(feature = "std")] -static LOCKED_CALLSITES: once_cell::sync::Lazy>> = - once_cell::sync::Lazy::new(Default::default); - -#[cfg(not(feature = "std"))] -crate::lazy_static! { - static ref LOCKED_CALLSITES: Mutex> = Mutex::new(Vec::new()); -} +static LOCKED_CALLSITES: Lazy>> = Lazy::new(Default::default); struct Callsites { list_head: AtomicPtr, @@ -514,8 +508,7 @@ mod private { #[cfg(feature = "std")] mod dispatchers { - use crate::dispatcher; - use once_cell::sync::Lazy; + use crate::{dispatcher, lazy::Lazy}; use std::sync::{ atomic::{AtomicBool, Ordering}, RwLock, RwLockReadGuard, RwLockWriteGuard, diff --git a/tracing-core/src/lazy.rs b/tracing-core/src/lazy.rs new file mode 100644 index 0000000000..b938cce367 --- /dev/null +++ b/tracing-core/src/lazy.rs @@ -0,0 +1,85 @@ +#[cfg(feature = "std")] +pub(crate) use once_cell::sync::Lazy; + +#[cfg(not(feature = "std"))] +pub(crate) use self::spin::Lazy; + +#[cfg(not(feature = "std"))] +mod spin { + use crate::spin::Once; + use core::{cell::Cell, fmt, ops::Deref}; + + /// Re-implementation of `once_cell::sync::Lazy` on top of `spin::Once` + /// rather than `OnceCell`. + /// + /// This is used when the standard library is disabled. + pub(crate) struct Lazy T> { + cell: Once, + init: Cell>, + } + + impl fmt::Debug for Lazy { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Lazy") + .field("cell", &self.cell) + .field("init", &"..") + .finish() + } + } + + impl Lazy { + /// Creates a new lazy value with the given initializing function. + pub(crate) const fn new(init: F) -> Lazy { + Lazy { + cell: Once::new(), + init: Cell::new(Some(init)), + } + } + + /// Consumes this `Lazy` returning the stored value. + /// + /// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise. + pub(crate) fn into_value(this: Lazy) -> Result { + let cell = this.cell; + let init = this.init; + cell.into_inner().ok_or_else(|| { + init.take() + .unwrap_or_else(|| panic!("Lazy instance has previously been poisoned")) + }) + } + } + + impl T> Lazy { + /// Forces the evaluation of this lazy value and returns a reference to + /// the result. + /// + /// This is equivalent to the `Deref` impl, but is explicit. + pub(crate) fn force(this: &Lazy) -> &T { + this.cell.get_or_init(|| match this.init.take() { + Some(f) => f(), + None => panic!("Lazy instance has previously been poisoned"), + }) + } + } + + impl T> Deref for Lazy { + type Target = T; + fn deref(&self) -> &T { + Lazy::force(self) + } + } + + impl T> DerefMut for Lazy { + fn deref_mut(&mut self) -> &mut T { + Lazy::force(self); + self.cell.get_mut().unwrap_or_else(|| unreachable!()) + } + } + + impl Default for Lazy { + /// Creates a new lazy value using `Default` as the initializing function. + fn default() -> Lazy { + Lazy::new(T::default) + } + } +} diff --git a/tracing-core/src/lazy_static/LICENSE b/tracing-core/src/lazy_static/LICENSE deleted file mode 100644 index 28e478827c..0000000000 --- a/tracing-core/src/lazy_static/LICENSE +++ /dev/null @@ -1,26 +0,0 @@ - -Copyright (c) 2010 The Rust Project Developers - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/tracing-core/src/lazy_static/core_lazy.rs b/tracing-core/src/lazy_static/core_lazy.rs deleted file mode 100644 index c61d36202d..0000000000 --- a/tracing-core/src/lazy_static/core_lazy.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2016 lazy-static.rs Developers -// -// Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be -// copied, modified, or distributed except according to those terms. - -use crate::spin::Once; - -pub(crate) struct Lazy(Once); - -impl Lazy { - pub(crate) const INIT: Self = Lazy(Once::INIT); - - #[inline(always)] - pub(crate) fn get(&'static self, builder: F) -> &T - where - F: FnOnce() -> T, - { - self.0.call_once(builder) - } -} - -#[macro_export] -#[doc(hidden)] -macro_rules! __lazy_static_create { - ($NAME:ident, $T:ty) => { - static $NAME: $crate::lazy_static::lazy::Lazy<$T> = $crate::lazy_static::lazy::Lazy::INIT; - }; -} diff --git a/tracing-core/src/lazy_static/mod.rs b/tracing-core/src/lazy_static/mod.rs deleted file mode 100644 index 78f0ae722b..0000000000 --- a/tracing-core/src/lazy_static/mod.rs +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2016 lazy-static.rs Developers -// -// Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be -// copied, modified, or distributed except according to those terms. - -/*! -A macro for declaring lazily evaluated statics. -Using this macro, it is possible to have `static`s that require code to be -executed at runtime in order to be initialized. -This includes anything requiring heap allocations, like vectors or hash maps, -as well as anything that requires function calls to be computed. -*/ - -#[path = "core_lazy.rs"] -pub(crate) mod lazy; - -#[doc(hidden)] -pub(crate) use core::ops::Deref as __Deref; - -#[macro_export] -#[doc(hidden)] -macro_rules! __lazy_static_internal { - // optional visibility restrictions are wrapped in `()` to allow for - // explicitly passing otherwise implicit information about private items - ($(#[$attr:meta])* ($($vis:tt)*) static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { - $crate::__lazy_static_internal!(@MAKE TY, $(#[$attr])*, ($($vis)*), $N); - $crate::__lazy_static_internal!(@TAIL, $N : $T = $e); - $crate::lazy_static!($($t)*); - }; - (@TAIL, $N:ident : $T:ty = $e:expr) => { - impl $crate::lazy_static::__Deref for $N { - type Target = $T; - fn deref(&self) -> &$T { - #[inline(always)] - fn __static_ref_initialize() -> $T { $e } - - #[inline(always)] - fn __stability() -> &'static $T { - $crate::__lazy_static_create!(LAZY, $T); - LAZY.get(__static_ref_initialize) - } - __stability() - } - } - impl $crate::lazy_static::LazyStatic for $N { - fn initialize(lazy: &Self) { - let _ = &**lazy; - } - } - }; - // `vis` is wrapped in `()` to prevent parsing ambiguity - (@MAKE TY, $(#[$attr:meta])*, ($($vis:tt)*), $N:ident) => { - #[allow(missing_copy_implementations)] - #[allow(non_camel_case_types)] - #[allow(dead_code)] - $(#[$attr])* - $($vis)* struct $N {__private_field: ()} - #[doc(hidden)] - $($vis)* static $N: $N = $N {__private_field: ()}; - }; - () => () -} - -#[macro_export] -#[doc(hidden)] -macro_rules! lazy_static { - ($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { - // use `()` to explicitly forward the information about private items - $crate::__lazy_static_internal!($(#[$attr])* () static ref $N : $T = $e; $($t)*); - }; - ($(#[$attr:meta])* pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { - $crate::__lazy_static_internal!($(#[$attr])* (pub) static ref $N : $T = $e; $($t)*); - }; - ($(#[$attr:meta])* pub ($($vis:tt)+) static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { - $crate::__lazy_static_internal!($(#[$attr])* (pub ($($vis)+)) static ref $N : $T = $e; $($t)*); - }; - () => () -} - -/// Support trait for enabling a few common operation on lazy static values. -/// -/// This is implemented by each defined lazy static, and -/// used by the free functions in this crate. -pub(crate) trait LazyStatic { - #[doc(hidden)] - fn initialize(lazy: &Self); -} diff --git a/tracing-core/src/lib.rs b/tracing-core/src/lib.rs index eceef7be22..c1f87b22f0 100644 --- a/tracing-core/src/lib.rs +++ b/tracing-core/src/lib.rs @@ -254,10 +254,7 @@ macro_rules! metadata { }; } -// Facade module: `no_std` uses spinlocks, `std` uses the mutexes in the standard library -#[cfg(not(feature = "std"))] -#[macro_use] -mod lazy_static; +pub(crate) mod lazy; // Trimmed-down vendored version of spin 0.5.2 (0387621) // Dependency of no_std lazy_static, not required in a std build From f38f813c75abf3f789e498881c7874223d6ae0ad Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Wed, 22 Jun 2022 15:07:19 -0700 Subject: [PATCH 2/6] whoops i forgot derefmut Signed-off-by: Eliza Weisman --- tracing-core/src/lazy.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tracing-core/src/lazy.rs b/tracing-core/src/lazy.rs index b938cce367..ee94700e2b 100644 --- a/tracing-core/src/lazy.rs +++ b/tracing-core/src/lazy.rs @@ -7,7 +7,11 @@ pub(crate) use self::spin::Lazy; #[cfg(not(feature = "std"))] mod spin { use crate::spin::Once; - use core::{cell::Cell, fmt, ops::Deref}; + use core::{ + cell::Cell, + fmt, + ops::{Deref, DerefMut}, + }; /// Re-implementation of `once_cell::sync::Lazy` on top of `spin::Once` /// rather than `OnceCell`. From 2a98e37dd56028b577a683b19a8e5c021b95e1e6 Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Wed, 22 Jun 2022 15:14:00 -0700 Subject: [PATCH 3/6] fix warnings Signed-off-by: Eliza Weisman --- tracing-core/src/lazy.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tracing-core/src/lazy.rs b/tracing-core/src/lazy.rs index ee94700e2b..42a9cc33d3 100644 --- a/tracing-core/src/lazy.rs +++ b/tracing-core/src/lazy.rs @@ -23,7 +23,7 @@ mod spin { } impl fmt::Debug for Lazy { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Lazy") .field("cell", &self.cell) .field("init", &"..") From 0c31e98d5a5535b9abcd5d6bbe9f48be127dbece Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Wed, 22 Jun 2022 15:14:14 -0700 Subject: [PATCH 4/6] oops i accidentally deleted the sync impl Signed-off-by: Eliza Weisman --- tracing-core/src/lazy.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tracing-core/src/lazy.rs b/tracing-core/src/lazy.rs index 42a9cc33d3..cc3c4af938 100644 --- a/tracing-core/src/lazy.rs +++ b/tracing-core/src/lazy.rs @@ -31,6 +31,13 @@ mod spin { } } + // We never create a `&F` from a `&Lazy` so it is fine to not impl + // `Sync` for `F`. We do create a `&mut Option` in `force`, but this is + // properly synchronized, so it only happens once so it also does not + // contribute to this impl. + unsafe impl Sync for Lazy where OnceCell: Sync {} + // auto-derived `Send` impl is OK. + impl Lazy { /// Creates a new lazy value with the given initializing function. pub(crate) const fn new(init: F) -> Lazy { From c0efb7c715558f5efd9ee9c892c56d89e4e4c7bc Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Wed, 22 Jun 2022 15:15:12 -0700 Subject: [PATCH 5/6] dox Signed-off-by: Eliza Weisman --- tracing-core/src/lazy.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tracing-core/src/lazy.rs b/tracing-core/src/lazy.rs index cc3c4af938..5f67261595 100644 --- a/tracing-core/src/lazy.rs +++ b/tracing-core/src/lazy.rs @@ -6,6 +6,9 @@ pub(crate) use self::spin::Lazy; #[cfg(not(feature = "std"))] mod spin { + //! This is the `once_cell::sync::Lazy` type, but modified to use our + //! `spin::Once` type rather than `OnceCell`. This is used to replace + //! `once_cell::sync::Lazy` on `no-std` builds. use crate::spin::Once; use core::{ cell::Cell, From 0e8b72823dec998bc67b0de1b5844ad5ffe05ff7 Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Wed, 22 Jun 2022 15:28:54 -0700 Subject: [PATCH 6/6] fixup! remove unused code Signed-off-by: Eliza Weisman --- tracing-core/src/lazy.rs | 29 +++-------------------------- tracing-core/src/stdlib.rs | 10 +++++----- 2 files changed, 8 insertions(+), 31 deletions(-) diff --git a/tracing-core/src/lazy.rs b/tracing-core/src/lazy.rs index 5f67261595..4f004e6364 100644 --- a/tracing-core/src/lazy.rs +++ b/tracing-core/src/lazy.rs @@ -10,11 +10,7 @@ mod spin { //! `spin::Once` type rather than `OnceCell`. This is used to replace //! `once_cell::sync::Lazy` on `no-std` builds. use crate::spin::Once; - use core::{ - cell::Cell, - fmt, - ops::{Deref, DerefMut}, - }; + use core::{cell::Cell, fmt, ops::Deref}; /// Re-implementation of `once_cell::sync::Lazy` on top of `spin::Once` /// rather than `OnceCell`. @@ -38,7 +34,7 @@ mod spin { // `Sync` for `F`. We do create a `&mut Option` in `force`, but this is // properly synchronized, so it only happens once so it also does not // contribute to this impl. - unsafe impl Sync for Lazy where OnceCell: Sync {} + unsafe impl Sync for Lazy where Once: Sync {} // auto-derived `Send` impl is OK. impl Lazy { @@ -49,18 +45,6 @@ mod spin { init: Cell::new(Some(init)), } } - - /// Consumes this `Lazy` returning the stored value. - /// - /// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise. - pub(crate) fn into_value(this: Lazy) -> Result { - let cell = this.cell; - let init = this.init; - cell.into_inner().ok_or_else(|| { - init.take() - .unwrap_or_else(|| panic!("Lazy instance has previously been poisoned")) - }) - } } impl T> Lazy { @@ -69,7 +53,7 @@ mod spin { /// /// This is equivalent to the `Deref` impl, but is explicit. pub(crate) fn force(this: &Lazy) -> &T { - this.cell.get_or_init(|| match this.init.take() { + this.cell.call_once(|| match this.init.take() { Some(f) => f(), None => panic!("Lazy instance has previously been poisoned"), }) @@ -83,13 +67,6 @@ mod spin { } } - impl T> DerefMut for Lazy { - fn deref_mut(&mut self) -> &mut T { - Lazy::force(self); - self.cell.get_mut().unwrap_or_else(|| unreachable!()) - } - } - impl Default for Lazy { /// Creates a new lazy value using `Default` as the initializing function. fn default() -> Lazy { diff --git a/tracing-core/src/stdlib.rs b/tracing-core/src/stdlib.rs index 4a1c17c2b8..741549519c 100644 --- a/tracing-core/src/stdlib.rs +++ b/tracing-core/src/stdlib.rs @@ -64,11 +64,11 @@ mod no_std { } impl Mutex { - pub(crate) fn new(data: T) -> Self { - Self { - inner: crate::spin::Mutex::new(data), - } - } + // pub(crate) fn new(data: T) -> Self { + // Self { + // inner: crate::spin::Mutex::new(data), + // } + // } pub(crate) fn lock(&self) -> Result, ()> { Ok(self.inner.lock())