diff --git a/benches/benchmarks.rs b/benches/benchmarks.rs index 9a3f71e20d..d809018926 100644 --- a/benches/benchmarks.rs +++ b/benches/benchmarks.rs @@ -2,8 +2,9 @@ use nu_cli::{eval_source, evaluate_commands}; use nu_parser::parse; use nu_plugin::{Encoder, EncodingType, PluginCallResponse, PluginOutput}; use nu_protocol::{ - engine::EngineState, eval_const::create_nu_constant, PipelineData, Span, Spanned, Value, - NU_VARIABLE_ID, + engine::{EngineState, Stack}, + eval_const::create_nu_constant, + PipelineData, Span, Spanned, Value, NU_VARIABLE_ID, }; use nu_std::load_standard_library; use nu_utils::{get_default_config, get_default_env}; @@ -54,6 +55,61 @@ fn setup_engine() -> EngineState { engine_state } +fn bench_command(bencher: divan::Bencher, scaled_command: String) { + bench_command_with_custom_stack_and_engine( + bencher, + scaled_command, + Stack::new(), + setup_engine(), + ) +} + +fn bench_command_with_custom_stack_and_engine( + bencher: divan::Bencher, + scaled_command: String, + stack: nu_protocol::engine::Stack, + mut engine: EngineState, +) { + load_standard_library(&mut engine).unwrap(); + let commands = Spanned { + span: Span::unknown(), + item: scaled_command, + }; + + bencher + .with_inputs(|| engine.clone()) + .bench_values(|mut engine| { + evaluate_commands( + &commands, + &mut engine, + &mut stack.clone(), + PipelineData::empty(), + None, + ) + .unwrap(); + }) +} + +fn setup_stack_and_engine_from_command(command: &str) -> (Stack, EngineState) { + let mut engine = setup_engine(); + let commands = Spanned { + span: Span::unknown(), + item: command.to_string(), + }; + + let mut stack = Stack::new(); + evaluate_commands( + &commands, + &mut engine, + &mut stack, + PipelineData::empty(), + None, + ) + .unwrap(); + + (stack, engine) +} + // FIXME: All benchmarks live in this 1 file to speed up build times when benchmarking. // When the *_benchmarks functions were in different files, `cargo bench` would build // an executable for every single one - incredibly slowly. Would be nice to figure out @@ -70,31 +126,69 @@ fn load_standard_lib(bencher: divan::Bencher) { } #[divan::bench_group] -mod eval_commands { +mod record { + use super::*; - fn bench_command(bencher: divan::Bencher, scaled_command: String) { - let mut engine = setup_engine(); - load_standard_library(&mut engine).unwrap(); - let commands = Spanned { - span: Span::unknown(), - item: scaled_command, - }; - - bencher - .with_inputs(|| engine.clone()) - .bench_values(|mut engine| { - evaluate_commands( - &commands, - &mut engine, - &mut nu_protocol::engine::Stack::new(), - PipelineData::empty(), - None, - ) - .unwrap(); - }) + fn create_flat_record_string(n: i32) -> String { + let mut s = String::from("let record = {"); + for i in 0..n { + s.push_str(&format!("col_{}: {}", i, i)); + if i < n - 1 { + s.push_str(", "); + } + } + s.push('}'); + s } + fn create_nested_record_string(depth: i32) -> String { + let mut s = String::from("let record = {"); + for _ in 0..depth { + s.push_str("col: {{"); + } + s.push_str("col_final: 0"); + for _ in 0..depth { + s.push('}'); + } + s.push('}'); + s + } + + #[divan::bench(args = [1, 10, 100, 1000])] + fn create(bencher: divan::Bencher, n: i32) { + bench_command(bencher, create_flat_record_string(n)); + } + + #[divan::bench(args = [1, 10, 100, 1000])] + fn flat_access(bencher: divan::Bencher, n: i32) { + let (stack, engine) = setup_stack_and_engine_from_command(&create_flat_record_string(n)); + bench_command_with_custom_stack_and_engine( + bencher, + "$record.col_0 | ignore".to_string(), + stack, + engine, + ); + } + + #[divan::bench(args = [1, 2, 4, 8, 16, 32, 64, 128])] + fn nest_access(bencher: divan::Bencher, depth: i32) { + let (stack, engine) = + setup_stack_and_engine_from_command(&create_nested_record_string(depth)); + let nested_access = ".col".repeat(depth as usize); + bench_command_with_custom_stack_and_engine( + bencher, + format!("$record{} | ignore", nested_access), + stack, + engine, + ); + } +} + +#[divan::bench_group] +mod eval_commands { + use super::*; + #[divan::bench(args = [100, 1_000, 10_000])] fn interleave(bencher: divan::Bencher, n: i32) { bench_command( diff --git a/crates/nu-cli/src/completions/variable_completions.rs b/crates/nu-cli/src/completions/variable_completions.rs index 5f370125c6..4d85e6730f 100644 --- a/crates/nu-cli/src/completions/variable_completions.rs +++ b/crates/nu-cli/src/completions/variable_completions.rs @@ -319,7 +319,7 @@ fn recursive_value(val: Value, sublevels: Vec>) -> Value { let span = val.span(); match val { Value::Record { val, .. } => { - for item in val { + for item in *val { // Check if index matches with sublevel if item.0.as_bytes().to_vec() == next_sublevel { // If matches try to fetch recursively the next diff --git a/crates/nu-cmd-base/src/hook.rs b/crates/nu-cmd-base/src/hook.rs index a608b47285..cdb2bed5f3 100644 --- a/crates/nu-cmd-base/src/hook.rs +++ b/crates/nu-cmd-base/src/hook.rs @@ -17,7 +17,7 @@ pub fn eval_env_change_hook( if let Some(hook) = env_change_hook { match hook { Value::Record { val, .. } => { - for (env_name, hook_value) in &val { + for (env_name, hook_value) in &*val { let before = engine_state .previous_env_vars .get(env_name) diff --git a/crates/nu-cmd-dataframe/src/dataframe/values/nu_dataframe/mod.rs b/crates/nu-cmd-dataframe/src/dataframe/values/nu_dataframe/mod.rs index 4c321fbd8d..503bf1d5e9 100644 --- a/crates/nu-cmd-dataframe/src/dataframe/values/nu_dataframe/mod.rs +++ b/crates/nu-cmd-dataframe/src/dataframe/values/nu_dataframe/mod.rs @@ -164,7 +164,7 @@ impl NuDataFrame { conversion::insert_record(&mut column_values, record, &maybe_schema)? } Value::Record { val: record, .. } => { - conversion::insert_record(&mut column_values, record, &maybe_schema)? + conversion::insert_record(&mut column_values, *record, &maybe_schema)? } _ => { let key = "0".to_string(); diff --git a/crates/nu-cmd-lang/src/core_commands/describe.rs b/crates/nu-cmd-lang/src/core_commands/describe.rs index b8af0c299e..9d2ca44483 100644 --- a/crates/nu-cmd-lang/src/core_commands/describe.rs +++ b/crates/nu-cmd-lang/src/core_commands/describe.rs @@ -319,7 +319,7 @@ fn describe_value( record!( "type" => Value::string("record", head), "lazy" => Value::bool(false, head), - "columns" => Value::record(val, head), + "columns" => Value::record(*val, head), ), head, ) @@ -410,7 +410,7 @@ fn describe_value( )?); } - record.push("columns", Value::record(val, head)); + record.push("columns", Value::record(*val, head)); } else { let cols = val.column_names(); record.push("length", Value::int(cols.len() as i64, head)); diff --git a/crates/nu-cmd-lang/src/example_support.rs b/crates/nu-cmd-lang/src/example_support.rs index 8a654cab23..8e848c20de 100644 --- a/crates/nu-cmd-lang/src/example_support.rs +++ b/crates/nu-cmd-lang/src/example_support.rs @@ -238,7 +238,7 @@ impl<'a> std::fmt::Debug for DebuggableValue<'a> { Value::Record { val, .. } => { write!(f, "{{")?; let mut first = true; - for (col, value) in val.into_iter() { + for (col, value) in (&**val).into_iter() { if !first { write!(f, ", ")?; } diff --git a/crates/nu-command/src/charting/histogram.rs b/crates/nu-command/src/charting/histogram.rs index a6b2b45e06..b39e75887c 100755 --- a/crates/nu-command/src/charting/histogram.rs +++ b/crates/nu-command/src/charting/histogram.rs @@ -182,7 +182,7 @@ fn run_histogram( match v { // parse record, and fill valid value to actual input. Value::Record { val, .. } => { - for (c, v) in val { + for (c, v) in *val { if &c == col_name { if let Ok(v) = HashableValue::from_value(v, head_span) { inputs.push(v); diff --git a/crates/nu-command/src/conversions/into/record.rs b/crates/nu-command/src/conversions/into/record.rs index 06aac86d9d..1405ceb3a7 100644 --- a/crates/nu-command/src/conversions/into/record.rs +++ b/crates/nu-command/src/conversions/into/record.rs @@ -135,7 +135,7 @@ fn into_record( .collect(), span, ), - Value::Record { val, .. } => Value::record(val, span), + Value::Record { val, .. } => Value::record(*val, span), Value::Error { .. } => input, other => Value::error( ShellError::TypeMismatch { diff --git a/crates/nu-command/src/env/load_env.rs b/crates/nu-command/src/env/load_env.rs index 59214c18df..5c65081b12 100644 --- a/crates/nu-command/src/env/load_env.rs +++ b/crates/nu-command/src/env/load_env.rs @@ -58,7 +58,7 @@ impl Command for LoadEnv { } None => match input { PipelineData::Value(Value::Record { val, .. }, ..) => { - for (env_var, rhs) in val { + for (env_var, rhs) in *val { let env_var_ = env_var.as_str(); if ["FILE_PWD", "CURRENT_FILE"].contains(&env_var_) { return Err(ShellError::AutomaticEnvVarSetManually { diff --git a/crates/nu-command/src/env/with_env.rs b/crates/nu-command/src/env/with_env.rs index 698f2ad215..39abd55db3 100644 --- a/crates/nu-command/src/env/with_env.rs +++ b/crates/nu-command/src/env/with_env.rs @@ -95,7 +95,7 @@ fn with_env( // single row([[X W]; [Y Z]]) match &table[0] { Value::Record { val, .. } => { - for (k, v) in val { + for (k, v) in &**val { env.insert(k.to_string(), v.clone()); } } @@ -123,7 +123,7 @@ fn with_env( } // when get object by `open x.json` or `from json` Value::Record { val, .. } => { - for (k, v) in val { + for (k, v) in &**val { env.insert(k.clone(), v.clone()); } } diff --git a/crates/nu-command/src/filters/default.rs b/crates/nu-command/src/filters/default.rs index 7f212ba2a0..74aac2318f 100644 --- a/crates/nu-command/src/filters/default.rs +++ b/crates/nu-command/src/filters/default.rs @@ -112,7 +112,7 @@ fn default( record.push(column.item.clone(), value.clone()); } - Value::record(record, span) + Value::record(*record, span) } _ => item, } diff --git a/crates/nu-command/src/filters/drop/column.rs b/crates/nu-command/src/filters/drop/column.rs index 8d98bfbe4d..cf7e9d0350 100644 --- a/crates/nu-command/src/filters/drop/column.rs +++ b/crates/nu-command/src/filters/drop/column.rs @@ -129,7 +129,7 @@ fn drop_cols( } => { let len = record.len().saturating_sub(columns); record.truncate(len); - Ok(Value::record(record, span).into_pipeline_data_with_metadata(metadata)) + Ok(Value::record(*record, span).into_pipeline_data_with_metadata(metadata)) } // Propagate errors Value::Error { error, .. } => Err(*error), diff --git a/crates/nu-command/src/filters/flatten.rs b/crates/nu-command/src/filters/flatten.rs index 372f60d6e0..836df34547 100644 --- a/crates/nu-command/src/filters/flatten.rs +++ b/crates/nu-command/src/filters/flatten.rs @@ -170,7 +170,7 @@ fn flat_value(columns: &[CellPath], item: Value, all: bool) -> Vec { match value { Value::Record { val, .. } => { if need_flatten { - for (col, val) in val { + for (col, val) in *val { if out.contains_key(&col) { out.insert(format!("{column}_{col}"), val); } else { @@ -178,9 +178,9 @@ fn flat_value(columns: &[CellPath], item: Value, all: bool) -> Vec { } } } else if out.contains_key(&column) { - out.insert(format!("{column}_{column}"), Value::record(val, span)); + out.insert(format!("{column}_{column}"), Value::record(*val, span)); } else { - out.insert(column, Value::record(val, span)); + out.insert(column, Value::record(*val, span)); } } Value::List { vals, .. } => { diff --git a/crates/nu-command/src/filters/rename.rs b/crates/nu-command/src/filters/rename.rs index 2cf8cf8111..7b597f7e59 100644 --- a/crates/nu-command/src/filters/rename.rs +++ b/crates/nu-command/src/filters/rename.rs @@ -228,7 +228,7 @@ fn rename( } } - Value::record(record, span) + Value::record(*record, span) } // Propagate errors by explicitly matching them before the final case. Value::Error { .. } => item.clone(), diff --git a/crates/nu-command/src/filters/sort.rs b/crates/nu-command/src/filters/sort.rs index ebdc12aeb0..b0ca9e7f88 100644 --- a/crates/nu-command/src/filters/sort.rs +++ b/crates/nu-command/src/filters/sort.rs @@ -149,7 +149,7 @@ impl Command for Sort { // Records have two sorting methods, toggled by presence or absence of -v PipelineData::Value(Value::Record { val, .. }, ..) => { let sort_by_value = call.has_flag(engine_state, stack, "values")?; - let record = sort_record(val, span, sort_by_value, reverse, insensitive, natural); + let record = sort_record(*val, span, sort_by_value, reverse, insensitive, natural); Ok(record.into_pipeline_data()) } // Other values are sorted here diff --git a/crates/nu-command/src/filters/values.rs b/crates/nu-command/src/filters/values.rs index 1a2c847fa0..5585dc0e59 100644 --- a/crates/nu-command/src/filters/values.rs +++ b/crates/nu-command/src/filters/values.rs @@ -111,7 +111,7 @@ pub fn get_values<'a>( for item in input { match item { Value::Record { val, .. } => { - for (k, v) in val { + for (k, v) in &**val { if let Some(vec) = output.get_mut(k) { vec.push(v.clone()); } else { diff --git a/crates/nu-command/src/formats/from/xml.rs b/crates/nu-command/src/formats/from/xml.rs index a168aeb652..433d2d3231 100644 --- a/crates/nu-command/src/formats/from/xml.rs +++ b/crates/nu-command/src/formats/from/xml.rs @@ -417,7 +417,7 @@ mod tests { content_tag( "nu", indexmap! {}, - &vec![ + &[ content_tag("dev", indexmap! {}, &[content_string("Andrés")]), content_tag("dev", indexmap! {}, &[content_string("JT")]), content_tag("dev", indexmap! {}, &[content_string("Yehuda")]) diff --git a/crates/nu-command/src/formats/to/json.rs b/crates/nu-command/src/formats/to/json.rs index 0934750d89..08764d296a 100644 --- a/crates/nu-command/src/formats/to/json.rs +++ b/crates/nu-command/src/formats/to/json.rs @@ -135,7 +135,7 @@ pub fn value_to_json_value(v: &Value) -> Result { } Value::Record { val, .. } => { let mut m = nu_json::Map::new(); - for (k, v) in val { + for (k, v) in &**val { m.insert(k.clone(), value_to_json_value(v)?); } nu_json::Value::Object(m) diff --git a/crates/nu-command/src/formats/to/nuon.rs b/crates/nu-command/src/formats/to/nuon.rs index 2843c50e3a..783e747ca5 100644 --- a/crates/nu-command/src/formats/to/nuon.rs +++ b/crates/nu-command/src/formats/to/nuon.rs @@ -252,7 +252,7 @@ pub fn value_to_string( )), Value::Record { val, .. } => { let mut collection = vec![]; - for (col, val) in val { + for (col, val) in &**val { collection.push(if needs_quotes(col) { format!( "{idt_po}\"{}\": {}", diff --git a/crates/nu-command/src/formats/to/toml.rs b/crates/nu-command/src/formats/to/toml.rs index 27c7a57248..d3ec8c8004 100644 --- a/crates/nu-command/src/formats/to/toml.rs +++ b/crates/nu-command/src/formats/to/toml.rs @@ -60,7 +60,7 @@ fn helper(engine_state: &EngineState, v: &Value) -> Result toml::Value::String(val.clone()), Value::Record { val, .. } => { let mut m = toml::map::Map::new(); - for (k, v) in val { + for (k, v) in &**val { m.insert(k.clone(), helper(engine_state, v)?); } toml::Value::Table(m) diff --git a/crates/nu-command/src/formats/to/xml.rs b/crates/nu-command/src/formats/to/xml.rs index f455f2e4f3..1d4e0bf702 100644 --- a/crates/nu-command/src/formats/to/xml.rs +++ b/crates/nu-command/src/formats/to/xml.rs @@ -331,7 +331,7 @@ impl Job { // content: null}, {tag: a}. See to_xml_entry for more let attrs = match attrs { Value::Record { val, .. } => val, - Value::Nothing { .. } => Record::new(), + Value::Nothing { .. } => Box::new(Record::new()), _ => { return Err(ShellError::CantConvert { to_type: "XML".into(), @@ -355,7 +355,7 @@ impl Job { } }; - self.write_tag(entry_span, tag, tag_span, attrs, content) + self.write_tag(entry_span, tag, tag_span, *attrs, content) } } diff --git a/crates/nu-command/src/formats/to/yaml.rs b/crates/nu-command/src/formats/to/yaml.rs index eb3335b59f..9960c5b34f 100644 --- a/crates/nu-command/src/formats/to/yaml.rs +++ b/crates/nu-command/src/formats/to/yaml.rs @@ -57,7 +57,7 @@ pub fn value_to_yaml_value(v: &Value) -> Result { } Value::Record { val, .. } => { let mut m = serde_yaml::Mapping::new(); - for (k, v) in val { + for (k, v) in &**val { m.insert( serde_yaml::Value::String(k.clone()), value_to_yaml_value(v)?, diff --git a/crates/nu-command/src/help/help_.rs b/crates/nu-command/src/help/help_.rs index ea0c0a1cc8..b76f332e1a 100644 --- a/crates/nu-command/src/help/help_.rs +++ b/crates/nu-command/src/help/help_.rs @@ -186,7 +186,7 @@ pub fn highlight_search_in_table( )?; if has_match { - matches.push(Value::record(record, record_span)); + matches.push(Value::record(*record, record_span)); } } diff --git a/crates/nu-command/src/math/utils.rs b/crates/nu-command/src/math/utils.rs index d10e88d22e..b6b20b2578 100644 --- a/crates/nu-command/src/math/utils.rs +++ b/crates/nu-command/src/math/utils.rs @@ -29,7 +29,7 @@ fn helper_for_tables( for val in values { match val { Value::Record { val, .. } => { - for (key, value) in val { + for (key, value) in &**val { column_values .entry(key.clone()) .and_modify(|v: &mut Vec| v.push(value.clone())) @@ -90,7 +90,7 @@ pub fn calculate( *val = mf(slice::from_ref(val), span, name)?; Ok(()) })?; - Ok(Value::record(record, span)) + Ok(Value::record(*record, span)) } PipelineData::Value(Value::Range { val, .. }, ..) => { let new_vals: Result, ShellError> = val diff --git a/crates/nu-command/src/network/http/client.rs b/crates/nu-command/src/network/http/client.rs index 0ac20ac41d..caa72edb5e 100644 --- a/crates/nu-command/src/network/http/client.rs +++ b/crates/nu-command/src/network/http/client.rs @@ -221,7 +221,7 @@ pub fn send_request( Value::Record { val, .. } if body_type == BodyType::Form => { let mut data: Vec<(String, String)> = Vec::with_capacity(val.len()); - for (col, val) in val { + for (col, val) in *val { data.push((col, val.coerce_into_string()?)) } @@ -335,7 +335,7 @@ pub fn request_add_custom_headers( match &headers { Value::Record { val, .. } => { - for (k, v) in val { + for (k, v) in &**val { custom_headers.insert(k.to_string(), v.clone()); } } @@ -345,7 +345,7 @@ pub fn request_add_custom_headers( // single row([key1 key2]; [val1 val2]) match &table[0] { Value::Record { val, .. } => { - for (k, v) in val { + for (k, v) in &**val { custom_headers.insert(k.to_string(), v.clone()); } } diff --git a/crates/nu-command/src/network/url/build_query.rs b/crates/nu-command/src/network/url/build_query.rs index cec4c49fe7..556b161a8d 100644 --- a/crates/nu-command/src/network/url/build_query.rs +++ b/crates/nu-command/src/network/url/build_query.rs @@ -69,7 +69,7 @@ fn to_url(input: PipelineData, head: Span) -> Result { match value { Value::Record { ref val, .. } => { let mut row_vec = vec![]; - for (k, v) in val { + for (k, v) in &**val { match v.coerce_string() { Ok(s) => { row_vec.push((k.clone(), s)); diff --git a/crates/nu-command/src/viewers/table.rs b/crates/nu-command/src/viewers/table.rs index 2f45f841ce..90ed150f26 100644 --- a/crates/nu-command/src/viewers/table.rs +++ b/crates/nu-command/src/viewers/table.rs @@ -413,7 +413,7 @@ fn handle_table_command( } PipelineData::Value(Value::Record { val, .. }, ..) => { input.data = PipelineData::Empty; - handle_record(input, cfg, val) + handle_record(input, cfg, *val) } PipelineData::Value(Value::LazyRecord { val, .. }, ..) => { input.data = val.collect()?.into_pipeline_data(); diff --git a/crates/nu-engine/src/documentation.rs b/crates/nu-engine/src/documentation.rs index b3dfbaefba..d0109b026b 100644 --- a/crates/nu-engine/src/documentation.rs +++ b/crates/nu-engine/src/documentation.rs @@ -378,8 +378,8 @@ fn get_argument_for_color_value( ) -> Option { match color { Value::Record { val, .. } => { - let record_exp: Vec = val - .into_iter() + let record_exp: Vec = (**val) + .iter() .map(|(k, v)| { RecordItem::Pair( Expression { diff --git a/crates/nu-explore/src/nu_common/table.rs b/crates/nu-explore/src/nu_common/table.rs index 9e9695ea87..b49ed7eb92 100644 --- a/crates/nu-explore/src/nu_common/table.rs +++ b/crates/nu-explore/src/nu_common/table.rs @@ -18,7 +18,7 @@ pub fn try_build_table( let span = value.span(); match value { Value::List { vals, .. } => try_build_list(vals, ctrlc, config, span, style_computer), - Value::Record { val, .. } => try_build_map(val, span, style_computer, ctrlc, config), + Value::Record { val, .. } => try_build_map(*val, span, style_computer, ctrlc, config), val if matches!(val, Value::String { .. }) => { nu_value_to_string_clean(&val, config, style_computer).0 } diff --git a/crates/nu-protocol/src/config/hooks.rs b/crates/nu-protocol/src/config/hooks.rs index 3d28691ca5..4bef3e5e6d 100644 --- a/crates/nu-protocol/src/config/hooks.rs +++ b/crates/nu-protocol/src/config/hooks.rs @@ -38,7 +38,7 @@ pub(super) fn create_hooks(value: &Value) -> Result { Value::Record { val, .. } => { let mut hooks = Hooks::new(); - for (col, val) in val { + for (col, val) in &**val { match col.as_str() { "pre_prompt" => hooks.pre_prompt = Some(val.clone()), "pre_execution" => hooks.pre_execution = Some(val.clone()), diff --git a/crates/nu-protocol/src/engine/pattern_match.rs b/crates/nu-protocol/src/engine/pattern_match.rs index 8c1266c1b5..e29779b633 100644 --- a/crates/nu-protocol/src/engine/pattern_match.rs +++ b/crates/nu-protocol/src/engine/pattern_match.rs @@ -23,7 +23,7 @@ impl Matcher for Pattern { Pattern::Record(field_patterns) => match value { Value::Record { val, .. } => { 'top: for field_pattern in field_patterns { - for (col, val) in val { + for (col, val) in &**val { if col == &field_pattern.0 { // We have found the field let result = field_pattern.1.match_value(val, matches); diff --git a/crates/nu-protocol/src/eval_base.rs b/crates/nu-protocol/src/eval_base.rs index 84ca009673..6650c7f6bf 100644 --- a/crates/nu-protocol/src/eval_base.rs +++ b/crates/nu-protocol/src/eval_base.rs @@ -76,7 +76,7 @@ pub trait Eval { RecordItem::Spread(_, inner) => { match Self::eval::(state, mut_state, inner)? { Value::Record { val: inner_val, .. } => { - for (col_name, val) in inner_val { + for (col_name, val) in *inner_val { if let Some(orig_span) = col_names.get(&col_name) { return Err(ShellError::ColumnDefinedTwice { col_name, diff --git a/crates/nu-protocol/src/value/from_value.rs b/crates/nu-protocol/src/value/from_value.rs index edac037650..79df03d808 100644 --- a/crates/nu-protocol/src/value/from_value.rs +++ b/crates/nu-protocol/src/value/from_value.rs @@ -538,7 +538,7 @@ impl FromValue for Vec { impl FromValue for Record { fn from_value(v: Value) -> Result { match v { - Value::Record { val, .. } => Ok(val), + Value::Record { val, .. } => Ok(*val), v => Err(ShellError::CantConvert { to_type: "Record".into(), from_type: v.get_type().to_string(), diff --git a/crates/nu-protocol/src/value/mod.rs b/crates/nu-protocol/src/value/mod.rs index 7e00d51e43..e60aa5506e 100644 --- a/crates/nu-protocol/src/value/mod.rs +++ b/crates/nu-protocol/src/value/mod.rs @@ -106,7 +106,7 @@ pub enum Value { internal_span: Span, }, Record { - val: Record, + val: Box, // note: spans are being refactored out of Value // please use .span() instead of matching this span value #[serde(rename = "span")] @@ -534,7 +534,7 @@ impl Value { /// Unwraps the inner [`Record`] value or returns an error if this `Value` is not a record pub fn into_record(self) -> Result { if let Value::Record { val, .. } = self { - Ok(val) + Ok(*val) } else { self.cant_convert_to("record") } @@ -1994,7 +1994,7 @@ impl Value { pub fn record(val: Record, span: Span) -> Value { Value::Record { - val, + val: Box::new(val), internal_span: span, } } diff --git a/crates/nu-table/src/types/collapse.rs b/crates/nu-table/src/types/collapse.rs index 2872085236..f8e34c79a4 100644 --- a/crates/nu-table/src/types/collapse.rs +++ b/crates/nu-table/src/types/collapse.rs @@ -52,17 +52,19 @@ fn colorize_value(value: &mut Value, config: &Config, style_computer: &StyleComp // Take ownership of the record and reassign to &mut // We do this to have owned keys through `.into_iter` let record = std::mem::take(val); - *val = record - .into_iter() - .map(|(mut header, mut val)| { - colorize_value(&mut val, config, style_computer); + *val = Box::new( + record + .into_iter() + .map(|(mut header, mut val)| { + colorize_value(&mut val, config, style_computer); - if let Some(color) = style.color_style { - header = color.paint(header).to_string(); - } - (header, val) - }) - .collect::(); + if let Some(color) = style.color_style { + header = color.paint(header).to_string(); + } + (header, val) + }) + .collect::(), + ); } Value::List { vals, .. } => { for val in vals { diff --git a/crates/nu-table/src/unstructured_table.rs b/crates/nu-table/src/unstructured_table.rs index 1330508fb6..9f56cf0f9a 100644 --- a/crates/nu-table/src/unstructured_table.rs +++ b/crates/nu-table/src/unstructured_table.rs @@ -90,7 +90,7 @@ fn build_table( fn convert_nu_value_to_table_value(value: Value, config: &Config) -> TableValue { match value { - Value::Record { val, .. } => build_vertical_map(val, config), + Value::Record { val, .. } => build_vertical_map(*val, config), Value::List { vals, .. } => { let rebuild_array_as_map = is_valid_record(&vals) && count_columns_in_record(&vals) > 0; if rebuild_array_as_map {