about summary refs log tree commit diff
path: root/tvix/eval/src
diff options
context:
space:
mode:
Diffstat (limited to 'tvix/eval/src')
-rw-r--r--tvix/eval/src/builtins/mod.rs15
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-equality-tolerate-catchable-in-type-field.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-equality-tolerate-catchable-in-type-field.nix1
-rw-r--r--tvix/eval/src/value/mod.rs12
-rw-r--r--tvix/eval/src/vm/generators.rs5
5 files changed, 26 insertions, 8 deletions
diff --git a/tvix/eval/src/builtins/mod.rs b/tvix/eval/src/builtins/mod.rs
index 7cc2732ecfd9..6ecbb5028471 100644
--- a/tvix/eval/src/builtins/mod.rs
+++ b/tvix/eval/src/builtins/mod.rs
@@ -312,8 +312,11 @@ mod pure_builtins {
     #[builtin("elem")]
     async fn builtin_elem(co: GenCo, x: Value, xs: Value) -> Result<Value, ErrorKind> {
         for val in xs.to_list()? {
-            if generators::check_equality(&co, x.clone(), val, PointerEquality::AllowAll).await? {
-                return Ok(true.into());
+            match generators::check_equality(&co, x.clone(), val, PointerEquality::AllowAll).await?
+            {
+                Ok(true) => return Ok(true.into()),
+                Ok(false) => continue,
+                Err(cek) => return Ok(Value::Catchable(cek)),
             }
         }
         Ok(false.into())
@@ -1183,7 +1186,7 @@ mod pure_builtins {
 /// value has been seen before.
 async fn bgc_insert_key(co: &GenCo, key: Value, done: &mut Vec<Value>) -> Result<bool, ErrorKind> {
     for existing in done.iter() {
-        if generators::check_equality(
+        match generators::check_equality(
             co,
             existing.clone(),
             key.clone(),
@@ -1192,7 +1195,11 @@ async fn bgc_insert_key(co: &GenCo, key: Value, done: &mut Vec<Value>) -> Result
         )
         .await?
         {
-            return Ok(false);
+            Ok(true) => return Ok(false),
+            Ok(false) => (),
+            Err(_cek) => {
+                unimplemented!("TODO(amjoseph): not sure what the correct behavior is here")
+            }
         }
     }
 
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-equality-tolerate-catchable-in-type-field.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-equality-tolerate-catchable-in-type-field.exp
new file mode 100644
index 000000000000..c508d5366f70
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-equality-tolerate-catchable-in-type-field.exp
@@ -0,0 +1 @@
+false
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-equality-tolerate-catchable-in-type-field.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-equality-tolerate-catchable-in-type-field.nix
new file mode 100644
index 000000000000..ecfc2ad37523
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-equality-tolerate-catchable-in-type-field.nix
@@ -0,0 +1 @@
+(builtins.tryEval (builtins.elem { type = rec { x = throw "fred"; }.x; } [ { type = 3; } ])).success
diff --git a/tvix/eval/src/value/mod.rs b/tvix/eval/src/value/mod.rs
index eb54f6ae5bd8..40c0025c45ca 100644
--- a/tvix/eval/src/value/mod.rs
+++ b/tvix/eval/src/value/mod.rs
@@ -547,8 +547,16 @@ impl Value {
                     #[allow(clippy::single_match)] // might need more match arms later
                     match (a1.select("type"), a2.select("type")) {
                         (Some(v1), Some(v2)) => {
-                            let s1 = v1.clone().force(co, span.clone()).await?.to_str();
-                            let s2 = v2.clone().force(co, span.clone()).await?.to_str();
+                            let s1 = v1.clone().force(co, span.clone()).await?;
+                            if s1.is_catchable() {
+                                return Ok(s1);
+                            }
+                            let s2 = v2.clone().force(co, span.clone()).await?;
+                            if s2.is_catchable() {
+                                return Ok(s2);
+                            }
+                            let s1 = s1.to_str();
+                            let s2 = s2.to_str();
 
                             if let (Ok(s1), Ok(s2)) = (s1, s2) {
                                 if s1.as_str() == "derivation" && s2.as_str() == "derivation" {
diff --git a/tvix/eval/src/vm/generators.rs b/tvix/eval/src/vm/generators.rs
index 9686e6542f13..716aaf96b498 100644
--- a/tvix/eval/src/vm/generators.rs
+++ b/tvix/eval/src/vm/generators.rs
@@ -631,12 +631,13 @@ pub(crate) async fn check_equality(
     a: Value,
     b: Value,
     ptr_eq: PointerEquality,
-) -> Result<bool, ErrorKind> {
+) -> Result<Result<bool, CatchableErrorKind>, ErrorKind> {
     match co
         .yield_(VMRequest::NixEquality(Box::new((a, b)), ptr_eq))
         .await
     {
-        VMResponse::Value(value) => value.as_bool(),
+        VMResponse::Value(Value::Bool(b)) => Ok(Ok(b)),
+        VMResponse::Value(Value::Catchable(cek)) => Ok(Err(cek)),
         msg => panic!(
             "Tvix bug: VM responded with incorrect generator message: {}",
             msg