fix: closure captures can also be constants (#11493)

<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx

you can also mention related issues, PRs or discussions!
-->

# Description
<!--
Thank you for improving Nushell. Please, check our [contributing
guide](../CONTRIBUTING.md) and talk to the core team before making major
changes.

Description of your pull request goes here. **Provide examples and/or
screenshots** if your changes affect the user experience.
-->
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
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->

# Tests + Formatting
<!--
Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# After Submitting
<!-- If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
-->
This commit is contained in:
Antoine Büsch 2024-01-07 21:51:39 +11:00 committed by GitHub
parent 6f59abaf43
commit 1920ece759
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 25 additions and 1 deletions

View File

@ -1102,7 +1102,18 @@ impl Eval for EvalRuntime {
.get_block(block_id) .get_block(block_id)
.captures .captures
.iter() .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::<Result<_, _>>()?; .collect::<Result<_, _>>()?;
Ok(Value::closure(Closure { block_id, captures }, span)) Ok(Value::closure(Closure { block_id, captures }, span))

View File

@ -304,6 +304,19 @@ fn const_captures_work() {
assert_eq!(actual.out, "xy"); 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`"] #[ignore = "TODO: Need to fix `overlay hide` to hide the constants brough by `overlay use`"]
#[test] #[test]
fn complex_const_overlay_use_hide() { fn complex_const_overlay_use_hide() {