nushell/crates/nu-parser/src
Yash Thakur d5946a9667
Parse time type checking for range (#13595)
# Description

As part of fixing https://github.com/nushell/nushell/issues/13586, this
PR checks the types of the operands when creating a range. Stuff like
`0..(glob .)` will be rejected at parse time. Additionally, `0..$x` will
be treated as a range and rejected if `x` is not defined, rather than
being treated as a string. A separate PR will need to be made to do
reject streams at runtime, so that stuff like `0..(open /dev/random)`
doesn't hang.

Internally, this PR adds a `ParseError::UnsupportedOperationTernary`
variant, for when you have a range like `1..2..(glob .)`.

# User-Facing Changes

Users will now receive an error if any of the operands in the ranges
they construct have types that aren't compatible with `Type::Number`.

Additionally, if a piece of code looks like a range but some parse error
is encountered while parsing it, that piece of code will still be
treated as a range and the user will be shown the parse error. This
means that a piece of code like `0..$x` will be treated as a range no
matter what. Previously, if `x` weren't the expression would've been
treated as a string `"0..$x"`. I feel like it makes the language less
complicated if we make it less context-sensitive.

Here's an example of the error you get:
```
> 0..(glob .)
Error: nu::parser::unsupported_operation

  × range is not supported between int and any.
   ╭─[entry #1:1:1]
 1 │ 0..(glob .)
   · ─────┬─────┬┬
   ·      │     │╰── any
   ·      │     ╰── int
   ·      ╰── doesn't support these values
   ╰────
```

And as an image:

![image](https://github.com/user-attachments/assets/5c76168d-27db-481b-b541-861dac899dbf)

Note: I made the operands themselves (above, `(glob .)`) be garbage,
rather than the `..` operator itself. This doesn't match the behavior of
the math operators (if you do `1 + "foo"`, `+` gets highlighted red).
This is because with ranges, the range operators aren't `Expression`s
themselves, so they can't be turned into garbage. I felt like here, it
makes more sense to highlight the individual operand anyway.
2024-08-13 15:05:34 +08:00
..
deparse.rs update deps calamine and quick-xml (#11582) 2024-01-19 12:23:51 -06:00
exportable.rs Restructure nu-protocol in more meaningful units (#11917) 2024-03-10 18:45:45 +01:00
flatten.rs Make parsing for unknown args in known externals like normal external calls (#13414) 2024-07-21 01:32:36 -07:00
known_external.rs Internal representation (IR) compiler and evaluator (#13330) 2024-07-10 17:33:59 -07:00
lex.rs Make assignment and const consistent with let/mut (#13385) 2024-07-30 18:55:22 -05:00
lib.rs Add top-level crate documentation/READMEs (#12907) 2024-07-14 10:10:41 +02:00
lite_parser.rs Make assignment and const consistent with let/mut (#13385) 2024-07-30 18:55:22 -05:00
parse_keywords.rs Contentious clippy fixes (#13498) 2024-08-01 11:02:55 +02:00
parse_patterns.rs Internal representation (IR) compiler and evaluator (#13330) 2024-07-10 17:33:59 -07:00
parse_shape_specs.rs Add command_prelude module (#12291) 2024-03-26 21:17:30 +00:00
parser.rs Parse time type checking for range (#13595) 2024-08-13 15:05:34 +08:00
type_check.rs Parse time type checking for range (#13595) 2024-08-13 15:05:34 +08:00