IR: rasing reasonable error when using subexpression with and operator (#15623)

# Description
Fixes: #15510
I think it's introduced by #14653, which changes `and/or` to `match`
expression.

After looking into `compile_match`, it's important to collect the value
before matching this.
```rust
    // Important to collect it first
    builder.push(Instruction::Collect { src_dst: match_reg }.into_spanned(match_expr.span))?;
```
This pr is going to apply the logic while compiling `and/or` operation.

# User-Facing Changes
The following will raise a reasonable error:
```nushell
> (nu --testbin cococo false) and true
Error: nu:🐚:operator_unsupported_type

  × The 'and' operator does not work on values of type 'string'.
   ╭─[entry #7:1:2]
 1 │ (nu --testbin cococo false) and true
   ·  ─┬                         ─┬─
   ·   │                          ╰── does not support 'string'
   ·   ╰── string
   ╰────
```

# Tests + Formatting
Added 1 test.

# After Submitting
Maybe need to update doc
https://github.com/nushell/nushell.github.io/pull/1876

---------

Co-authored-by: Stefan Holderbach <sholderbach@users.noreply.github.com>
This commit is contained in:
Wind 2025-04-25 22:00:20 +08:00 committed by GitHub
parent 0ca5c2f135
commit 11cdb94699
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 10 additions and 0 deletions

View File

@ -70,6 +70,8 @@ pub(crate) fn compile_binary_op(
Boolean::Xor => unreachable!(),
};
// Before match against lhs_reg, it's important to collect it first to get a concrete value if there is a subexpression.
builder.push(Instruction::Collect { src_dst: lhs_reg }.into_spanned(lhs.span))?;
// Short-circuit to return `lhs_reg`. `match` op does not consume `lhs_reg`.
let short_circuit_label = builder.label(None);
builder.r#match(

View File

@ -717,3 +717,11 @@ fn external_error_with_backtrace() {
assert_eq!(chained_error_cnt.len(), 0);
});
}
#[test]
fn sub_external_expression_with_and_op_should_raise_proper_error() {
let actual = nu!("(nu --testbin cococo false) and true");
assert!(actual
.err
.contains("The 'and' operator does not work on values of type 'string'"))
}