diff --git a/crates/typst/src/eval/call.rs b/crates/typst/src/eval/call.rs index 12d024ad6..a143c8ac2 100644 --- a/crates/typst/src/eval/call.rs +++ b/crates/typst/src/eval/call.rs @@ -128,7 +128,7 @@ impl Eval for ast::FuncCall<'_> { (callee.eval(vm)?, args.eval(vm)?.spanned(span)) }; - let func_result = callee.clone().cast::().at(callee_span); + let func_result = callee.clone().cast::(); if in_math && func_result.is_err() { // For non-functions in math, we wrap the arguments in parentheses. let mut body = Content::empty(); @@ -148,7 +148,21 @@ impl Eval for ast::FuncCall<'_> { )); } - let func = func_result?; + let func = func_result + .map_err(|mut err| { + if let ast::Expr::Ident(ident) = self.callee() { + let ident = ident.get(); + if vm.scopes.check_std_shadowed(ident) { + err.hint(eco_format!( + "use `std.{}` to access the shadowed standard library function", + ident, + )); + } + } + err + }) + .at(callee_span)?; + let point = || Tracepoint::Call(func.name().map(Into::into)); let f = || { func.call(&mut vm.engine, vm.context, args) diff --git a/crates/typst/src/foundations/scope.rs b/crates/typst/src/foundations/scope.rs index e0ef7a728..0313df7a9 100644 --- a/crates/typst/src/foundations/scope.rs +++ b/crates/typst/src/foundations/scope.rs @@ -87,6 +87,14 @@ impl<'a> Scopes<'a> { } })? } + + /// Check if an std variable is shadowed. + pub fn check_std_shadowed(&self, var: &str) -> bool { + self.base.is_some_and(|base| base.global.scope().get(var).is_some()) + && std::iter::once(&self.top) + .chain(self.scopes.iter().rev()) + .any(|scope| scope.get(var).is_some()) + } } #[cold] diff --git a/tests/suite/scripting/call.typ b/tests/suite/scripting/call.typ index 34344608a..5a5fb326d 100644 --- a/tests/suite/scripting/call.typ +++ b/tests/suite/scripting/call.typ @@ -49,6 +49,13 @@ // Error: 2-3 expected function, found string #x() +--- call-shadowed-builtin-function --- +#let image = "image" + +// Error: 2-7 expected function, found string +// Hint: 2-7 use `std.image` to access the shadowed standard library function +#image("image") + --- call-bad-type-int-expr --- #let f(x) = x