Allow string to copmpare with another string (#11590)

# Description

Nushell parser now reject comparison operator with 2 strings (e.g.
`"abc" < "cba"`). This pr fixes it.

## before

```nu
~
❯ "abc" < "bca"
Error: nu::parser::unsupported_operation

  × less-than comparison is not supported on values of type string
   ╭─[entry #43:1:1]
 1 │ "abc" < "bca"
   · ──┬── ┬
   ·   │   ╰── doesn't support this value
   ·   ╰── string
   ╰────


~
❯ def foo []: nothing -> string { "abc" }

~
❯ (foo) < "bca"
Error: nu::parser::unsupported_operation

  × less-than comparison is not supported on values of type string
   ╭─[entry #53:1:1]
 1 │ (foo) < "bca"
   · ──┬── ┬
   ·   │   ╰── doesn't support this value
   ·   ╰── string
   ╰────
```

## after

```nu
~
❯ "abc" < "bca"
true

~
❯ def foo []: nothing -> string { "abc" }

~
❯ (foo) < "bca"
true
```

# User-Facing Changes

Following pattern will be allowed.

| operator | type of lhs | type of rhs | result |
| -------- | ----------- | ----------- | ------ |
| `<`      | string      | string      | bool   |
| `<=`     | string      | string      | bool   |
| `>`      | string      | string      | bool   |
| `>=`     | string      | string      | bool   |

# Tests + Formatting

- [x] `cargo fmt --all -- --check` to check standard code formatting
(`cargo fmt --all` applies these changes)
- [x] `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used`
to check that you're using the standard code style
- [x] `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))
- [x] `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

# After Submitting
This commit is contained in:
tomoda 2024-01-21 22:43:40 +09:00 committed by GitHub
parent bc872a1a2a
commit 6edf91dcae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 28 additions and 0 deletions

View File

@ -429,6 +429,7 @@ pub fn math_result_type(
(Type::Int, Type::Number) => (Type::Bool, None),
(Type::Number, Type::Float) => (Type::Bool, None),
(Type::Float, Type::Number) => (Type::Bool, None),
(Type::String, Type::String) => (Type::Bool, None),
(Type::Duration, Type::Duration) => (Type::Bool, None),
(Type::Date, Type::Date) => (Type::Bool, None),
(Type::Filesize, Type::Filesize) => (Type::Bool, None),
@ -478,6 +479,7 @@ pub fn math_result_type(
(Type::Int, Type::Number) => (Type::Bool, None),
(Type::Number, Type::Float) => (Type::Bool, None),
(Type::Float, Type::Number) => (Type::Bool, None),
(Type::String, Type::String) => (Type::Bool, None),
(Type::Duration, Type::Duration) => (Type::Bool, None),
(Type::Date, Type::Date) => (Type::Bool, None),
(Type::Filesize, Type::Filesize) => (Type::Bool, None),
@ -527,6 +529,7 @@ pub fn math_result_type(
(Type::Int, Type::Number) => (Type::Bool, None),
(Type::Number, Type::Float) => (Type::Bool, None),
(Type::Float, Type::Number) => (Type::Bool, None),
(Type::String, Type::String) => (Type::Bool, None),
(Type::Duration, Type::Duration) => (Type::Bool, None),
(Type::Date, Type::Date) => (Type::Bool, None),
(Type::Filesize, Type::Filesize) => (Type::Bool, None),
@ -576,6 +579,7 @@ pub fn math_result_type(
(Type::Int, Type::Number) => (Type::Bool, None),
(Type::Number, Type::Float) => (Type::Bool, None),
(Type::Float, Type::Number) => (Type::Bool, None),
(Type::String, Type::String) => (Type::Bool, None),
(Type::Duration, Type::Duration) => (Type::Bool, None),
(Type::Date, Type::Date) => (Type::Bool, None),
(Type::Filesize, Type::Filesize) => (Type::Bool, None),

View File

@ -1915,3 +1915,27 @@ mod input_types {
)
}
}
#[cfg(test)]
mod operator {
use super::*;
#[rstest]
#[case(br#""abc" < "bca""#, "string < string")]
#[case(br#""abc" <= "bca""#, "string <= string")]
#[case(br#""abc" > "bca""#, "string > string")]
#[case(br#""abc" >= "bca""#, "string >= string")]
fn parse_comparison_operators_with_string_and_string(
#[case] expr: &[u8],
#[case] test_tag: &str,
) {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
parse(&mut working_set, None, expr, false);
assert_eq!(
working_set.parse_errors.len(),
0,
"{test_tag}: expected to be parsed successfully, but failed."
);
}
}