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.
This commit is contained in:
parent
d9ba84085e
commit
47dff3765d
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -369,8 +369,7 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||
[[package]]
|
||||
name = "comemo"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ba423e212681b51c5452a458bb24e88165f4c09857a783c802719cc46313f3f"
|
||||
source = "git+https://github.com/typst/comemo#0c141bbe47ca2d8c123fffc3f7f1ce35bb693993"
|
||||
dependencies = [
|
||||
"comemo-macros",
|
||||
"siphasher",
|
||||
@ -379,8 +378,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "comemo-macros"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fca5ceeb99665bad04a32fe297d1581a68685e36fb6da92a1c9b7d9693638c01"
|
||||
source = "git+https://github.com/typst/comemo#0c141bbe47ca2d8c123fffc3f7f1ce35bb693993"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -36,7 +36,7 @@ bench = false
|
||||
typst-macros = { path = "macros" }
|
||||
bitflags = { version = "2", features = ["serde"] }
|
||||
bytemuck = "1"
|
||||
comemo = "0.2.2"
|
||||
comemo = { git = "https://github.com/typst/comemo" }
|
||||
ecow = "0.1"
|
||||
flate2 = "1"
|
||||
fontdb = "0.13"
|
||||
|
@ -25,7 +25,7 @@ typst-library = { path = "../library" }
|
||||
chrono = { version = "0.4", default-features = false, features = ["clock", "std"] }
|
||||
clap = { version = "4.2.4", features = ["derive", "env"] }
|
||||
codespan-reporting = "0.11"
|
||||
comemo = "0.2.2"
|
||||
comemo = { git = "https://github.com/typst/comemo" }
|
||||
dirs = "5"
|
||||
elsa = "1.8"
|
||||
inferno = "0.11.15"
|
||||
|
@ -13,7 +13,7 @@ bench = false
|
||||
[dependencies]
|
||||
typst = { path = ".." }
|
||||
typst-library = { path = "../library" }
|
||||
comemo = "0.2.2"
|
||||
comemo = { git = "https://github.com/typst/comemo" }
|
||||
heck = "0.4"
|
||||
include_dir = "0.7"
|
||||
once_cell = "1"
|
||||
|
@ -19,7 +19,7 @@ bench = false
|
||||
typst = { path = ".." }
|
||||
az = "1.2"
|
||||
chinese-number = { version = "0.7.2", default-features = false, features = ["number-to-chinese"] }
|
||||
comemo = "0.2.2"
|
||||
comemo = { git = "https://github.com/typst/comemo" }
|
||||
csv = "1"
|
||||
ecow = "0.1"
|
||||
hayagriva = "0.3"
|
||||
|
@ -73,7 +73,7 @@ impl LayoutRoot for Content {
|
||||
#[comemo::memoize]
|
||||
fn cached(
|
||||
content: &Content,
|
||||
world: Tracked<dyn World>,
|
||||
world: Tracked<dyn World + '_>,
|
||||
tracer: TrackedMut<Tracer>,
|
||||
provider: TrackedMut<StabilityProvider>,
|
||||
introspector: Tracked<Introspector>,
|
||||
@ -139,7 +139,7 @@ impl Layout for Content {
|
||||
#[comemo::memoize]
|
||||
fn cached(
|
||||
content: &Content,
|
||||
world: Tracked<dyn World>,
|
||||
world: Tracked<dyn World + '_>,
|
||||
tracer: TrackedMut<Tracer>,
|
||||
provider: TrackedMut<StabilityProvider>,
|
||||
introspector: Tracked<Introspector>,
|
||||
|
@ -139,7 +139,7 @@ impl ParElem {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn cached(
|
||||
par: &ParElem,
|
||||
world: Tracked<dyn World>,
|
||||
world: Tracked<dyn World + '_>,
|
||||
tracer: TrackedMut<Tracer>,
|
||||
provider: TrackedMut<StabilityProvider>,
|
||||
introspector: Tracked<Introspector>,
|
||||
|
@ -121,7 +121,7 @@ impl BibliographyElem {
|
||||
|
||||
/// Find all bibliography keys.
|
||||
pub fn keys(
|
||||
world: Tracked<dyn World>,
|
||||
world: Tracked<dyn World + '_>,
|
||||
introspector: Tracked<Introspector>,
|
||||
) -> Vec<(EcoString, Option<EcoString>)> {
|
||||
Self::find(introspector)
|
||||
@ -426,7 +426,7 @@ impl Works {
|
||||
/// Generate all citations and the whole bibliography.
|
||||
#[comemo::memoize]
|
||||
fn create(
|
||||
world: Tracked<dyn World>,
|
||||
world: Tracked<dyn World + '_>,
|
||||
bibliography: BibliographyElem,
|
||||
citations: Vec<CiteElem>,
|
||||
) -> Arc<Works> {
|
||||
@ -582,7 +582,7 @@ fn create(
|
||||
/// Load bibliography entries from a path.
|
||||
#[comemo::memoize]
|
||||
fn load(
|
||||
world: Tracked<dyn World>,
|
||||
world: Tracked<dyn World + '_>,
|
||||
paths: &BibPaths,
|
||||
) -> StrResult<EcoVec<hayagriva::Entry>> {
|
||||
let mut result = EcoVec::new();
|
||||
|
@ -405,7 +405,7 @@ impl Counter {
|
||||
#[comemo::memoize]
|
||||
fn sequence_impl(
|
||||
&self,
|
||||
world: Tracked<dyn World>,
|
||||
world: Tracked<dyn World + '_>,
|
||||
tracer: TrackedMut<Tracer>,
|
||||
provider: TrackedMut<StabilityProvider>,
|
||||
introspector: Tracked<Introspector>,
|
||||
|
@ -320,7 +320,7 @@ impl State {
|
||||
#[comemo::memoize]
|
||||
fn sequence_impl(
|
||||
&self,
|
||||
world: Tracked<dyn World>,
|
||||
world: Tracked<dyn World + '_>,
|
||||
tracer: TrackedMut<Tracer>,
|
||||
provider: TrackedMut<StabilityProvider>,
|
||||
introspector: Tracked<Introspector>,
|
||||
|
@ -448,8 +448,8 @@ impl Debug for ShapedText<'_> {
|
||||
}
|
||||
|
||||
/// Holds shaping results and metadata common to all shaped segments.
|
||||
struct ShapingContext<'a> {
|
||||
vt: &'a Vt<'a>,
|
||||
struct ShapingContext<'a, 'v> {
|
||||
vt: &'a Vt<'v>,
|
||||
spans: &'a SpanMapper,
|
||||
glyphs: Vec<ShapedGlyph>,
|
||||
used: Vec<Font>,
|
||||
|
@ -165,7 +165,7 @@ pub enum ImageFit {
|
||||
/// Load an image from a path.
|
||||
#[comemo::memoize]
|
||||
fn load(
|
||||
world: Tracked<dyn World>,
|
||||
world: Tracked<dyn World + '_>,
|
||||
full: &str,
|
||||
fallback_family: Option<&str>,
|
||||
alt: Option<EcoString>,
|
||||
|
@ -130,13 +130,13 @@ impl Display for Tracepoint {
|
||||
/// Enrich a [`SourceResult`] with a tracepoint.
|
||||
pub trait Trace<T> {
|
||||
/// Add the tracepoint to all errors that lie outside the `span`.
|
||||
fn trace<F>(self, world: Tracked<dyn World>, make_point: F, span: Span) -> Self
|
||||
fn trace<F>(self, world: Tracked<dyn World + '_>, make_point: F, span: Span) -> Self
|
||||
where
|
||||
F: Fn() -> Tracepoint;
|
||||
}
|
||||
|
||||
impl<T> Trace<T> for SourceResult<T> {
|
||||
fn trace<F>(self, world: Tracked<dyn World>, make_point: F, span: Span) -> Self
|
||||
fn trace<F>(self, world: Tracked<dyn World + '_>, make_point: F, span: Span) -> Self
|
||||
where
|
||||
F: Fn() -> Tracepoint,
|
||||
{
|
||||
|
@ -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>,
|
||||
|
@ -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`.
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ impl Image {
|
||||
pub fn with_fonts(
|
||||
data: Buffer,
|
||||
format: ImageFormat,
|
||||
world: Tracked<dyn World>,
|
||||
world: Tracked<dyn World + '_>,
|
||||
fallback_family: Option<&str>,
|
||||
alt: Option<EcoString>,
|
||||
) -> StrResult<Self> {
|
||||
@ -240,7 +240,7 @@ fn decode_svg(data: &Buffer) -> StrResult<Arc<DecodedImage>> {
|
||||
#[comemo::memoize]
|
||||
fn decode_svg_with_fonts(
|
||||
data: &Buffer,
|
||||
world: Tracked<dyn World>,
|
||||
world: Tracked<dyn World + '_>,
|
||||
fallback_family: Option<&str>,
|
||||
) -> StrResult<Arc<DecodedImage>> {
|
||||
let mut opts = usvg::Options::default();
|
||||
@ -269,7 +269,7 @@ fn decode_svg_with_fonts(
|
||||
/// Discover and load the fonts referenced by an SVG.
|
||||
fn load_svg_fonts(
|
||||
tree: &usvg::Tree,
|
||||
world: Tracked<dyn World>,
|
||||
world: Tracked<dyn World + '_>,
|
||||
fallback_family: Option<&str>,
|
||||
) -> fontdb::Database {
|
||||
let mut referenced = BTreeMap::<EcoString, bool>::new();
|
||||
|
@ -65,7 +65,7 @@ use crate::util::Buffer;
|
||||
|
||||
/// Compile a source file into a fully layouted document.
|
||||
#[tracing::instrument(skip(world))]
|
||||
pub fn compile(world: &(dyn World + 'static)) -> SourceResult<Document> {
|
||||
pub fn compile(world: &dyn World) -> SourceResult<Document> {
|
||||
// Evaluate the source file into a module.
|
||||
let route = Route::default();
|
||||
let mut tracer = Tracer::default();
|
||||
|
@ -14,7 +14,7 @@ pub use self::styles::*;
|
||||
|
||||
pub use typst_macros::element;
|
||||
|
||||
use comemo::{Constraint, Track, Tracked, TrackedMut};
|
||||
use comemo::{Track, Tracked, TrackedMut, Validate};
|
||||
|
||||
use crate::diag::SourceResult;
|
||||
use crate::doc::Document;
|
||||
@ -25,7 +25,7 @@ use crate::World;
|
||||
#[comemo::memoize]
|
||||
#[tracing::instrument(skip(world, tracer, content))]
|
||||
pub fn typeset(
|
||||
world: Tracked<dyn World>,
|
||||
world: Tracked<dyn World + '_>,
|
||||
mut tracer: TrackedMut<Tracer>,
|
||||
content: &Content,
|
||||
) -> SourceResult<Document> {
|
||||
@ -42,8 +42,8 @@ pub fn typeset(
|
||||
loop {
|
||||
tracing::info!("Layout iteration {iter}");
|
||||
|
||||
let constraint = Constraint::new();
|
||||
let mut provider = StabilityProvider::new();
|
||||
let constraint = <Introspector as Validate>::Constraint::new();
|
||||
let mut vt = Vt {
|
||||
world,
|
||||
tracer: TrackedMut::reborrow_mut(&mut tracer),
|
||||
@ -56,7 +56,7 @@ pub fn typeset(
|
||||
|
||||
introspector = Introspector::new(&document.pages);
|
||||
|
||||
if iter >= 5 || introspector.valid(&constraint) {
|
||||
if iter >= 5 || introspector.validate(&constraint) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -69,7 +69,7 @@ pub fn typeset(
|
||||
/// Holds the state needed to [typeset] content.
|
||||
pub struct Vt<'a> {
|
||||
/// The compilation environment.
|
||||
pub world: Tracked<'a, dyn World>,
|
||||
pub world: Tracked<'a, dyn World + 'a>,
|
||||
/// The tracer for inspection of the values an expression produces.
|
||||
pub tracer: TrackedMut<'a, Tracer>,
|
||||
/// Provides stable identities to elements.
|
||||
|
@ -9,7 +9,7 @@ publish = false
|
||||
[dev-dependencies]
|
||||
typst = { path = ".." }
|
||||
typst-library = { path = "../library" }
|
||||
comemo = "0.2.2"
|
||||
comemo = { git = "https://github.com/typst/comemo" }
|
||||
elsa = "1.8"
|
||||
iai = { git = "https://github.com/reknih/iai" }
|
||||
once_cell = "1"
|
||||
|
Loading…
Reference in New Issue
Block a user