diff --git a/crates/typst/src/engine.rs b/crates/typst/src/engine.rs index 9e4d9d709..c3a862f80 100644 --- a/crates/typst/src/engine.rs +++ b/crates/typst/src/engine.rs @@ -156,6 +156,11 @@ impl Sink { pub fn values(self) -> EcoVec<(Value, Option)> { self.values } + + /// Extend from another sink. + pub fn extend_from_sink(&mut self, other: Sink) { + self.extend(other.delayed, other.warnings, other.values); + } } #[comemo::track] @@ -181,7 +186,7 @@ impl Sink { } } - /// Extend from another sink. + /// Extend from parts of another sink. fn extend( &mut self, delayed: EcoVec, diff --git a/crates/typst/src/lib.rs b/crates/typst/src/lib.rs index 69c8dad8e..9888e4e49 100644 --- a/crates/typst/src/lib.rs +++ b/crates/typst/src/lib.rs @@ -128,6 +128,7 @@ fn compile_impl( .content(); let mut iter = 0; + let mut subsink; let mut document = Document::default(); // Relayout until all introspections stabilize. @@ -138,15 +139,14 @@ fn compile_impl( &["layout (1)", "layout (2)", "layout (3)", "layout (4)", "layout (5)"]; let _scope = TimingScope::new(ITER_NAMES[iter], None); - // Clear delayed errors. - sink.delayed(); + subsink = Sink::new(); let constraint = ::Constraint::new(); let mut engine = Engine { world, introspector: document.introspector.track_with(&constraint), traced, - sink: sink.track_mut(), + sink: subsink.track_mut(), route: Route::default(), }; @@ -160,7 +160,7 @@ fn compile_impl( } if iter >= 5 { - sink.warn(warning!( + subsink.warn(warning!( Span::detached(), "layout did not converge within 5 attempts"; hint: "check if any states or queries are updating themselves" )); @@ -168,6 +168,8 @@ fn compile_impl( } } + sink.extend_from_sink(subsink); + // Promote delayed errors. let delayed = sink.delayed(); if !delayed.is_empty() { diff --git a/tests/suite/foundations/context.typ b/tests/suite/foundations/context.typ index 0906fb1e4..9ed317575 100644 --- a/tests/suite/foundations/context.typ +++ b/tests/suite/foundations/context.typ @@ -76,3 +76,16 @@ // Warning: 2-44 `counter.display` without context is deprecated // Hint: 2-44 use it in a `context` expression instead #counter(heading).display(n => test(n, 10)) + +--- context-delayed-warning --- +// Ensure that the warning that triggers in the first layout iteration is not +// surfaced since it goes away in the second one. Just like errors in show +// rules. +#show heading: none + += A +#context { + let n = query().len() + let fonts = ("nope", "Roboto") + set text(font: fonts.at(n)) +}