From 7ddea7340f547166a3c3f7fdd0afa776d9ba35aa Mon Sep 17 00:00:00 2001 From: Adam Joseph Date: Tue, 12 Dec 2023 21:18:09 -0800 Subject: [PATCH] fix(tvix/eval): catchable in type field of nix_eq() Change-Id: I165ff77764e272cc94d18cb03ad6cbc9a8ebefde Reviewed-on: https://cl.tvl.fyi/c/depot/+/10348 Autosubmit: Adam Joseph Reviewed-by: sterni Tested-by: BuildkiteCI --- tvix/eval/src/builtins/mod.rs | 15 +++++++++++---- ...-equality-tolerate-catchable-in-type-field.exp | 1 + ...-equality-tolerate-catchable-in-type-field.nix | 1 + tvix/eval/src/value/mod.rs | 12 ++++++++++-- tvix/eval/src/vm/generators.rs | 5 +++-- 5 files changed, 26 insertions(+), 8 deletions(-) create mode 100644 tvix/eval/src/tests/tvix_tests/eval-okay-equality-tolerate-catchable-in-type-field.exp create mode 100644 tvix/eval/src/tests/tvix_tests/eval-okay-equality-tolerate-catchable-in-type-field.nix diff --git a/tvix/eval/src/builtins/mod.rs b/tvix/eval/src/builtins/mod.rs index 7cc2732ec..6ecbb5028 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 { 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) -> Result { 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) -> 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 000000000..c508d5366 --- /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 000000000..ecfc2ad37 --- /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 eb54f6ae5..40c0025c4 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 9686e6542..716aaf96b 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 { +) -> Result, 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