summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2024-02-21 15:11:35 +0100
committerGitHub <noreply@github.com>2024-02-21 14:11:35 +0000
commit56ecd6c806ab32a7cca5289500504e398198d283 (patch)
tree1b6fd1b34922d2877a714398beedb20f3e6cd317 /crates
parent23756f9e8b0e3bf5b3e1126f681024575cca4529 (diff)
Wider callsite span (#3466)
Diffstat (limited to 'crates')
-rw-r--r--crates/typst/src/eval/access.rs2
-rw-r--r--crates/typst/src/eval/call.rs12
-rw-r--r--crates/typst/src/eval/rules.rs2
-rw-r--r--crates/typst/src/foundations/args.rs15
-rw-r--r--crates/typst/src/foundations/calc.rs22
5 files changed, 34 insertions, 19 deletions
diff --git a/crates/typst/src/eval/access.rs b/crates/typst/src/eval/access.rs
index e3bf2bf0..6b6dff15 100644
--- a/crates/typst/src/eval/access.rs
+++ b/crates/typst/src/eval/access.rs
@@ -56,7 +56,7 @@ impl Access for ast::FuncCall<'_> {
if is_accessor_method(&method) {
let span = self.span();
let world = vm.world();
- let args = self.args().eval(vm)?;
+ let args = self.args().eval(vm)?.spanned(span);
let value = access.target().access(vm)?;
let result = call_method_access(value, &method, args, span);
let point = || Tracepoint::Call(Some(method.get().clone()));
diff --git a/crates/typst/src/eval/call.rs b/crates/typst/src/eval/call.rs
index 26626b1e..3f7224d8 100644
--- a/crates/typst/src/eval/call.rs
+++ b/crates/typst/src/eval/call.rs
@@ -12,7 +12,7 @@ use crate::introspection::{Introspector, Locator};
use crate::math::{Accent, AccentElem, LrElem};
use crate::symbols::Symbol;
use crate::syntax::ast::{self, AstNode};
-use crate::syntax::{Spanned, SyntaxNode};
+use crate::syntax::{Span, Spanned, SyntaxNode};
use crate::text::TextElem;
use crate::util::LazyHash;
use crate::World;
@@ -40,7 +40,7 @@ impl Eval for ast::FuncCall<'_> {
let field_span = field.span();
let target = if is_mutating_method(&field) {
- let mut args = args.eval(vm)?;
+ let mut args = args.eval(vm)?.spanned(span);
let target = target.access(vm)?;
// Only arrays and dictionaries have mutable methods.
@@ -59,7 +59,7 @@ impl Eval for ast::FuncCall<'_> {
access.target().eval(vm)?
};
- let mut args = args.eval(vm)?;
+ let mut args = args.eval(vm)?.spanned(span);
// Handle plugins.
if let Value::Plugin(plugin) = &target {
@@ -126,7 +126,7 @@ impl Eval for ast::FuncCall<'_> {
bail!(error);
}
} else {
- (callee.eval(vm)?, args.eval(vm)?)
+ (callee.eval(vm)?, args.eval(vm)?.spanned(span))
};
// Handle math special cases for non-functions:
@@ -222,7 +222,9 @@ impl Eval for ast::Args<'_> {
}
}
- Ok(Args { span: self.span(), items })
+ // We do *not* use the `self.span()` here because we want the callsite
+ // span to be one level higher (the whole function call).
+ Ok(Args { span: Span::detached(), items })
}
}
diff --git a/crates/typst/src/eval/rules.rs b/crates/typst/src/eval/rules.rs
index e34fe5cd..f5d7da17 100644
--- a/crates/typst/src/eval/rules.rs
+++ b/crates/typst/src/eval/rules.rs
@@ -23,7 +23,7 @@ impl Eval for ast::SetRule<'_> {
})
})
.at(target.span())?;
- let args = self.args().eval(vm)?;
+ let args = self.args().eval(vm)?.spanned(self.span());
Ok(target.set(&mut vm.engine, args)?.spanned(self.span()))
}
}
diff --git a/crates/typst/src/foundations/args.rs b/crates/typst/src/foundations/args.rs
index 54811437..4624ae02 100644
--- a/crates/typst/src/foundations/args.rs
+++ b/crates/typst/src/foundations/args.rs
@@ -42,7 +42,8 @@ use crate::syntax::{Span, Spanned};
#[derive(Clone, Hash)]
#[allow(clippy::derived_hash_with_manual_eq)]
pub struct Args {
- /// The span of the whole argument list.
+ /// The callsite span for the function. This is not the span of the argument
+ /// list itself, but of the whole function call.
pub span: Span,
/// The positional and named arguments.
pub items: EcoVec<Arg>,
@@ -62,6 +63,14 @@ impl Args {
Self { span, items }
}
+ /// Attach a span to these arguments if they don't already have one.
+ pub fn spanned(mut self, span: Span) -> Self {
+ if self.span.is_detached() {
+ self.span = span;
+ }
+ self
+ }
+
/// Returns the number of remaining positional arguments.
pub fn remaining(&self) -> usize {
self.items.iter().filter(|slot| slot.name.is_none()).count()
@@ -345,8 +354,8 @@ pub trait IntoArgs {
}
impl IntoArgs for Args {
- fn into_args(self, _: Span) -> Args {
- self
+ fn into_args(self, fallback: Span) -> Args {
+ self.spanned(fallback)
}
}
diff --git a/crates/typst/src/foundations/calc.rs b/crates/typst/src/foundations/calc.rs
index c65102ce..eb0b59dd 100644
--- a/crates/typst/src/foundations/calc.rs
+++ b/crates/typst/src/foundations/calc.rs
@@ -114,11 +114,9 @@ pub fn pow(
};
let result = match (base, exponent.v) {
- (Num::Int(a), Num::Int(b)) if b >= 0 => a
- .checked_pow(b as u32)
- .map(Num::Int)
- .ok_or("the result is too large")
- .at(span)?,
+ (Num::Int(a), Num::Int(b)) if b >= 0 => {
+ a.checked_pow(b as u32).map(Num::Int).ok_or_else(too_large).at(span)?
+ }
(a, b) => Num::Float(if a.float() == std::f64::consts::E {
b.float().exp()
} else if a.float() == 2.0 {
@@ -469,7 +467,7 @@ pub fn fact(
/// The number whose factorial to calculate. Must be non-negative.
number: u64,
) -> StrResult<i64> {
- Ok(fact_impl(1, number).ok_or("the result is too large")?)
+ Ok(fact_impl(1, number).ok_or_else(too_large)?)
}
/// Calculates a permutation.
@@ -493,7 +491,7 @@ pub fn perm(
return Ok(0);
}
- Ok(fact_impl(base - numbers + 1, base).ok_or("the result is too large")?)
+ Ok(fact_impl(base - numbers + 1, base).ok_or_else(too_large)?)
}
/// Calculates the product of a range of numbers. Used to calculate
@@ -528,7 +526,7 @@ pub fn binom(
/// The lower coefficient. Must be non-negative.
k: u64,
) -> StrResult<i64> {
- Ok(binom_impl(n, k).ok_or("the result is too large")?)
+ Ok(binom_impl(n, k).ok_or_else(too_large)?)
}
/// Calculates a binomial coefficient, with `n` the upper coefficient and `k`
@@ -594,7 +592,7 @@ pub fn lcm(
Ok(a.checked_div(gcd(a, b))
.and_then(|gcd| gcd.checked_mul(b))
.map(|v| v.abs())
- .ok_or("the return value is too large")?)
+ .ok_or_else(too_large)?)
}
/// Rounds a number down to the nearest integer.
@@ -974,3 +972,9 @@ cast! {
v: f64 => Self::Float(v),
v: Angle => Self::Angle(v),
}
+
+/// The error message when the result is too large to be represented.
+#[cold]
+fn too_large() -> &'static str {
+ "the result is too large"
+}