Use Vec for Closure captures (#10940)

# Description
Changes the `captures` field in `Closure` from a `HashMap` to a `Vec`
and makes `Stack::captures_to_stack` take an owned `Vec` instead of a
borrowed `HashMap`.

This eliminates the conversion to a `Vec` inside `captures_to_stack` and
makes it possible to avoid clones altogether when using an owned
`Closure` (which is the case for most commands). Additionally, using a
`Vec` reduces the size of `Value` by 8 bytes (down to 72).

# User-Facing Changes
Breaking API change for `nu-protocol`.
This commit is contained in:
Ian Manske
2023-11-07 23:43:28 +00:00
committed by GitHub
parent 7a3cbf43e8
commit 60da7abbc7
33 changed files with 46 additions and 59 deletions

View File

@ -1,5 +1,3 @@
use std::collections::HashMap;
use crate::{BlockId, Value, VarId};
use serde::{Deserialize, Serialize};
@ -7,7 +5,7 @@ use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Closure {
pub block_id: BlockId,
pub captures: HashMap<VarId, Value>,
pub captures: Vec<(VarId, Value)>,
}
#[derive(Clone, Debug)]

View File

@ -138,19 +138,13 @@ impl Stack {
})
}
pub fn captures_to_stack(&self, captures: &HashMap<VarId, Value>) -> Stack {
pub fn captures_to_stack(&self, captures: Vec<(VarId, Value)>) -> Stack {
// FIXME: this is probably slow
let mut env_vars = self.env_vars.clone();
env_vars.push(HashMap::new());
// FIXME make this more efficient
let mut vars = vec![];
for (id, val) in captures {
vars.push((*id, val.clone()));
}
Stack {
vars,
vars: captures,
env_vars,
env_hidden: self.env_hidden.clone(),
active_overlays: self.active_overlays.clone(),

View File

@ -1,4 +1,3 @@
use std::collections::HashMap;
use std::path::PathBuf;
use crate::ast::{CellPath, MatchPattern, PathMember};
@ -496,7 +495,7 @@ impl FromValue for Closure {
Value::Closure { val, .. } => Ok(val),
Value::Block { val, .. } => Ok(Closure {
block_id: val,
captures: HashMap::new(),
captures: Vec::new(),
}),
v => Err(ShellError::CantConvert {
to_type: "Closure".into(),