Empty rest args match should be an empty list (#14246)

Fixes #14145 

# User-Facing Changes
An empty rest match would be `null` previously. Now it will be an empty
list.
This is a breaking change for any scripts relying on the old behavior.

Example script:
```nu
match [1] {
  [_ ..$rest] => {
    match $rest {
      null => { "old" }
      [] => { "new" }
    }
  } 
}
```
This expression would evaluate to "old" on current nu versions and "new"
with this patch.
This commit is contained in:
Charles Taylor 2024-11-04 12:03:26 -05:00 committed by GitHub
parent 22ca5a6b8d
commit 20c2de9eed
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 11 additions and 4 deletions

View file

@ -64,6 +64,12 @@ fn match_list_rest() {
assert_eq!(actual.out, "single: 1 5"); assert_eq!(actual.out, "single: 1 5");
} }
#[test]
fn match_list_rest_empty() {
let actual = nu!(r#"match [1] { [1 ..$rest] => { $rest == [] } }"#);
assert_eq!(actual.out, "true");
}
#[test] #[test]
fn match_constant_1() { fn match_constant_1() {
let actual = nu!( let actual = nu!(

View file

@ -48,13 +48,14 @@ impl Matcher for Pattern {
Pattern::List(items) => match &value { Pattern::List(items) => match &value {
Value::List { vals, .. } => { Value::List { vals, .. } => {
if items.len() > vals.len() { if items.len() > vals.len() {
// The only we we allow this is to have a rest pattern in the n+1 position // We only allow this is to have a rest pattern in the n+1 position
if items.len() == (vals.len() + 1) { if items.len() == (vals.len() + 1) {
match &items[vals.len()].pattern { match &items[vals.len()].pattern {
Pattern::IgnoreRest => {} Pattern::IgnoreRest => {}
Pattern::Rest(var_id) => { Pattern::Rest(var_id) => matches.push((
matches.push((*var_id, Value::nothing(items[vals.len()].span))) *var_id,
} Value::list(Vec::new(), items[vals.len()].span),
)),
_ => { _ => {
// There is a pattern which can't skip missing values, so we fail // There is a pattern which can't skip missing values, so we fail
return false; return false;