about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--tvix/eval/src/builtins/mod.rs22
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-genericClosure-propagate-catchable.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-genericClosure-propagate-catchable.nix1
3 files changed, 17 insertions, 7 deletions
diff --git a/tvix/eval/src/builtins/mod.rs b/tvix/eval/src/builtins/mod.rs
index b19ba7009f2f..bbf2eb80c410 100644
--- a/tvix/eval/src/builtins/mod.rs
+++ b/tvix/eval/src/builtins/mod.rs
@@ -501,7 +501,13 @@ mod pure_builtins {
             let attrs = val.to_attrs()?;
             let key = attrs.select_required("key")?;
 
-            if !bgc_insert_key(&co, key.clone(), &mut done_keys).await? {
+            let value_missing = bgc_insert_key(&co, key.clone(), &mut done_keys).await?;
+
+            if let Err(cek) = value_missing {
+                return Ok(Value::Catchable(Box::new(cek)));
+            }
+
+            if let Ok(false) = value_missing {
                 continue;
             }
 
@@ -1485,7 +1491,11 @@ mod pure_builtins {
 
 /// Internal helper function for genericClosure, determining whether a
 /// value has been seen before.
-async fn bgc_insert_key(co: &GenCo, key: Value, done: &mut Vec<Value>) -> Result<bool, ErrorKind> {
+async fn bgc_insert_key(
+    co: &GenCo,
+    key: Value,
+    done: &mut Vec<Value>,
+) -> Result<Result<bool, CatchableErrorKind>, ErrorKind> {
     for existing in done.iter() {
         match generators::check_equality(
             co,
@@ -1496,16 +1506,14 @@ async fn bgc_insert_key(co: &GenCo, key: Value, done: &mut Vec<Value>) -> Result
         )
         .await?
         {
-            Ok(true) => return Ok(false),
+            Ok(true) => return Ok(Ok(false)),
             Ok(false) => (),
-            Err(_cek) => {
-                unimplemented!("TODO(amjoseph): not sure what the correct behavior is here")
-            }
+            Err(cek) => return Ok(Err(cek)),
         }
     }
 
     done.push(key);
-    Ok(true)
+    Ok(Ok(true))
 }
 
 /// The set of standard pure builtins in Nix, mostly concerned with
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-genericClosure-propagate-catchable.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-genericClosure-propagate-catchable.exp
new file mode 100644
index 000000000000..6c89e78fc4b5
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-genericClosure-propagate-catchable.exp
@@ -0,0 +1 @@
+{ success = false; value = false; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-genericClosure-propagate-catchable.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-genericClosure-propagate-catchable.nix
new file mode 100644
index 000000000000..1dfc0bb04fc5
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-genericClosure-propagate-catchable.nix
@@ -0,0 +1 @@
+builtins.tryEval (builtins.genericClosure { operator = (_: [{ key = throw "lol"; }]); startSet = [{ key = "lol"; }]; })