summaryrefslogtreecommitdiff
path: root/library/src
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2023-06-12 15:40:43 +0200
committerLaurenz <laurmaedje@gmail.com>2023-06-12 15:42:01 +0200
commit378ebe5f5601f11c3f428c17bed492012feb251e (patch)
tree4530bf009844faca40ca4fd6d0b9251fd51ef587 /library/src
parent19bf1f58944a42f17903869c162a33aba22b80b0 (diff)
Delayed errors
Fixes #785. Thanks to @Dherse for the idea!
Diffstat (limited to 'library/src')
-rw-r--r--library/src/layout/mod.rs44
-rw-r--r--library/src/layout/par.rs19
-rw-r--r--library/src/meta/bibliography.rs88
-rw-r--r--library/src/meta/context.rs10
-rw-r--r--library/src/meta/counter.rs76
-rw-r--r--library/src/meta/link.rs23
-rw-r--r--library/src/meta/reference.rs92
-rw-r--r--library/src/meta/state.rs37
8 files changed, 212 insertions, 177 deletions
diff --git a/library/src/layout/mod.rs b/library/src/layout/mod.rs
index d934c458..41490eb8 100644
--- a/library/src/layout/mod.rs
+++ b/library/src/layout/mod.rs
@@ -50,6 +50,7 @@ use std::mem;
use typed_arena::Arena;
use typst::diag::SourceResult;
use typst::eval::Tracer;
+use typst::model::DelayedErrors;
use typst::model::{applicable, realize, StyleVecBuilder};
use crate::math::{EquationElem, LayoutMath};
@@ -116,13 +117,20 @@ impl LayoutRoot for Content {
fn cached(
content: &Content,
world: Tracked<dyn World + '_>,
- tracer: TrackedMut<Tracer>,
- locator: Tracked<Locator>,
introspector: Tracked<Introspector>,
+ locator: Tracked<Locator>,
+ delayed: TrackedMut<DelayedErrors>,
+ tracer: TrackedMut<Tracer>,
styles: StyleChain,
) -> SourceResult<Document> {
let mut locator = Locator::chained(locator);
- let mut vt = Vt { world, tracer, locator: &mut locator, introspector };
+ let mut vt = Vt {
+ world,
+ introspector,
+ locator: &mut locator,
+ delayed,
+ tracer,
+ };
let scratch = Scratch::default();
let (realized, styles) = realize_root(&mut vt, &scratch, content, styles)?;
realized
@@ -132,13 +140,13 @@ impl LayoutRoot for Content {
}
tracing::info!("Starting layout");
-
cached(
self,
vt.world,
- TrackedMut::reborrow_mut(&mut vt.tracer),
- vt.locator.track(),
vt.introspector,
+ vt.locator.track(),
+ TrackedMut::reborrow_mut(&mut vt.delayed),
+ TrackedMut::reborrow_mut(&mut vt.tracer),
styles,
)
}
@@ -168,9 +176,10 @@ pub trait Layout {
let mut locator = Locator::chained(vt.locator.track());
let mut vt = Vt {
world: vt.world,
- tracer: TrackedMut::reborrow_mut(&mut vt.tracer),
- locator: &mut locator,
introspector: vt.introspector,
+ locator: &mut locator,
+ tracer: TrackedMut::reborrow_mut(&mut vt.tracer),
+ delayed: TrackedMut::reborrow_mut(&mut vt.delayed),
};
self.layout(&mut vt, styles, regions)
}
@@ -184,18 +193,26 @@ impl Layout for Content {
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
+ #[allow(clippy::too_many_arguments)]
#[comemo::memoize]
fn cached(
content: &Content,
world: Tracked<dyn World + '_>,
- tracer: TrackedMut<Tracer>,
- locator: Tracked<Locator>,
introspector: Tracked<Introspector>,
+ locator: Tracked<Locator>,
+ delayed: TrackedMut<DelayedErrors>,
+ tracer: TrackedMut<Tracer>,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
let mut locator = Locator::chained(locator);
- let mut vt = Vt { world, tracer, locator: &mut locator, introspector };
+ let mut vt = Vt {
+ world,
+ introspector,
+ locator: &mut locator,
+ delayed,
+ tracer,
+ };
let scratch = Scratch::default();
let (realized, styles) = realize_block(&mut vt, &scratch, content, styles)?;
realized
@@ -209,9 +226,10 @@ impl Layout for Content {
let fragment = cached(
self,
vt.world,
- TrackedMut::reborrow_mut(&mut vt.tracer),
- vt.locator.track(),
vt.introspector,
+ vt.locator.track(),
+ TrackedMut::reborrow_mut(&mut vt.delayed),
+ TrackedMut::reborrow_mut(&mut vt.tracer),
styles,
regions,
)?;
diff --git a/library/src/layout/par.rs b/library/src/layout/par.rs
index fa53f031..2d0944ce 100644
--- a/library/src/layout/par.rs
+++ b/library/src/layout/par.rs
@@ -5,6 +5,7 @@ use icu_provider_blob::BlobDataProvider;
use icu_segmenter::{LineBreakIteratorUtf8, LineSegmenter};
use once_cell::sync::Lazy;
use typst::eval::Tracer;
+use typst::model::DelayedErrors;
use unicode_bidi::{BidiInfo, Level as BidiLevel};
use unicode_script::{Script, UnicodeScript};
@@ -148,16 +149,23 @@ impl ParElem {
fn cached(
par: &ParElem,
world: Tracked<dyn World + '_>,
- tracer: TrackedMut<Tracer>,
- locator: Tracked<Locator>,
introspector: Tracked<Introspector>,
+ locator: Tracked<Locator>,
+ delayed: TrackedMut<DelayedErrors>,
+ tracer: TrackedMut<Tracer>,
styles: StyleChain,
consecutive: bool,
region: Size,
expand: bool,
) -> SourceResult<Fragment> {
let mut locator = Locator::chained(locator);
- let mut vt = Vt { world, tracer, locator: &mut locator, introspector };
+ let mut vt = Vt {
+ world,
+ introspector,
+ locator: &mut locator,
+ delayed,
+ tracer,
+ };
let children = par.children();
// Collect all text into one string for BiDi analysis.
@@ -178,9 +186,10 @@ impl ParElem {
let fragment = cached(
self,
vt.world,
- TrackedMut::reborrow_mut(&mut vt.tracer),
- vt.locator.track(),
vt.introspector,
+ vt.locator.track(),
+ TrackedMut::reborrow_mut(&mut vt.delayed),
+ TrackedMut::reborrow_mut(&mut vt.tracer),
styles,
consecutive,
region,
diff --git a/library/src/meta/bibliography.rs b/library/src/meta/bibliography.rs
index 737530b8..f020f730 100644
--- a/library/src/meta/bibliography.rs
+++ b/library/src/meta/bibliography.rs
@@ -96,11 +96,11 @@ impl BibliographyElem {
pub fn find(introspector: Tracked<Introspector>) -> StrResult<Self> {
let mut iter = introspector.query(&Self::func().select()).into_iter();
let Some(elem) = iter.next() else {
- return Err("the document does not contain a bibliography".into());
+ bail!("the document does not contain a bibliography");
};
if iter.next().is_some() {
- Err("multiple bibliographies are not supported")?;
+ bail!("multiple bibliographies are not supported");
}
Ok(elem.to::<Self>().unwrap().clone())
@@ -162,42 +162,40 @@ impl Show for BibliographyElem {
seq.push(HeadingElem::new(title).with_level(NonZeroUsize::ONE).pack());
}
- if !vt.introspector.init() {
- return Ok(Content::sequence(seq));
- }
+ Ok(vt.delayed(|vt| {
+ let works = Works::new(vt).at(self.span())?;
- let works = Works::new(vt).at(self.span())?;
+ let row_gutter = BlockElem::below_in(styles).amount();
+ if works.references.iter().any(|(prefix, _)| prefix.is_some()) {
+ let mut cells = vec![];
+ for (prefix, reference) in &works.references {
+ cells.push(prefix.clone().unwrap_or_default());
+ cells.push(reference.clone());
+ }
- let row_gutter = BlockElem::below_in(styles).amount();
- if works.references.iter().any(|(prefix, _)| prefix.is_some()) {
- let mut cells = vec![];
- for (prefix, reference) in &works.references {
- cells.push(prefix.clone().unwrap_or_default());
- cells.push(reference.clone());
- }
+ seq.push(VElem::new(row_gutter).with_weakness(3).pack());
+ seq.push(
+ GridElem::new(cells)
+ .with_columns(TrackSizings(vec![Sizing::Auto; 2]))
+ .with_column_gutter(TrackSizings(vec![COLUMN_GUTTER.into()]))
+ .with_row_gutter(TrackSizings(vec![row_gutter.into()]))
+ .pack(),
+ );
+ } else {
+ let mut entries = vec![];
+ for (_, reference) in &works.references {
+ entries.push(VElem::new(row_gutter).with_weakness(3).pack());
+ entries.push(reference.clone());
+ }
- seq.push(VElem::new(row_gutter).with_weakness(3).pack());
- seq.push(
- GridElem::new(cells)
- .with_columns(TrackSizings(vec![Sizing::Auto; 2]))
- .with_column_gutter(TrackSizings(vec![COLUMN_GUTTER.into()]))
- .with_row_gutter(TrackSizings(vec![row_gutter.into()]))
- .pack(),
- );
- } else {
- let mut entries = vec![];
- for (_, reference) in &works.references {
- entries.push(VElem::new(row_gutter).with_weakness(3).pack());
- entries.push(reference.clone());
+ seq.push(
+ Content::sequence(entries)
+ .styled(ParElem::set_hanging_indent(INDENT.into())),
+ );
}
- seq.push(
- Content::sequence(entries)
- .styled(ParElem::set_hanging_indent(INDENT.into())),
- );
- }
-
- Ok(Content::sequence(seq))
+ Ok(Content::sequence(seq))
+ }))
}
}
@@ -357,19 +355,17 @@ impl Synthesize for CiteElem {
impl Show for CiteElem {
#[tracing::instrument(name = "CiteElem::show", skip(self, vt))]
fn show(&self, vt: &mut Vt, _: StyleChain) -> SourceResult<Content> {
- if !vt.introspector.init() {
- return Ok(Content::empty());
- }
-
- let works = Works::new(vt).at(self.span())?;
- let location = self.0.location().unwrap();
- works
- .citations
- .get(&location)
- .cloned()
- .flatten()
- .ok_or("bibliography does not contain this key")
- .at(self.span())
+ Ok(vt.delayed(|vt| {
+ let works = Works::new(vt).at(self.span())?;
+ let location = self.0.location().unwrap();
+ works
+ .citations
+ .get(&location)
+ .cloned()
+ .flatten()
+ .ok_or("bibliography does not contain this key")
+ .at(self.span())
+ }))
}
}
diff --git a/library/src/meta/context.rs b/library/src/meta/context.rs
index d599c63e..2ed359ee 100644
--- a/library/src/meta/context.rs
+++ b/library/src/meta/context.rs
@@ -73,12 +73,10 @@ struct LocateElem {
impl Show for LocateElem {
#[tracing::instrument(name = "LocateElem::show", skip(self, vt))]
fn show(&self, vt: &mut Vt, _: StyleChain) -> SourceResult<Content> {
- if !vt.introspector.init() {
- return Ok(Content::empty());
- }
-
- let location = self.0.location().unwrap();
- Ok(self.func().call_vt(vt, [location])?.display())
+ Ok(vt.delayed(|vt| {
+ let location = self.0.location().unwrap();
+ Ok(self.func().call_vt(vt, [location])?.display())
+ }))
}
}
diff --git a/library/src/meta/counter.rs b/library/src/meta/counter.rs
index ef4646ab..65522c40 100644
--- a/library/src/meta/counter.rs
+++ b/library/src/meta/counter.rs
@@ -4,6 +4,7 @@ use std::str::FromStr;
use ecow::{eco_vec, EcoVec};
use smallvec::{smallvec, SmallVec};
use typst::eval::Tracer;
+use typst::model::DelayedErrors;
use super::{FigureElem, HeadingElem, Numbering, NumberingPattern};
use crate::layout::PageElem;
@@ -397,9 +398,10 @@ impl Counter {
) -> SourceResult<EcoVec<(CounterState, NonZeroUsize)>> {
self.sequence_impl(
vt.world,
- TrackedMut::reborrow_mut(&mut vt.tracer),
- vt.locator.track(),
vt.introspector,
+ vt.locator.track(),
+ TrackedMut::reborrow_mut(&mut vt.delayed),
+ TrackedMut::reborrow_mut(&mut vt.tracer),
)
}
@@ -408,12 +410,19 @@ impl Counter {
fn sequence_impl(
&self,
world: Tracked<dyn World + '_>,
- tracer: TrackedMut<Tracer>,
- locator: Tracked<Locator>,
introspector: Tracked<Introspector>,
+ locator: Tracked<Locator>,
+ delayed: TrackedMut<DelayedErrors>,
+ tracer: TrackedMut<Tracer>,
) -> SourceResult<EcoVec<(CounterState, NonZeroUsize)>> {
let mut locator = Locator::chained(locator);
- let mut vt = Vt { world, tracer, locator: &mut locator, introspector };
+ let mut vt = Vt {
+ world,
+ introspector,
+ locator: &mut locator,
+ delayed,
+ tracer,
+ };
let mut state = CounterState(match &self.0 {
// special case, because pages always start at one.
CounterKey::Page => smallvec![1],
@@ -618,37 +627,36 @@ struct DisplayElem {
impl Show for DisplayElem {
#[tracing::instrument(name = "DisplayElem::show", skip_all)]
fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
- if !vt.introspector.init() {
- return Ok(Content::empty());
- }
-
- let location = self.0.location().unwrap();
- let counter = self.counter();
- let numbering = self
- .numbering()
- .or_else(|| {
- let CounterKey::Selector(Selector::Elem(func, _)) = counter.0 else {
- return None;
+ Ok(vt.delayed(|vt| {
+ let location = self.0.location().unwrap();
+ let counter = self.counter();
+ let numbering = self
+ .numbering()
+ .or_else(|| {
+ let CounterKey::Selector(Selector::Elem(func, _)) = counter.0 else {
+ return None;
+ };
+
+ if func == HeadingElem::func() {
+ HeadingElem::numbering_in(styles)
+ } else if func == FigureElem::func() {
+ FigureElem::numbering_in(styles)
+ } else if func == EquationElem::func() {
+ EquationElem::numbering_in(styles)
+ } else {
+ None
+ }
+ })
+ .unwrap_or_else(|| NumberingPattern::from_str("1.1").unwrap().into());
+
+ let state = if self.both() {
+ counter.both(vt, location)?
+ } else {
+ counter.at(vt, location)?
};
- if func == HeadingElem::func() {
- HeadingElem::numbering_in(styles)
- } else if func == FigureElem::func() {
- FigureElem::numbering_in(styles)
- } else if func == EquationElem::func() {
- EquationElem::numbering_in(styles)
- } else {
- None
- }
- })
- .unwrap_or_else(|| NumberingPattern::from_str("1.1").unwrap().into());
-
- let state = if self.both() {
- counter.both(vt, location)?
- } else {
- counter.at(vt, location)?
- };
- state.display(vt, &numbering)
+ state.display(vt, &numbering)
+ }))
}
}
diff --git a/library/src/meta/link.rs b/library/src/meta/link.rs
index 43f6a34d..c3d8718c 100644
--- a/library/src/meta/link.rs
+++ b/library/src/meta/link.rs
@@ -91,21 +91,18 @@ impl Show for LinkElem {
#[tracing::instrument(name = "LinkElem::show", skip(self, vt))]
fn show(&self, vt: &mut Vt, _: StyleChain) -> SourceResult<Content> {
let body = self.body();
- let dest = match self.dest() {
- LinkTarget::Dest(dest) => dest,
- LinkTarget::Label(label) => {
- if !vt.introspector.init() {
- return Ok(body);
- }
-
- let elem = vt.introspector.query_label(&label).at(self.span())?;
- Destination::Location(elem.location().unwrap())
- }
+ let linked = match self.dest() {
+ LinkTarget::Dest(dest) => body.linked(dest),
+ LinkTarget::Label(label) => vt
+ .delayed(|vt| {
+ let elem = vt.introspector.query_label(&label).at(self.span())?;
+ let dest = Destination::Location(elem.location().unwrap());
+ Ok(Some(body.clone().linked(dest)))
+ })
+ .unwrap_or(body),
};
- Ok(body
- .linked(dest)
- .styled(TextElem::set_hyphenate(Hyphenate(Smart::Custom(false)))))
+ Ok(linked.styled(TextElem::set_hyphenate(Hyphenate(Smart::Custom(false)))))
}
}
diff --git a/library/src/meta/reference.rs b/library/src/meta/reference.rs
index 5a295e33..96358ffa 100644
--- a/library/src/meta/reference.rs
+++ b/library/src/meta/reference.rs
@@ -132,7 +132,7 @@ impl Synthesize for RefElem {
self.push_element(None);
let target = self.target();
- if vt.introspector.init() && !BibliographyElem::has(vt, &target.0) {
+ if !BibliographyElem::has(vt, &target.0) {
if let Ok(elem) = vt.introspector.query_label(&target) {
self.push_element(Some(elem.into_inner()));
return Ok(());
@@ -146,63 +146,65 @@ impl Synthesize for RefElem {
impl Show for RefElem {
#[tracing::instrument(name = "RefElem::show", skip_all)]
fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
- if !vt.introspector.init() {
- return Ok(Content::empty());
- }
+ Ok(vt.delayed(|vt| {
+ let target = self.target();
+ let elem = vt.introspector.query_label(&self.target());
+ let span = self.span();
- let target = self.target();
- let elem = vt.introspector.query_label(&self.target());
- let span = self.span();
+ if BibliographyElem::has(vt, &target.0) {
+ if elem.is_ok() {
+ bail!(span, "label occurs in the document and its bibliography");
+ }
- if BibliographyElem::has(vt, &target.0) {
- if elem.is_ok() {
- bail!(span, "label occurs in the document and its bibliography");
+ return Ok(self.to_citation(vt, styles)?.pack().spanned(span));
}
- return Ok(self.to_citation(vt, styles)?.pack().spanned(span));
- }
+ let elem = elem.at(span)?;
+ let refable = elem
+ .with::<dyn Refable>()
+ .ok_or_else(|| {
+ if elem.can::<dyn Figurable>() {
+ eco_format!(
+ "cannot reference {} directly, try putting it into a figure",
+ elem.func().name()
+ )
+ } else {
+ eco_format!("cannot reference {}", elem.func().name())
+ }
+ })
+ .at(span)?;
- let elem = elem.at(span)?;
- let refable = elem
- .with::<dyn Refable>()
- .ok_or_else(|| {
- if elem.can::<dyn Figurable>() {
+ let numbering = refable
+ .numbering()
+ .ok_or_else(|| {
eco_format!(
- "cannot reference {} directly, try putting it into a figure",
+ "cannot reference {0} without numbering \
+ - did you mean to use `#set {0}(numbering: \"1.\")`?",
elem.func().name()
)
- } else {
- eco_format!("cannot reference {}", elem.func().name())
- }
- })
- .at(span)?;
+ })
+ .at(span)?;
- let numbering = refable
- .numbering()
- .ok_or_else(|| {
- eco_format!("cannot reference {0} without numbering - did you mean to use `#set {0}(numbering: \"1.\")`?", elem.func().name())
- })
- .at(span)?;
+ let numbers = refable
+ .counter()
+ .at(vt, elem.location().unwrap())?
+ .display(vt, &numbering.trimmed())?;
- let numbers = refable
- .counter()
- .at(vt, elem.location().unwrap())?
- .display(vt, &numbering.trimmed())?;
+ let supplement = match self.supplement(styles) {
+ Smart::Auto => refable.supplement(),
+ Smart::Custom(None) => Content::empty(),
+ Smart::Custom(Some(supplement)) => {
+ supplement.resolve(vt, [(*elem).clone()])?
+ }
+ };
- let supplement = match self.supplement(styles) {
- Smart::Auto => refable.supplement(),
- Smart::Custom(None) => Content::empty(),
- Smart::Custom(Some(supplement)) => {
- supplement.resolve(vt, [(*elem).clone()])?
+ let mut content = numbers;
+ if !supplement.is_empty() {
+ content = supplement + TextElem::packed("\u{a0}") + content;
}
- };
-
- let mut content = numbers;
- if !supplement.is_empty() {
- content = supplement + TextElem::packed("\u{a0}") + content;
- }
- Ok(content.linked(Destination::Location(elem.location().unwrap())))
+ Ok(content.linked(Destination::Location(elem.location().unwrap())))
+ }))
}
}
diff --git a/library/src/meta/state.rs b/library/src/meta/state.rs
index 231852e3..a8e37901 100644
--- a/library/src/meta/state.rs
+++ b/library/src/meta/state.rs
@@ -2,6 +2,7 @@ use std::fmt::{self, Debug, Formatter, Write};
use ecow::{eco_vec, EcoVec};
use typst::eval::Tracer;
+use typst::model::DelayedErrors;
use crate::prelude::*;
@@ -306,9 +307,10 @@ impl State {
fn sequence(&self, vt: &mut Vt) -> SourceResult<EcoVec<Value>> {
self.sequence_impl(
vt.world,
- TrackedMut::reborrow_mut(&mut vt.tracer),
- vt.locator.track(),
vt.introspector,
+ vt.locator.track(),
+ TrackedMut::reborrow_mut(&mut vt.delayed),
+ TrackedMut::reborrow_mut(&mut vt.tracer),
)
}
@@ -317,12 +319,19 @@ impl State {
fn sequence_impl(
&self,
world: Tracked<dyn World + '_>,
- tracer: TrackedMut<Tracer>,
- locator: Tracked<Locator>,
introspector: Tracked<Introspector>,
+ locator: Tracked<Locator>,
+ delayed: TrackedMut<DelayedErrors>,
+ tracer: TrackedMut<Tracer>,
) -> SourceResult<EcoVec<Value>> {
let mut locator = Locator::chained(locator);
- let mut vt = Vt { world, tracer, locator: &mut locator, introspector };
+ let mut vt = Vt {
+ world,
+ introspector,
+ locator: &mut locator,
+ delayed,
+ tracer,
+ };
let mut state = self.init.clone();
let mut stops = eco_vec![state.clone()];
@@ -397,16 +406,14 @@ struct DisplayElem {
impl Show for DisplayElem {
#[tracing::instrument(name = "DisplayElem::show", skip(self, vt))]
fn show(&self, vt: &mut Vt, _: StyleChain) -> SourceResult<Content> {
- if !vt.introspector.init() {
- return Ok(Content::empty());
- }
-
- let location = self.0.location().unwrap();
- let value = self.state().at(vt, location)?;
- Ok(match self.func() {
- Some(func) => func.call_vt(vt, [value])?.display(),
- None => value.display(),
- })
+ Ok(vt.delayed(|vt| {
+ let location = self.0.location().unwrap();
+ let value = self.state().at(vt, location)?;
+ Ok(match self.func() {
+ Some(func) => func.call_vt(vt, [value])?.display(),
+ None => value.display(),
+ })
+ }))
}
}