Replace raw usize IDs with new types (#13832)

# Description

In this PR I replaced most of the raw usize IDs with
[newtypes](https://doc.rust-lang.org/rust-by-example/generics/new_types.html).
Some other IDs already started using new types and in this PR I did not
want to touch them. To make the implementation less repetitive, I made
use of a generic `Id<T>` with marker structs. If this lands I would try
to move make other IDs also in this pattern.

Also at some places I needed to use `cast`, I'm not sure if the type was
incorrect and therefore casting not needed or if actually different ID
types intermingle sometimes.

# User-Facing Changes

Probably few, if you got a `DeclId` via a function and placed it later
again it will still work.
This commit is contained in:
Piepmatz
2024-09-30 13:20:15 +02:00
committed by GitHub
parent fc61416c79
commit f0c83a4459
36 changed files with 317 additions and 185 deletions

View File

@ -96,7 +96,7 @@ pub struct Call {
impl Call {
pub fn new(head: Span) -> Call {
Self {
decl_id: 0,
decl_id: DeclId::new(0),
head,
arguments: vec![],
parser_info: HashMap::new(),

View File

@ -6,7 +6,7 @@ use super::{
Range, Table, ValueWithUnit,
};
use crate::{
ast::ImportPattern, engine::StateWorkingSet, BlockId, OutDest, Signature, Span, VarId,
ast::ImportPattern, engine::StateWorkingSet, BlockId, ModuleId, OutDest, Signature, Span, VarId,
};
/// An [`Expression`] AST node
@ -47,7 +47,7 @@ pub enum Expr {
CellPath(CellPath),
FullCellPath(Box<FullCellPath>),
ImportPattern(Box<ImportPattern>),
Overlay(Option<BlockId>), // block ID of the overlay's origin module
Overlay(Option<ModuleId>),
Signature(Box<Signature>),
StringInterpolation(Vec<Expression>),
/// The boolean is `true` if the string is quoted.

View File

@ -31,7 +31,7 @@ impl Call<'_> {
// anyway.
Call {
head: span,
decl_id: 0,
decl_id: DeclId::new(0),
inner: CallImpl::AstBox(Box::new(ast::Call::new(span))),
}
}

View File

@ -93,7 +93,7 @@ pub struct EngineState {
pub config: Arc<Config>,
pub pipeline_externals_state: Arc<(AtomicU32, AtomicU32)>,
pub repl_state: Arc<Mutex<ReplState>>,
pub table_decl_id: Option<usize>,
pub table_decl_id: Option<DeclId>,
#[cfg(feature = "plugin")]
pub plugin_path: Option<PathBuf>,
#[cfg(feature = "plugin")]
@ -114,9 +114,9 @@ pub struct EngineState {
// The max number of compiled regexes to keep around in a LRU cache, arbitrarily chosen
const REGEX_CACHE_SIZE: usize = 100; // must be nonzero, otherwise will panic
pub const NU_VARIABLE_ID: usize = 0;
pub const IN_VARIABLE_ID: usize = 1;
pub const ENV_VARIABLE_ID: usize = 2;
pub const NU_VARIABLE_ID: VarId = VarId::new(0);
pub const IN_VARIABLE_ID: VarId = VarId::new(1);
pub const ENV_VARIABLE_ID: VarId = VarId::new(2);
// NOTE: If you add more to this list, make sure to update the > checks based on the last in the list
// The first span is unknown span
@ -144,7 +144,7 @@ impl EngineState {
// make sure we have some default overlay:
scope: ScopeFrame::with_empty_overlay(
DEFAULT_OVERLAY_NAME.as_bytes().to_vec(),
0,
ModuleId::new(0),
false,
),
signal_handlers: None,
@ -380,7 +380,7 @@ impl EngineState {
let other_names = other.active_overlays.iter().map(|other_id| {
&other
.overlays
.get(*other_id)
.get(other_id.get())
.expect("internal error: missing overlay")
.0
});
@ -410,7 +410,7 @@ impl EngineState {
&self
.scope
.overlays
.get(overlay_id)
.get(overlay_id.get())
.expect("internal error: missing overlay")
.0
}
@ -419,7 +419,7 @@ impl EngineState {
&self
.scope
.overlays
.get(overlay_id)
.get(overlay_id.get())
.expect("internal error: missing overlay")
.1
}
@ -763,7 +763,7 @@ impl EngineState {
pub fn get_var(&self, var_id: VarId) -> &Variable {
self.vars
.get(var_id)
.get(var_id.get())
.expect("internal error: missing variable")
}
@ -773,12 +773,12 @@ impl EngineState {
}
pub fn generate_nu_constant(&mut self) {
self.vars[NU_VARIABLE_ID].const_val = Some(create_nu_constant(self, Span::unknown()));
self.vars[NU_VARIABLE_ID.get()].const_val = Some(create_nu_constant(self, Span::unknown()));
}
pub fn get_decl(&self, decl_id: DeclId) -> &dyn Command {
self.decls
.get(decl_id)
.get(decl_id.get())
.expect("internal error: missing declaration")
.as_ref()
}
@ -810,7 +810,7 @@ impl EngineState {
pub fn get_signature(&self, decl: &dyn Command) -> Signature {
if let Some(block_id) = decl.block_id() {
*self.blocks[block_id].signature.clone()
*self.blocks[block_id.get()].signature.clone()
} else {
decl.signature()
}
@ -830,7 +830,7 @@ impl EngineState {
pub fn get_block(&self, block_id: BlockId) -> &Arc<Block> {
self.blocks
.get(block_id)
.get(block_id.get())
.expect("internal error: missing block")
}
@ -840,18 +840,18 @@ impl EngineState {
/// are normally a compiler error. This only exists to stop plugins from crashing the engine if
/// they send us something invalid.
pub fn try_get_block(&self, block_id: BlockId) -> Option<&Arc<Block>> {
self.blocks.get(block_id)
self.blocks.get(block_id.get())
}
pub fn get_module(&self, module_id: ModuleId) -> &Module {
self.modules
.get(module_id)
.get(module_id.get())
.expect("internal error: missing module")
}
pub fn get_virtual_path(&self, virtual_path_id: VirtualPathId) -> &(String, VirtualPath) {
self.virtual_paths
.get(virtual_path_id)
.get(virtual_path_id.get())
.expect("internal error: missing virtual path")
}
@ -879,7 +879,7 @@ impl EngineState {
covered_span,
});
self.num_files() - 1
FileId::new(self.num_files() - 1)
}
pub fn set_config_path(&mut self, key: &str, val: PathBuf) {
@ -1065,7 +1065,7 @@ mod engine_state_tests {
let mut engine_state = StateWorkingSet::new(&engine_state);
let id = engine_state.add_file("test.nu".into(), &[]);
assert_eq!(id, 0);
assert_eq!(id, FileId::new(0));
}
#[test]
@ -1076,8 +1076,8 @@ mod engine_state_tests {
let mut working_set = StateWorkingSet::new(&engine_state);
let working_set_id = working_set.add_file("child.nu".into(), &[]);
assert_eq!(parent_id, 0);
assert_eq!(working_set_id, 1);
assert_eq!(parent_id, FileId::new(0));
assert_eq!(working_set_id, FileId::new(1));
}
#[test]

View File

@ -76,7 +76,7 @@ impl ScopeFrame {
pub fn with_empty_overlay(name: Vec<u8>, origin: ModuleId, prefixed: bool) -> Self {
Self {
overlays: vec![(name, OverlayFrame::from_origin(origin, prefixed))],
active_overlays: vec![0],
active_overlays: vec![OverlayId::new(0)],
removed_overlays: vec![],
predecls: HashMap::new(),
}
@ -86,7 +86,7 @@ impl ScopeFrame {
for overlay_id in self.active_overlays.iter().rev() {
if let Some(var_id) = self
.overlays
.get(*overlay_id)
.get(overlay_id.get())
.expect("internal error: missing overlay")
.1
.vars
@ -139,7 +139,7 @@ impl ScopeFrame {
pub fn get_overlay_name(&self, overlay_id: OverlayId) -> &[u8] {
&self
.overlays
.get(overlay_id)
.get(overlay_id.get())
.expect("internal error: missing overlay")
.0
}
@ -147,7 +147,7 @@ impl ScopeFrame {
pub fn get_overlay(&self, overlay_id: OverlayId) -> &OverlayFrame {
&self
.overlays
.get(overlay_id)
.get(overlay_id.get())
.expect("internal error: missing overlay")
.1
}
@ -155,19 +155,23 @@ impl ScopeFrame {
pub fn get_overlay_mut(&mut self, overlay_id: OverlayId) -> &mut OverlayFrame {
&mut self
.overlays
.get_mut(overlay_id)
.get_mut(overlay_id.get())
.expect("internal error: missing overlay")
.1
}
pub fn find_overlay(&self, name: &[u8]) -> Option<OverlayId> {
self.overlays.iter().position(|(n, _)| n == name)
self.overlays
.iter()
.position(|(n, _)| n == name)
.map(OverlayId::new)
}
pub fn find_active_overlay(&self, name: &[u8]) -> Option<OverlayId> {
self.overlays
.iter()
.position(|(n, _)| n == name)
.map(OverlayId::new)
.filter(|id| self.active_overlays.contains(id))
}
}

View File

@ -734,7 +734,7 @@ impl Stack {
mod test {
use std::sync::Arc;
use crate::{engine::EngineState, Span, Value};
use crate::{engine::EngineState, Span, Value, VarId};
use super::Stack;
@ -749,22 +749,25 @@ mod test {
#[test]
fn test_children_see_inner_values() {
let mut original = Stack::new();
original.add_var(0, string_value("hello"));
original.add_var(VarId::new(0), string_value("hello"));
let cloned = Stack::with_parent(Arc::new(original));
assert_eq!(cloned.get_var(0, ZERO_SPAN), Ok(string_value("hello")));
assert_eq!(
cloned.get_var(VarId::new(0), ZERO_SPAN),
Ok(string_value("hello"))
);
}
#[test]
fn test_children_dont_see_deleted_values() {
let mut original = Stack::new();
original.add_var(0, string_value("hello"));
original.add_var(VarId::new(0), string_value("hello"));
let mut cloned = Stack::with_parent(Arc::new(original));
cloned.remove_var(0);
cloned.remove_var(VarId::new(0));
assert_eq!(
cloned.get_var(0, ZERO_SPAN),
cloned.get_var(VarId::new(0), ZERO_SPAN),
Err(crate::ShellError::VariableNotFoundAtRuntime { span: ZERO_SPAN })
);
}
@ -772,60 +775,69 @@ mod test {
#[test]
fn test_children_changes_override_parent() {
let mut original = Stack::new();
original.add_var(0, string_value("hello"));
original.add_var(VarId::new(0), string_value("hello"));
let mut cloned = Stack::with_parent(Arc::new(original));
cloned.add_var(0, string_value("there"));
assert_eq!(cloned.get_var(0, ZERO_SPAN), Ok(string_value("there")));
cloned.add_var(VarId::new(0), string_value("there"));
assert_eq!(
cloned.get_var(VarId::new(0), ZERO_SPAN),
Ok(string_value("there"))
);
cloned.remove_var(0);
cloned.remove_var(VarId::new(0));
// the underlying value shouldn't magically re-appear
assert_eq!(
cloned.get_var(0, ZERO_SPAN),
cloned.get_var(VarId::new(0), ZERO_SPAN),
Err(crate::ShellError::VariableNotFoundAtRuntime { span: ZERO_SPAN })
);
}
#[test]
fn test_children_changes_persist_in_offspring() {
let mut original = Stack::new();
original.add_var(0, string_value("hello"));
original.add_var(VarId::new(0), string_value("hello"));
let mut cloned = Stack::with_parent(Arc::new(original));
cloned.add_var(1, string_value("there"));
cloned.add_var(VarId::new(1), string_value("there"));
cloned.remove_var(0);
cloned.remove_var(VarId::new(0));
let cloned = Stack::with_parent(Arc::new(cloned));
assert_eq!(
cloned.get_var(0, ZERO_SPAN),
cloned.get_var(VarId::new(0), ZERO_SPAN),
Err(crate::ShellError::VariableNotFoundAtRuntime { span: ZERO_SPAN })
);
assert_eq!(cloned.get_var(1, ZERO_SPAN), Ok(string_value("there")));
assert_eq!(
cloned.get_var(VarId::new(1), ZERO_SPAN),
Ok(string_value("there"))
);
}
#[test]
fn test_merging_children_back_to_parent() {
let mut original = Stack::new();
let engine_state = EngineState::new();
original.add_var(0, string_value("hello"));
original.add_var(VarId::new(0), string_value("hello"));
let original_arc = Arc::new(original);
let mut cloned = Stack::with_parent(original_arc.clone());
cloned.add_var(1, string_value("there"));
cloned.add_var(VarId::new(1), string_value("there"));
cloned.remove_var(0);
cloned.remove_var(VarId::new(0));
cloned.add_env_var("ADDED_IN_CHILD".to_string(), string_value("New Env Var"));
let original = Stack::with_changes_from_child(original_arc, cloned);
assert_eq!(
original.get_var(0, ZERO_SPAN),
original.get_var(VarId::new(0), ZERO_SPAN),
Err(crate::ShellError::VariableNotFoundAtRuntime { span: ZERO_SPAN })
);
assert_eq!(original.get_var(1, ZERO_SPAN), Ok(string_value("there")));
assert_eq!(
original.get_var(VarId::new(1), ZERO_SPAN),
Ok(string_value("there"))
);
assert_eq!(
original.get_env_var(&engine_state, "ADDED_IN_CHILD"),

View File

@ -98,7 +98,7 @@ impl StateDelta {
Some(
&mut last_scope
.overlays
.get_mut(*last_overlay_id)
.get_mut(last_overlay_id.get())
.expect("internal error: missing required overlay")
.1,
)
@ -117,7 +117,7 @@ impl StateDelta {
Some(
&last_scope
.overlays
.get(*last_overlay_id)
.get(last_overlay_id.get())
.expect("internal error: missing required overlay")
.1,
)

View File

@ -4,8 +4,8 @@ use crate::{
description::build_desc, CachedFile, Command, CommandType, EngineState, OverlayFrame,
StateDelta, Variable, VirtualPath, Visibility,
},
BlockId, Category, CompileError, Config, DeclId, FileId, GetSpan, Module, ModuleId, ParseError,
ParseWarning, Signature, Span, SpanId, Type, Value, VarId, VirtualPathId,
BlockId, Category, CompileError, Config, DeclId, FileId, GetSpan, Module, ModuleId, OverlayId,
ParseError, ParseWarning, Signature, Span, SpanId, Type, Value, VarId, VirtualPathId,
};
use core::panic;
use std::{
@ -92,7 +92,7 @@ impl<'a> StateWorkingSet<'a> {
for overlay_id in scope_frame.active_overlays.iter().rev() {
let (overlay_name, _) = scope_frame
.overlays
.get(*overlay_id)
.get(overlay_id.get())
.expect("internal error: missing overlay");
names.insert(overlay_name);
@ -112,6 +112,7 @@ impl<'a> StateWorkingSet<'a> {
self.delta.decls.push(decl);
let decl_id = self.num_decls() - 1;
let decl_id = DeclId::new(decl_id);
self.last_overlay_mut().insert_decl(name, decl_id);
@ -152,6 +153,7 @@ impl<'a> StateWorkingSet<'a> {
self.delta.decls.push(decl);
let decl_id = self.num_decls() - 1;
let decl_id = DeclId::new(decl_id);
self.delta
.last_scope_frame_mut()
@ -268,7 +270,7 @@ impl<'a> StateWorkingSet<'a> {
self.delta.blocks.push(block);
self.num_blocks() - 1
BlockId::new(self.num_blocks() - 1)
}
pub fn add_module(&mut self, name: &str, module: Module, comments: Vec<Span>) -> ModuleId {
@ -276,6 +278,7 @@ impl<'a> StateWorkingSet<'a> {
self.delta.modules.push(Arc::new(module));
let module_id = self.num_modules() - 1;
let module_id = ModuleId::new(module_id);
if !comments.is_empty() {
self.delta
@ -314,7 +317,7 @@ impl<'a> StateWorkingSet<'a> {
}
pub fn get_contents_of_file(&self, file_id: FileId) -> Option<&[u8]> {
if let Some(cached_file) = self.permanent_state.get_file_contents().get(file_id) {
if let Some(cached_file) = self.permanent_state.get_file_contents().get(file_id.get()) {
return Some(&cached_file.content);
}
// The index subtraction will not underflow, if we hit the permanent state first.
@ -322,7 +325,7 @@ impl<'a> StateWorkingSet<'a> {
if let Some(cached_file) = self
.delta
.get_file_contents()
.get(file_id - self.permanent_state.num_files())
.get(file_id.get() - self.permanent_state.num_files())
{
return Some(&cached_file.content);
}
@ -335,7 +338,7 @@ impl<'a> StateWorkingSet<'a> {
// First, look for the file to see if we already have it
for (idx, cached_file) in self.files().enumerate() {
if *cached_file.name == filename && &*cached_file.content == contents {
return idx;
return FileId::new(idx);
}
}
@ -350,18 +353,19 @@ impl<'a> StateWorkingSet<'a> {
covered_span,
});
self.num_files() - 1
FileId::new(self.num_files() - 1)
}
#[must_use]
pub fn add_virtual_path(&mut self, name: String, virtual_path: VirtualPath) -> VirtualPathId {
self.delta.virtual_paths.push((name, virtual_path));
self.num_virtual_paths() - 1
VirtualPathId::new(self.num_virtual_paths() - 1)
}
pub fn get_span_for_filename(&self, filename: &str) -> Option<Span> {
let file_id = self.files().position(|file| &*file.name == filename)?;
let file_id = FileId::new(file_id);
Some(self.get_span_for_file(file_id))
}
@ -373,7 +377,7 @@ impl<'a> StateWorkingSet<'a> {
pub fn get_span_for_file(&self, file_id: FileId) -> Span {
let result = self
.files()
.nth(file_id)
.nth(file_id.get())
.expect("internal error: could not find source for previously parsed file");
result.covered_span
@ -526,7 +530,7 @@ impl<'a> StateWorkingSet<'a> {
pub fn next_var_id(&self) -> VarId {
let num_permanent_vars = self.permanent_state.num_vars();
num_permanent_vars + self.delta.vars.len()
VarId::new(num_permanent_vars + self.delta.vars.len())
}
pub fn list_variables(&self) -> Vec<&[u8]> {
@ -635,40 +639,40 @@ impl<'a> StateWorkingSet<'a> {
pub fn set_variable_type(&mut self, var_id: VarId, ty: Type) {
let num_permanent_vars = self.permanent_state.num_vars();
if var_id < num_permanent_vars {
if var_id.get() < num_permanent_vars {
panic!("Internal error: attempted to set into permanent state from working set")
} else {
self.delta.vars[var_id - num_permanent_vars].ty = ty;
self.delta.vars[var_id.get() - num_permanent_vars].ty = ty;
}
}
pub fn set_variable_const_val(&mut self, var_id: VarId, val: Value) {
let num_permanent_vars = self.permanent_state.num_vars();
if var_id < num_permanent_vars {
if var_id.get() < num_permanent_vars {
panic!("Internal error: attempted to set into permanent state from working set")
} else {
self.delta.vars[var_id - num_permanent_vars].const_val = Some(val);
self.delta.vars[var_id.get() - num_permanent_vars].const_val = Some(val);
}
}
pub fn get_variable(&self, var_id: VarId) -> &Variable {
let num_permanent_vars = self.permanent_state.num_vars();
if var_id < num_permanent_vars {
if var_id.get() < num_permanent_vars {
self.permanent_state.get_var(var_id)
} else {
self.delta
.vars
.get(var_id - num_permanent_vars)
.get(var_id.get() - num_permanent_vars)
.expect("internal error: missing variable")
}
}
pub fn get_variable_if_possible(&self, var_id: VarId) -> Option<&Variable> {
let num_permanent_vars = self.permanent_state.num_vars();
if var_id < num_permanent_vars {
if var_id.get() < num_permanent_vars {
Some(self.permanent_state.get_var(var_id))
} else {
self.delta.vars.get(var_id - num_permanent_vars)
self.delta.vars.get(var_id.get() - num_permanent_vars)
}
}
@ -687,12 +691,12 @@ impl<'a> StateWorkingSet<'a> {
pub fn get_decl(&self, decl_id: DeclId) -> &dyn Command {
let num_permanent_decls = self.permanent_state.num_decls();
if decl_id < num_permanent_decls {
if decl_id.get() < num_permanent_decls {
self.permanent_state.get_decl(decl_id)
} else {
self.delta
.decls
.get(decl_id - num_permanent_decls)
.get(decl_id.get() - num_permanent_decls)
.expect("internal error: missing declaration")
.as_ref()
}
@ -700,12 +704,12 @@ impl<'a> StateWorkingSet<'a> {
pub fn get_decl_mut(&mut self, decl_id: DeclId) -> &mut Box<dyn Command> {
let num_permanent_decls = self.permanent_state.num_decls();
if decl_id < num_permanent_decls {
if decl_id.get() < num_permanent_decls {
panic!("internal error: can only mutate declarations in working set")
} else {
self.delta
.decls
.get_mut(decl_id - num_permanent_decls)
.get_mut(decl_id.get() - num_permanent_decls)
.expect("internal error: missing declaration")
}
}
@ -756,36 +760,36 @@ impl<'a> StateWorkingSet<'a> {
pub fn get_block(&self, block_id: BlockId) -> &Arc<Block> {
let num_permanent_blocks = self.permanent_state.num_blocks();
if block_id < num_permanent_blocks {
if block_id.get() < num_permanent_blocks {
self.permanent_state.get_block(block_id)
} else {
self.delta
.blocks
.get(block_id - num_permanent_blocks)
.get(block_id.get() - num_permanent_blocks)
.expect("internal error: missing block")
}
}
pub fn get_module(&self, module_id: ModuleId) -> &Module {
let num_permanent_modules = self.permanent_state.num_modules();
if module_id < num_permanent_modules {
if module_id.get() < num_permanent_modules {
self.permanent_state.get_module(module_id)
} else {
self.delta
.modules
.get(module_id - num_permanent_modules)
.get(module_id.get() - num_permanent_modules)
.expect("internal error: missing module")
}
}
pub fn get_block_mut(&mut self, block_id: BlockId) -> &mut Block {
let num_permanent_blocks = self.permanent_state.num_blocks();
if block_id < num_permanent_blocks {
if block_id.get() < num_permanent_blocks {
panic!("Attempt to mutate a block that is in the permanent (immutable) state")
} else {
self.delta
.blocks
.get_mut(block_id - num_permanent_blocks)
.get_mut(block_id.get() - num_permanent_blocks)
.map(Arc::make_mut)
.expect("internal error: missing block")
}
@ -912,7 +916,7 @@ impl<'a> StateWorkingSet<'a> {
last_scope_frame
.overlays
.push((name, OverlayFrame::from_origin(origin, prefixed)));
last_scope_frame.overlays.len() - 1
OverlayId::new(last_scope_frame.overlays.len() - 1)
};
last_scope_frame
@ -989,13 +993,13 @@ impl<'a> StateWorkingSet<'a> {
pub fn find_module_by_span(&self, span: Span) -> Option<ModuleId> {
for (id, module) in self.delta.modules.iter().enumerate() {
if Some(span) == module.span {
return Some(self.permanent_state.num_modules() + id);
return Some(ModuleId::new(self.permanent_state.num_modules() + id));
}
}
for (module_id, module) in self.permanent_state.modules.iter().enumerate() {
if Some(span) == module.span {
return Some(module_id);
return Some(ModuleId::new(module_id));
}
}
@ -1020,12 +1024,12 @@ impl<'a> StateWorkingSet<'a> {
pub fn get_virtual_path(&self, virtual_path_id: VirtualPathId) -> &(String, VirtualPath) {
let num_permanent_virtual_paths = self.permanent_state.num_virtual_paths();
if virtual_path_id < num_permanent_virtual_paths {
if virtual_path_id.get() < num_permanent_virtual_paths {
self.permanent_state.get_virtual_path(virtual_path_id)
} else {
self.delta
.virtual_paths
.get(virtual_path_id - num_permanent_virtual_paths)
.get(virtual_path_id.get() - num_permanent_virtual_paths)
.expect("internal error: missing virtual path")
}
}

View File

@ -5,7 +5,7 @@ use crate::{
ExternalArgument, ListItem, Math, Operator, RecordItem,
},
debugger::DebugContext,
Config, GetSpan, Range, Record, ShellError, Span, Value, VarId, ENV_VARIABLE_ID,
BlockId, Config, GetSpan, Range, Record, ShellError, Span, Value, VarId, ENV_VARIABLE_ID,
};
use std::{collections::HashMap, sync::Arc};
@ -369,7 +369,7 @@ pub trait Eval {
fn eval_subexpression<D: DebugContext>(
state: Self::State<'_>,
mut_state: &mut Self::MutState,
block_id: usize,
block_id: BlockId,
span: Span,
) -> Result<Value, ShellError>;
@ -396,7 +396,7 @@ pub trait Eval {
fn eval_row_condition_or_closure(
state: Self::State<'_>,
mut_state: &mut Self::MutState,
block_id: usize,
block_id: BlockId,
span: Span,
) -> Result<Value, ShellError>;

View File

@ -7,7 +7,8 @@ use crate::{
debugger::{DebugContext, WithoutDebug},
engine::{EngineState, StateWorkingSet},
eval_base::Eval,
record, Config, HistoryFileFormat, PipelineData, Record, ShellError, Span, Value, VarId,
record, BlockId, Config, HistoryFileFormat, PipelineData, Record, ShellError, Span, Value,
VarId,
};
use nu_system::os_info::{get_kernel_version, get_os_arch, get_os_family, get_os_name};
use std::{
@ -481,7 +482,7 @@ impl Eval for EvalConst {
fn eval_subexpression<D: DebugContext>(
working_set: &StateWorkingSet,
_: &mut (),
block_id: usize,
block_id: BlockId,
span: Span,
) -> Result<Value, ShellError> {
// TODO: Allow debugging const eval
@ -516,7 +517,7 @@ impl Eval for EvalConst {
fn eval_row_condition_or_closure(
_: &StateWorkingSet,
_: &mut (),
_: usize,
_: BlockId,
span: Span,
) -> Result<Value, ShellError> {
Err(ShellError::NotAConstant { span })

View File

@ -1,12 +1,90 @@
use std::any;
use std::fmt::{Debug, Error, Formatter};
use std::marker::PhantomData;
use serde::{Deserialize, Serialize};
pub type VarId = usize;
pub type DeclId = usize;
pub type BlockId = usize;
pub type ModuleId = usize;
pub type OverlayId = usize;
pub type FileId = usize;
pub type VirtualPathId = usize;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Id<T> {
inner: usize,
_phantom: PhantomData<T>,
}
impl<T> Id<T> {
/// Creates a new `Id`.
///
/// Using a distinct type like `Id` instead of `usize` helps us avoid mixing plain integers
/// with identifiers.
#[inline]
pub const fn new(inner: usize) -> Self {
Self {
inner,
_phantom: PhantomData,
}
}
/// Returns the inner `usize` value.
///
/// This requires an explicit call, ensuring we only use the raw value when intended.
#[inline]
pub const fn get(self) -> usize {
self.inner
}
}
impl<T> Debug for Id<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
let marker = any::type_name::<T>().split("::").last().expect("not empty");
write!(f, "{marker}Id({})", self.inner)
}
}
impl<T> Serialize for Id<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.inner.serialize(serializer)
}
}
impl<'de, T> Deserialize<'de> for Id<T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let inner = usize::deserialize(deserializer)?;
Ok(Self {
inner,
_phantom: PhantomData,
})
}
}
pub mod marker {
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Var;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Decl;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Block;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Module;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Overlay;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct File;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct VirtualPath;
}
pub type VarId = Id<marker::Var>;
pub type DeclId = Id<marker::Decl>;
pub type BlockId = Id<marker::Block>;
pub type ModuleId = Id<marker::Module>;
pub type OverlayId = Id<marker::Overlay>;
pub type FileId = Id<marker::File>;
pub type VirtualPathId = Id<marker::VirtualPath>;
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct SpanId(pub usize); // more robust ID style used in the new parser

View File

@ -276,11 +276,11 @@ impl<'a> FmtDecl<'a> {
impl fmt::Display for FmtDecl<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "decl {} {:?}", self.0, self.1)
write!(f, "decl {} {:?}", self.0.get(), self.1)
}
}
struct FmtVar<'a>(DeclId, Option<&'a str>);
struct FmtVar<'a>(VarId, Option<&'a str>);
impl<'a> FmtVar<'a> {
fn new(engine_state: &'a EngineState, var_id: VarId) -> Self {
@ -297,9 +297,9 @@ impl<'a> FmtVar<'a> {
impl fmt::Display for FmtVar<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(name) = self.1 {
write!(f, "var {} {:?}", self.0, name)
write!(f, "var {} {:?}", self.0.get(), name)
} else {
write!(f, "var {}", self.0)
write!(f, "var {}", self.0.get())
}
}
}
@ -346,9 +346,9 @@ impl<'a> fmt::Display for FmtLiteral<'a> {
Literal::Filesize(q) => write!(f, "filesize({q}b)"),
Literal::Duration(q) => write!(f, "duration({q}ns)"),
Literal::Binary(b) => write!(f, "binary({})", FmtData(self.data, *b)),
Literal::Block(id) => write!(f, "block({id})"),
Literal::Closure(id) => write!(f, "closure({id})"),
Literal::RowCondition(id) => write!(f, "row_condition({id})"),
Literal::Block(id) => write!(f, "block({})", id.get()),
Literal::Closure(id) => write!(f, "closure({})", id.get()),
Literal::RowCondition(id) => write!(f, "row_condition({})", id.get()),
Literal::Range {
start,
step,

View File

@ -1,4 +1,7 @@
use crate::engine::{StateWorkingSet, VirtualPath};
use crate::{
engine::{StateWorkingSet, VirtualPath},
FileId,
};
use std::{
ffi::OsStr,
path::{Path, PathBuf},
@ -112,7 +115,7 @@ impl ParserPath {
std::fs::File::open(p).map(|f| Box::new(f) as Box<dyn std::io::Read>)
}
ParserPath::VirtualFile(_, file_id) => working_set
.get_contents_of_file(*file_id)
.get_contents_of_file(FileId::new(*file_id))
.map(|bytes| Box::new(bytes) as Box<dyn std::io::Read>)
.ok_or(std::io::ErrorKind::NotFound.into()),
@ -136,7 +139,9 @@ impl ParserPath {
virtual_path: &VirtualPath,
) -> Self {
match virtual_path {
VirtualPath::File(file_id) => ParserPath::VirtualFile(PathBuf::from(name), *file_id),
VirtualPath::File(file_id) => {
ParserPath::VirtualFile(PathBuf::from(name), file_id.get())
}
VirtualPath::Dir(entries) => ParserPath::VirtualDir(
PathBuf::from(name),
entries

View File

@ -23,7 +23,7 @@ use crate::{
ast::{Bits, Boolean, CellPath, Comparison, Math, Operator, PathMember},
did_you_mean,
engine::{Closure, EngineState},
Config, ShellError, Signals, Span, Type,
BlockId, Config, ShellError, Signals, Span, Type,
};
use chrono::{DateTime, Datelike, FixedOffset, Locale, TimeZone};
use chrono_humanize::HumanTime;
@ -863,7 +863,7 @@ impl Value {
.collect::<Vec<_>>()
.join(separator)
),
Value::Closure { val, .. } => format!("<Closure {}>", val.block_id),
Value::Closure { val, .. } => format!("<Closure {}>", val.block_id.get()),
Value::Nothing { .. } => String::new(),
Value::Error { error, .. } => format!("{error:?}"),
Value::Binary { val, .. } => format!("{val:?}"),
@ -2029,7 +2029,7 @@ impl Value {
Value::test_record(Record::new()),
Value::test_list(Vec::new()),
Value::test_closure(Closure {
block_id: 0,
block_id: BlockId::new(0),
captures: Vec::new(),
}),
Value::test_nothing(),