fix(tvix/eval): Force thunks during equality comparison

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>
This commit is contained in:
Griffin Smith 2022-09-18 15:34:33 -04:00 committed by clbot
parent 0b76ed5615
commit 6f70f32513
3 changed files with 20 additions and 5 deletions

View file

@ -0,0 +1 @@
[ true true false ]

View file

@ -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)
]

View file

@ -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()),