IR: fix incorrect capturing of subexpressions (#13467)

# Description


[Discovered](https://discord.com/channels/601130461678272522/614593951969574961/1266503282554179604)
by `@warp` on Discord.

The IR compiler was not properly setting redirect modes for
subexpressions because `FullCellPath` was always being compiled with
capture-out redirection. This is the correct behavior if there is a tail
to the `FullCellPath`, as we need the value in order to try to extract
anything from it (although this is unlikely to work) - however, the
parser also generates `FullCellPath`s with an empty tail quite often,
including for bare subexpressions.

Because of this, the following did not behave as expected:

```nushell
(docker run -it --rm alpine)
```

Capturing the output meant that `docker` didn't have direct access to
the terminal as a TTY.

As this is a minor bug fix, it should be okay to include in the 0.96.1
patch release.

# User-Facing Changes

- Fixes the bug as described when running with IR evaluation enabled.

# Tests + Formatting

I added a test for this, though we're not currently running all tests
with IR on the CI, but it should ensure this behaviour is consistent.
The equivalent minimum repro I could find was:

```nushell
(nu --testbin cococo); null
```

as this should cause the `cococo` message to appear on stdout, and if
Nushell is capturing the output, it would be discarded instead.
This commit is contained in:
Devyn Cairns 2024-07-27 19:38:57 -07:00 committed by GitHub
parent 53fbf62493
commit 5f7afafe51
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 15 additions and 1 deletions

View file

@ -444,7 +444,15 @@ pub(crate) fn compile_expression(
working_set,
builder,
&full_cell_path.head,
RedirectModes::capture_out(expr.span),
// Only capture the output if there is a tail. This was a bit of a headscratcher
// as the parser emits a FullCellPath with no tail for subexpressions in
// general, which shouldn't be captured any differently than they otherwise
// would be.
if !full_cell_path.tail.is_empty() {
RedirectModes::capture_out(expr.span)
} else {
redirect_modes
},
in_reg,
out_reg,
)?;

View file

@ -209,6 +209,12 @@ fn run_glob_if_pass_variable_to_external() {
})
}
#[test]
fn subexpression_does_not_implicitly_capture() {
let actual = nu!("(nu --testbin cococo); null");
assert_eq!(actual.out, "cococo");
}
mod it_evaluation {
use super::nu;
use nu_test_support::fs::Stub::{EmptyFile, FileWithContent, FileWithContentToBeTrimmed};