diff options
| author | Laurenz <laurmaedje@gmail.com> | 2023-05-11 10:50:30 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2023-05-11 10:50:30 +0200 |
| commit | 47dff3765de863554ca296448555599fc50d4a8a (patch) | |
| tree | f632073bd800466d94dae7d19b1d4e28e80ff743 /src/eval | |
| parent | d9ba84085e36036409c919cff2e3eb3d126e3bb3 (diff) | |
Remove 'static bound on `World`
Thanks to improvements in comemo, tracked types don't need to be 'static anymore. This means that the 'static bound on the `World` is now lifted and that the `Route` doesn't need to use unsafe code anymore to manage its lifetime.
Diffstat (limited to 'src/eval')
| -rw-r--r-- | src/eval/func.rs | 4 | ||||
| -rw-r--r-- | src/eval/library.rs | 2 | ||||
| -rw-r--r-- | src/eval/mod.rs | 43 |
3 files changed, 30 insertions, 19 deletions
diff --git a/src/eval/func.rs b/src/eval/func.rs index 51eba564..060e72cf 100644 --- a/src/eval/func.rs +++ b/src/eval/func.rs @@ -4,7 +4,7 @@ use std::fmt::{self, Debug, Formatter}; use std::hash::{Hash, Hasher}; use std::sync::Arc; -use comemo::{Prehashed, Track, Tracked, TrackedMut}; +use comemo::{Prehashed, Tracked, TrackedMut}; use ecow::eco_format; use once_cell::sync::Lazy; @@ -317,7 +317,7 @@ impl Closure { #[allow(clippy::too_many_arguments)] fn call( this: &Func, - world: Tracked<dyn World>, + world: Tracked<dyn World + '_>, route: Tracked<Route>, tracer: TrackedMut<Tracer>, provider: TrackedMut<StabilityProvider>, diff --git a/src/eval/library.rs b/src/eval/library.rs index 25f715f8..0067bf57 100644 --- a/src/eval/library.rs +++ b/src/eval/library.rs @@ -67,7 +67,7 @@ pub struct LangItems { /// The keys contained in the bibliography and short descriptions of them. #[allow(clippy::type_complexity)] pub bibliography_keys: fn( - world: Tracked<dyn World>, + world: Tracked<dyn World + '_>, introspector: Tracked<Introspector>, ) -> Vec<(EcoString, Option<EcoString>)>, /// A section heading: `= Introduction`. diff --git a/src/eval/mod.rs b/src/eval/mod.rs index a837c9e0..95822530 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -41,7 +41,7 @@ use std::collections::HashSet; use std::mem; use std::path::{Path, PathBuf}; -use comemo::{Track, Tracked, TrackedMut}; +use comemo::{Track, Tracked, TrackedMut, Validate}; use ecow::{EcoString, EcoVec}; use unicode_segmentation::UnicodeSegmentation; @@ -67,7 +67,7 @@ const MAX_CALL_DEPTH: usize = 64; #[comemo::memoize] #[tracing::instrument(skip(world, route, tracer, source))] pub fn eval( - world: Tracked<dyn World>, + world: Tracked<dyn World + '_>, route: Tracked<Route>, tracer: TrackedMut<Tracer>, source: &Source, @@ -84,7 +84,7 @@ pub fn eval( set_lang_items(library.items.clone()); // Evaluate the module. - let route = unsafe { Route::insert(route, id) }; + let route = Route::insert(route, id); let scopes = Scopes::new(Some(library)); let mut provider = StabilityProvider::new(); let introspector = Introspector::new(&[]); @@ -117,7 +117,7 @@ pub fn eval( /// Everything in the output is associated with the given `span`. #[comemo::memoize] pub fn eval_string( - world: Tracked<dyn World>, + world: Tracked<dyn World + '_>, code: &str, span: Span, ) -> SourceResult<Value> { @@ -164,7 +164,7 @@ pub struct Vm<'a> { /// The language items. items: LangItems, /// The route of source ids the VM took to reach its current location. - route: Tracked<'a, Route>, + route: Tracked<'a, Route<'a>>, /// The current location. location: SourceId, /// A control flow event that is currently happening. @@ -200,7 +200,7 @@ impl<'a> Vm<'a> { } /// Access the underlying world. - pub fn world(&self) -> Tracked<'a, dyn World> { + pub fn world(&self) -> Tracked<'a, dyn World + 'a> { self.vt.world } @@ -263,34 +263,45 @@ impl Flow { /// A route of source ids. #[derive(Default)] -pub struct Route { - parent: Option<Tracked<'static, Self>>, +pub struct Route<'a> { + // We need to override the constraint's lifetime here so that `Tracked` is + // covariant over the constraint. If it becomes invariant, we're in for a + // world of lifetime pain. + outer: Option<Tracked<'a, Self, <Route<'static> as Validate>::Constraint>>, id: Option<SourceId>, } -impl Route { +impl<'a> Route<'a> { /// Create a new route with just one entry. pub fn new(id: SourceId) -> Self { - Self { id: Some(id), parent: None } + Self { id: Some(id), outer: None } } /// Insert a new id into the route. /// /// You must guarantee that `outer` lives longer than the resulting /// route is ever used. - unsafe fn insert(outer: Tracked<Route>, id: SourceId) -> Route { - Route { - parent: Some(std::mem::transmute(outer)), - id: Some(id), + pub fn insert(outer: Tracked<'a, Self>, id: SourceId) -> Self { + Route { outer: Some(outer), id: Some(id) } + } + + /// Start tracking this locator. + /// + /// In comparison to [`Track::track`], this method skips this chain link + /// if it does not contribute anything. + pub fn track(&self) -> Tracked<'_, Self> { + match self.outer { + Some(outer) if self.id.is_none() => outer, + _ => Track::track(self), } } } #[comemo::track] -impl Route { +impl<'a> Route<'a> { /// Whether the given id is part of the route. fn contains(&self, id: SourceId) -> bool { - self.id == Some(id) || self.parent.map_or(false, |parent| parent.contains(id)) + self.id == Some(id) || self.outer.map_or(false, |outer| outer.contains(id)) } } |
