about summary refs log tree commit diff
path: root/tvix/eval/src/vm
diff options
context:
space:
mode:
authorFlorian Klink <flokli@flokli.de>2024-01-16T12·19+0200
committerflokli <flokli@flokli.de>2024-01-18T09·09+0000
commite0a867cabff021348cc283b25467cfd40b8eb15a (patch)
tree9b4f1fd63460ba8385b38259481a7bb32363801b /tvix/eval/src/vm
parent44d24852c3c62320cb2a4c9b9627e744c518f207 (diff)
refactor(tvix/eval): generalize EvalIO container r/7407
Don't restrict to a Box<dyn EvalIO>.

There's still one or two places where we do restrict, this will be
solved by b/262.

Change-Id: Ic8d927d6ea81fa12d90b1e4352f35ffaafbd1adf
Reviewed-on: https://cl.tvl.fyi/c/depot/+/10639
Tested-by: BuildkiteCI
Reviewed-by: raitobezarius <tvl@lahfa.xyz>
Diffstat (limited to 'tvix/eval/src/vm')
-rw-r--r--tvix/eval/src/vm/generators.rs9
-rw-r--r--tvix/eval/src/vm/mod.rs39
2 files changed, 32 insertions, 16 deletions
diff --git a/tvix/eval/src/vm/generators.rs b/tvix/eval/src/vm/generators.rs
index f2ce73a0c742..3d2fd9d266c7 100644
--- a/tvix/eval/src/vm/generators.rs
+++ b/tvix/eval/src/vm/generators.rs
@@ -224,7 +224,10 @@ pub fn pin_generator(
     Box::pin(f)
 }
 
