diff options
author | Griffin Smith <root@gws.fyi> | 2022-09-18T19·34-0400 |
---|---|---|
committer | clbot <clbot@tvl.fyi> | 2022-09-18T22·08+0000 |
commit | 6f70f325138b48f2c9b03a2103371663cb210d7c (patch) | |
tree | a5eeb3b027a98e387c2cc24a8999bc60f376c241 | |
parent | 0b76ed5615eb48130773abf1e1a949e29b6cbd25 (diff) |
fix(tvix/eval): Force thunks during equality comparison r/4910
Thunks might be encountered deep in equality comparison (eg nested inside a list or attr-set), at which point we need to force them in order to compare them for equality (or else we panic when trying to get at their value). Fixes: b/192 Change-Id: I912151085f8298f30d5214c7965251c9266443f2 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6652 Autosubmit: grfn <grfn@gws.fyi> Tested-by: BuildkiteCI Reviewed-by: tazjin <tazjin@tvl.su>
-rw-r--r-- | tvix/eval/src/tests/tvix_tests/eval-okay-lazy-equality.exp | 1 | ||||
-rw-r--r-- | tvix/eval/src/tests/tvix_tests/eval-okay-lazy-equality.nix | 11 | ||||
-rw-r--r-- | tvix/eval/src/value/mod.rs | 13 |
3 files changed, 20 insertions, 5 deletions
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-equality.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-equality.exp new file mode 100644 index 000000000000..e6f2d1aaadd2 --- /dev/null +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-equality.exp @@ -0,0 +1 @@ +[ true true false ] diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-equality.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-equality.nix new file mode 100644 index 000000000000..b0ec8593a468 --- /dev/null +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-equality.nix @@ -0,0 +1,11 @@ +let + attrs1 = { x = 1 + 2; }; + attrs2 = { x = 2 + 1; }; + list1 = [ (1 + 2) ]; + list2 = [ (2 + 1) ]; + list3 = [ (2 + 2) ]; +in [ + (attrs1 == attrs2) + (list1 == list2) + (list3 == list2) +] diff --git a/tvix/eval/src/value/mod.rs b/tvix/eval/src/value/mod.rs index 8a2ab19961cf..b628d7c4ee8f 100644 --- a/tvix/eval/src/value/mod.rs +++ b/tvix/eval/src/value/mod.rs @@ -275,11 +275,14 @@ impl Value { // Optimised attribute set comparison (Value::Attrs(a1), Value::Attrs(a2)) => Ok(Rc::ptr_eq(a1, a2) || a1.nix_eq(a2, vm)?), - // If either value is a thunk, the inner value must be - // compared instead. The compiler should ensure that - // thunks under comparison have been forced, otherwise it - // is a bug. - (Value::Thunk(lhs), Value::Thunk(rhs)) => Ok(*lhs.value() == *rhs.value()), + // If either value is a thunk, the thunk should be forced, and then the resulting value + // must be compared instead. + (Value::Thunk(lhs), Value::Thunk(rhs)) => { + lhs.force(vm)?; + rhs.force(vm)?; + + Ok(*lhs.value() == *rhs.value()) + } (Value::Thunk(lhs), rhs) => Ok(&*lhs.value() == rhs), (lhs, Value::Thunk(rhs)) => Ok(lhs == &*rhs.value()), |