diff --git a/src/api/mod.rs b/src/api/mod.rs index 82b857db..96837470 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -1,5 +1,3 @@ -#![recursion_limit = "192"] - pub mod client; pub mod router; pub mod server; diff --git a/src/main/main.rs b/src/main/main.rs index 8703eef2..8e644a15 100644 --- a/src/main/main.rs +++ b/src/main/main.rs @@ -1,5 +1,3 @@ -#![recursion_limit = "192"] - pub(crate) mod clap; mod mods; mod restart; diff --git a/src/router/mod.rs b/src/router/mod.rs index 67ebc0e3..e123442c 100644 --- a/src/router/mod.rs +++ b/src/router/mod.rs @@ -1,5 +1,3 @@ -#![recursion_limit = "160"] - mod layers; mod request; mod router; diff --git a/src/service/mod.rs b/src/service/mod.rs index cb8bfcd9..604e3404 100644 --- a/src/service/mod.rs +++ b/src/service/mod.rs @@ -1,4 +1,3 @@ -#![recursion_limit = "192"] #![allow(refining_impl_trait)] mod manager; diff --git a/src/service/service.rs b/src/service/service.rs index 03165050..7ec2ea0f 100644 --- a/src/service/service.rs +++ b/src/service/service.rs @@ -51,7 +51,7 @@ pub(crate) struct Args<'a> { /// Dep is a reference to a service used within another service. /// Circular-dependencies between services require this indirection. -pub(crate) struct Dep { +pub(crate) struct Dep { dep: OnceLock>, service: Weak, name: &'static str, @@ -62,24 +62,47 @@ pub(crate) type MapType = BTreeMap; pub(crate) type MapVal = (Weak, Weak); pub(crate) type MapKey = String; -impl Deref for Dep { +/// SAFETY: Workaround for a compiler limitation (or bug) where it is Hard to +/// prove the Sync'ness of Dep because services contain circular references +/// to other services through Dep's. The Sync'ness of Dep can still be +/// proved without unsafety by declaring the crate-attribute #![recursion_limit +/// = "192"] but this may take a while. Re-evaluate this when a new trait-solver +/// (such as Chalk) becomes available. +unsafe impl Sync for Dep {} + +/// SAFETY: Ancillary to unsafe impl Sync; while this is not needed to prevent +/// violating the recursion_limit, the trait-solver still spends an inordinate +/// amount of time to prove this. +unsafe impl Send for Dep {} + +impl Deref for Dep { type Target = Arc; /// Dereference a dependency. The dependency must be ready or panics. + #[inline] fn deref(&self) -> &Self::Target { - self.dep.get_or_init(|| { - let service = self - .service - .upgrade() - .expect("services map exists for dependency initialization."); + self.dep.get_or_init( + #[inline(never)] + || self.init(), + ) + } +} - require::(&service, self.name) - }) +impl Dep { + #[inline] + fn init(&self) -> Arc { + let service = self + .service + .upgrade() + .expect("services map exists for dependency initialization."); + + require::(&service, self.name) } } impl<'a> Args<'a> { /// Create a lazy-reference to a service when constructing another Service. + #[inline] pub(crate) fn depend(&'a self, name: &'static str) -> Dep { Dep:: { dep: OnceLock::new(), @@ -90,12 +113,14 @@ impl<'a> Args<'a> { /// Create a reference immediately to a service when constructing another /// Service. The other service must be constructed. + #[inline] pub(crate) fn require(&'a self, name: &str) -> Arc { require::(self.service, name) } } /// Reference a Service by name. Panics if the Service does not exist or was /// incorrectly cast. -pub(crate) fn require(map: &Map, name: &str) -> Arc { +#[inline] +fn require(map: &Map, name: &str) -> Arc { try_get::(map, name) .inspect_err(inspect_log) .expect("Failure to reference service required by another service.") diff --git a/src/service/services.rs b/src/service/services.rs index da22fb2d..0b63a5ca 100644 --- a/src/service/services.rs +++ b/src/service/services.rs @@ -195,6 +195,7 @@ impl Services { } } + #[inline] pub fn try_get(&self, name: &str) -> Result> where T: Any + Send + Sync + Sized, @@ -202,6 +203,7 @@ impl Services { service::try_get::(&self.service, name) } + #[inline] pub fn get(&self, name: &str) -> Option> where T: Any + Send + Sync + Sized,