From 1920ece759310ee78e0b1c1c447b8f27adce57b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoine=20B=C3=BCsch?= Date: Sun, 7 Jan 2024 21:51:39 +1100 Subject: [PATCH] fix: closure captures can also be constants (#11493) # Description When evaluating a closure (in `EvalRuntime::eval_row_condition_or_closure()`), we try to resolve the closure's block's captures, but we only check if they're variables on the stack. We need to also check if they are constants (see the logic in `Stack::gather_captures()`). fixes #10701 # User-Facing Changes # Tests + Formatting # After Submitting --- crates/nu-engine/src/eval.rs | 13 ++++++++++++- tests/const_/mod.rs | 13 +++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/crates/nu-engine/src/eval.rs b/crates/nu-engine/src/eval.rs index 550eee6e1a..adfc2a795a 100644 --- a/crates/nu-engine/src/eval.rs +++ b/crates/nu-engine/src/eval.rs @@ -1102,7 +1102,18 @@ impl Eval for EvalRuntime { .get_block(block_id) .captures .iter() - .map(|&id| stack.get_var(id, span).map(|var| (id, var))) + .map(|&id| { + stack + .get_var(id, span) + .or_else(|_| { + engine_state + .get_var(id) + .const_val + .clone() + .ok_or(ShellError::VariableNotFoundAtRuntime { span }) + }) + .map(|var| (id, var)) + }) .collect::>()?; Ok(Value::closure(Closure { block_id, captures }, span)) diff --git a/tests/const_/mod.rs b/tests/const_/mod.rs index 9ef7667bc0..a76c19efdc 100644 --- a/tests/const_/mod.rs +++ b/tests/const_/mod.rs @@ -304,6 +304,19 @@ fn const_captures_work() { assert_eq!(actual.out, "xy"); } +#[test] +fn const_captures_in_closures_work() { + let module = "module foo { + const a = 'world' + export def bar [] { + 'hello ' + $a + } + }"; + let inp = &[module, "use foo", "do { foo bar }"]; + let actual = nu!(&inp.join("; ")); + assert_eq!(actual.out, "hello world"); +} + #[ignore = "TODO: Need to fix `overlay hide` to hide the constants brough by `overlay use`"] #[test] fn complex_const_overlay_use_hide() {