-impl<'o> VM<'o> {
+impl<'o, IO> VM<'o, IO>
+where
+    IO: AsRef<dyn EvalIO> + 'static,
+{
     /// Helper function to re-enqueue the current generator while it
     /// is awaiting a value.
     fn reenqueue_generator(&mut self, name: &'static str, span: LightSpan, generator: Generator) {
@@ -411,6 +414,7 @@ impl<'o> VM<'o> {
                         VMRequest::PathImport(path) => {
                             let imported = self
                                 .io_handle
+                                .as_ref()
                                 .import_path(&path)
                                 .map_err(|e| ErrorKind::IO {
                                     path: Some(path),
@@ -424,6 +428,7 @@ impl<'o> VM<'o> {
                         VMRequest::ReadToString(path) => {
                             let content = self
                                 .io_handle
+                                .as_ref()
                                 .read_to_string(&path)
                                 .map_err(|e| ErrorKind::IO {
                                     path: Some(path),
@@ -437,6 +442,7 @@ impl<'o> VM<'o> {
                         VMRequest::PathExists(path) => {
                             let exists = self
                                 .io_handle
+                                .as_ref()
                                 .path_exists(&path)
                                 .map_err(|e| ErrorKind::IO {
                                     path: Some(path),
@@ -451,6 +457,7 @@ impl<'o> VM<'o> {
                         VMRequest::ReadDir(path) => {
                             let dir = self
                                 .io_handle
+                                .as_ref()
                                 .read_dir(&path)
                                 .map_err(|e| ErrorKind::IO {
                                     path: Some(path),
diff --git a/tvix/eval/src/vm/mod.rs b/tvix/eval/src/vm/mod.rs
index 398a02cc78c8..5238fdc0662f 100644
--- a/tvix/eval/src/vm/mod.rs
+++ b/tvix/eval/src/vm/mod.rs
@@ -48,7 +48,7 @@ trait GetSpan {
     fn get_span(self) -> Span;
 }
 
-impl<'o> GetSpan for &VM<'o> {
+impl<'o, IO> GetSpan for &VM<'o, IO> {
     fn get_span(self) -> Span {
         self.reasonable_span.span()
     }
@@ -75,12 +75,12 @@ impl GetSpan for Span {
 /// Internal helper trait for ergonomically converting from a `Result<T,
 /// ErrorKind>` to a `Result<T, Error>` using the current span of a call frame,
 /// and chaining the VM's frame stack around it for printing a cause chain.
-trait WithSpan<T, S: GetSpan> {
-    fn with_span(self, top_span: S, vm: &VM) -> Result<T, Error>;
+trait WithSpan<T, S: GetSpan, IO> {
+    fn with_span(self, top_span: S, vm: &VM<IO>) -> Result<T, Error>;
 }
 
-impl<T, S: GetSpan> WithSpan<T, S> for Result<T, ErrorKind> {
-    fn with_span(self, top_span: S, vm: &VM) -> Result<T, Error> {
+impl<T, S: GetSpan, IO> WithSpan<T, S, IO> for Result<T, ErrorKind> {
+    fn with_span(self, top_span: S, vm: &VM<IO>) -> Result<T, Error> {
         match self {
             Ok(something) => Ok(something),
             Err(kind) => {
@@ -149,7 +149,7 @@ impl CallFrame {
 
     /// Construct an error result from the given ErrorKind and the source span
     /// of the current instruction.
-    pub fn error<T>(&self, vm: &VM, kind: ErrorKind) -> Result<T, Error> {
+    pub fn error<T, IO>(&self, vm: &VM<IO>, kind: ErrorKind) -> Result<T, Error> {
         Err(kind).with_span(self, vm)
     }
 
@@ -249,7 +249,7 @@ impl ImportCache {
     }
 }
 
-struct VM<'o> {
+struct VM<'o, IO> {
     /// VM's frame stack, representing the execution contexts the VM is working
     /// through. Elements are usually pushed when functions are called, or
     /// thunks are being forced.
@@ -280,7 +280,7 @@ struct VM<'o> {
 
     /// Implementation of I/O operations used for impure builtins and
     /// features like `import`.
-    io_handle: Box<dyn EvalIO>,
+    io_handle: IO,
 
     /// Runtime observer which can print traces of runtime operations.
     observer: &'o mut dyn RuntimeObserver,
@@ -324,10 +324,13 @@ struct VM<'o> {
     try_eval_frames: Vec<usize>,
 }
 
-impl<'o> VM<'o> {
+impl<'o, IO> VM<'o, IO>
+where
+    IO: AsRef<dyn EvalIO> + 'static,
+{
     pub fn new(
         nix_search_path: NixSearchPath,
-        io_handle: Box<dyn EvalIO>,
+        io_handle: IO,
         observer: &'o mut dyn RuntimeObserver,
         globals: Rc<GlobalsMap>,
         reasonable_span: LightSpan,
@@ -858,7 +861,7 @@ impl<'o> VM<'o> {
                     Value::UnresolvedPath(path) => {
                         let resolved = self
                             .nix_search_path
-                            .resolve(&mut *self.io_handle, *path)
+                            .resolve(&self.io_handle, *path)
                             .with_span(&frame, self)?;
                         self.stack.push(resolved.into());
                     }
@@ -914,7 +917,10 @@ impl<'o> VM<'o> {
 }
 
 /// Implementation of helper functions for the runtime logic above.
-impl<'o> VM<'o> {
+impl<'o, IO> VM<'o, IO>
+where
+    IO: AsRef<dyn EvalIO> + 'static,
+{
     pub(crate) fn stack_pop(&mut self) -> Value {
         self.stack.pop().expect("runtime stack empty")
     }
@@ -1301,14 +1307,17 @@ async fn final_deep_force(co: GenCo) -> Result<Value, ErrorKind> {
     Ok(generators::request_deep_force(&co, value).await)
 }
 
-pub fn run_lambda(
+pub fn run_lambda<IO>(
     nix_search_path: NixSearchPath,
-    io_handle: Box<dyn EvalIO>,
+    io_handle: IO,
     observer: &mut dyn RuntimeObserver,
     globals: Rc<GlobalsMap>,
     lambda: Rc<Lambda>,
     strict: bool,
-) -> EvalResult<RuntimeResult> {
+) -> EvalResult<RuntimeResult>
+where
+    IO: AsRef<dyn EvalIO> + 'static,
+{
     // Retain the top-level span of the expression in this lambda, as
     // synthetic "calls" in deep_force will otherwise not have a span
     // to fall back to.