mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
A little less route nesting
This commit is contained in:
parent
b9d025de83
commit
aa23198ad9
@ -8,9 +8,6 @@ use crate::introspection::{Introspector, Locator};
|
|||||||
use crate::syntax::FileId;
|
use crate::syntax::FileId;
|
||||||
use crate::World;
|
use crate::World;
|
||||||
|
|
||||||
/// The maxmium stack nesting depth.
|
|
||||||
const MAX_DEPTH: usize = 64;
|
|
||||||
|
|
||||||
/// Holds all data needed during compilation.
|
/// Holds all data needed during compilation.
|
||||||
pub struct Engine<'a> {
|
pub struct Engine<'a> {
|
||||||
/// The compilation environment.
|
/// The compilation environment.
|
||||||
@ -69,26 +66,28 @@ pub struct Route<'a> {
|
|||||||
upper: Cell<usize>,
|
upper: Cell<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The maximum nesting depths. They are different so that even if show rule and
|
||||||
|
/// call checks are interleaved, show rule problems we always get the show rule.
|
||||||
|
/// The lower the max depth for a kind of error, the higher its precedence
|
||||||
|
/// compared to the others.
|
||||||
|
impl Route<'_> {
|
||||||
|
/// The maximum stack nesting depth.
|
||||||
|
pub const MAX_SHOW_RULE_DEPTH: usize = 64;
|
||||||
|
|
||||||
|
/// The maxmium layout nesting depth.
|
||||||
|
pub const MAX_LAYOUT_DEPTH: usize = 72;
|
||||||
|
|
||||||
|
/// The maxmium function call nesting depth.
|
||||||
|
pub const MAX_CALL_DEPTH: usize = 80;
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Route<'a> {
|
impl<'a> Route<'a> {
|
||||||
/// Create a new, empty route.
|
/// Create a new, empty route.
|
||||||
pub fn root() -> Self {
|
pub fn root() -> Self {
|
||||||
Self { id: None, outer: None, len: 0, upper: Cell::new(0) }
|
Self { id: None, outer: None, len: 0, upper: Cell::new(0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert a new id into the route.
|
/// Extend the route with another segment with a default length of 1.
|
||||||
///
|
|
||||||
/// You must guarantee that `outer` lives longer than the resulting
|
|
||||||
/// route is ever used.
|
|
||||||
pub fn insert(outer: Tracked<'a, Self>, id: FileId) -> Self {
|
|
||||||
Route {
|
|
||||||
outer: Some(outer),
|
|
||||||
id: Some(id),
|
|
||||||
len: 0,
|
|
||||||
upper: Cell::new(usize::MAX),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Extend the route without another id.
|
|
||||||
pub fn extend(outer: Tracked<'a, Self>) -> Self {
|
pub fn extend(outer: Tracked<'a, Self>) -> Self {
|
||||||
Route {
|
Route {
|
||||||
outer: Some(outer),
|
outer: Some(outer),
|
||||||
@ -98,6 +97,16 @@ impl<'a> Route<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Attach a file id to the route segment.
|
||||||
|
pub fn with_id(self, id: FileId) -> Self {
|
||||||
|
Self { id: Some(id), ..self }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the length of the route segment to zero.
|
||||||
|
pub fn unnested(self) -> Self {
|
||||||
|
Self { len: 0, ..self }
|
||||||
|
}
|
||||||
|
|
||||||
/// Start tracking this route.
|
/// Start tracking this route.
|
||||||
///
|
///
|
||||||
/// In comparison to [`Track::track`], this method skips this chain link
|
/// In comparison to [`Track::track`], this method skips this chain link
|
||||||
@ -118,11 +127,6 @@ impl<'a> Route<'a> {
|
|||||||
pub fn decrease(&mut self) {
|
pub fn decrease(&mut self) {
|
||||||
self.len -= 1;
|
self.len -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check whether the nesting depth exceeds the limit.
|
|
||||||
pub fn exceeding(&self) -> bool {
|
|
||||||
!self.within(MAX_DEPTH)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[comemo::track]
|
#[comemo::track]
|
||||||
|
@ -28,7 +28,7 @@ impl Eval for ast::FuncCall<'_> {
|
|||||||
let args = self.args();
|
let args = self.args();
|
||||||
let trailing_comma = args.trailing_comma();
|
let trailing_comma = args.trailing_comma();
|
||||||
|
|
||||||
if vm.engine.route.exceeding() {
|
if !vm.engine.route.within(Route::MAX_CALL_DEPTH) {
|
||||||
bail!(span, "maximum function call depth exceeded");
|
bail!(span, "maximum function call depth exceeded");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ pub fn eval(
|
|||||||
let introspector = Introspector::default();
|
let introspector = Introspector::default();
|
||||||
let engine = Engine {
|
let engine = Engine {
|
||||||
world,
|
world,
|
||||||
route: Route::insert(route, id),
|
route: Route::extend(route).with_id(id),
|
||||||
introspector: introspector.track(),
|
introspector: introspector.track(),
|
||||||
locator: &mut locator,
|
locator: &mut locator,
|
||||||
tracer,
|
tracer,
|
||||||
|
@ -277,7 +277,7 @@ impl Counter {
|
|||||||
let mut engine = Engine {
|
let mut engine = Engine {
|
||||||
world,
|
world,
|
||||||
introspector,
|
introspector,
|
||||||
route: Route::extend(route),
|
route: Route::extend(route).unnested(),
|
||||||
locator: &mut locator,
|
locator: &mut locator,
|
||||||
tracer,
|
tracer,
|
||||||
};
|
};
|
||||||
|
@ -228,7 +228,7 @@ impl State {
|
|||||||
let mut engine = Engine {
|
let mut engine = Engine {
|
||||||
world,
|
world,
|
||||||
introspector,
|
introspector,
|
||||||
route: Route::extend(route),
|
route: Route::extend(route).unnested(),
|
||||||
locator: &mut locator,
|
locator: &mut locator,
|
||||||
tracer,
|
tracer,
|
||||||
};
|
};
|
||||||
|
@ -28,7 +28,7 @@ use crate::text::{
|
|||||||
use crate::util::Numeric;
|
use crate::util::Numeric;
|
||||||
use crate::World;
|
use crate::World;
|
||||||
|
|
||||||
/// Layout's content inline.
|
/// Layouts content inline.
|
||||||
pub(crate) fn layout_inline(
|
pub(crate) fn layout_inline(
|
||||||
children: &[Prehashed<Content>],
|
children: &[Prehashed<Content>],
|
||||||
engine: &mut Engine,
|
engine: &mut Engine,
|
||||||
|
@ -182,7 +182,7 @@ impl LayoutRoot for Content {
|
|||||||
let mut engine = Engine {
|
let mut engine = Engine {
|
||||||
world,
|
world,
|
||||||
introspector,
|
introspector,
|
||||||
route: Route::extend(route),
|
route: Route::extend(route).unnested(),
|
||||||
locator: &mut locator,
|
locator: &mut locator,
|
||||||
tracer,
|
tracer,
|
||||||
};
|
};
|
||||||
@ -237,7 +237,7 @@ impl Layout for Content {
|
|||||||
tracer,
|
tracer,
|
||||||
};
|
};
|
||||||
|
|
||||||
if engine.route.exceeding() {
|
if !engine.route.within(Route::MAX_LAYOUT_DEPTH) {
|
||||||
bail!(
|
bail!(
|
||||||
content.span(), "maximum layout depth exceeded";
|
content.span(), "maximum layout depth exceeded";
|
||||||
hint: "try to reduce the amount of nesting in your layout",
|
hint: "try to reduce the amount of nesting in your layout",
|
||||||
|
@ -11,7 +11,7 @@ use smallvec::smallvec;
|
|||||||
use typed_arena::Arena;
|
use typed_arena::Arena;
|
||||||
|
|
||||||
use crate::diag::{bail, SourceResult};
|
use crate::diag::{bail, SourceResult};
|
||||||
use crate::engine::Engine;
|
use crate::engine::{Engine, Route};
|
||||||
use crate::foundations::{
|
use crate::foundations::{
|
||||||
Content, Finalize, Guard, NativeElement, Recipe, Selector, Show, StyleChain,
|
Content, Finalize, Guard, NativeElement, Recipe, Selector, Show, StyleChain,
|
||||||
StyleVecBuilder, Styles, Synthesize,
|
StyleVecBuilder, Styles, Synthesize,
|
||||||
@ -307,7 +307,7 @@ impl<'a, 'v, 't> Builder<'a, 'v, 't> {
|
|||||||
|
|
||||||
if let Some(realized) = realize(self.engine, content, styles)? {
|
if let Some(realized) = realize(self.engine, content, styles)? {
|
||||||
self.engine.route.increase();
|
self.engine.route.increase();
|
||||||
if self.engine.route.exceeding() {
|
if !self.engine.route.within(Route::MAX_SHOW_RULE_DEPTH) {
|
||||||
bail!(
|
bail!(
|
||||||
content.span(), "maximum show rule depth exceeded";
|
content.span(), "maximum show rule depth exceeded";
|
||||||
hint: "check whether the show rule matches its own output";
|
hint: "check whether the show rule matches its own output";
|
||||||
|
@ -44,8 +44,8 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
// Test cyclic imports during layout.
|
// Test cyclic imports during layout.
|
||||||
// Error: 2-38 maximum layout depth exceeded
|
// Error: 14-37 maximum layout depth exceeded
|
||||||
// Hint: 2-38 try to reduce the amount of nesting in your layout
|
// Hint: 14-37 try to reduce the amount of nesting in your layout
|
||||||
#layout(_ => include "recursion.typ")
|
#layout(_ => include "recursion.typ")
|
||||||
|
|
||||||
---
|
---
|
||||||
|
Loading…
x
Reference in New Issue
Block a user