From 20c2de9eed522543a5444c4afef891fbe8dbab9f Mon Sep 17 00:00:00 2001 From: Charles Taylor Date: Mon, 4 Nov 2024 12:03:26 -0500 Subject: [PATCH] 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. --- crates/nu-command/tests/commands/match_.rs | 6 ++++++ crates/nu-protocol/src/engine/pattern_match.rs | 9 +++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/crates/nu-command/tests/commands/match_.rs b/crates/nu-command/tests/commands/match_.rs index b37d4a32e2..23e4450d2b 100644 --- a/crates/nu-command/tests/commands/match_.rs +++ b/crates/nu-command/tests/commands/match_.rs @@ -64,6 +64,12 @@ fn match_list_rest() { 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] fn match_constant_1() { let actual = nu!( diff --git a/crates/nu-protocol/src/engine/pattern_match.rs b/crates/nu-protocol/src/engine/pattern_match.rs index 2a2287ea67..3284527cc6 100644 --- a/crates/nu-protocol/src/engine/pattern_match.rs +++ b/crates/nu-protocol/src/engine/pattern_match.rs @@ -48,13 +48,14 @@ impl Matcher for Pattern { Pattern::List(items) => match &value { Value::List { vals, .. } => { 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) { match &items[vals.len()].pattern { Pattern::IgnoreRest => {} - Pattern::Rest(var_id) => { - matches.push((*var_id, Value::nothing(items[vals.len()].span))) - } + Pattern::Rest(var_id) => matches.push(( + *var_id, + Value::list(Vec::new(), items[vals.len()].span), + )), _ => { // There is a pattern which can't skip missing values, so we fail return false;