about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2022-08-09T17·24+0300
committertazjin <tazjin@tvl.su>2022-08-13T20·24+0000
commit8c2bc683cd28f095ce7942fa2402b48e7e6139be (patch)
tree2e45a85cc60000fea6b40df3617ea1e94af1ac72
parente15bd9aa63d03e95b6151d5b0dbb4d43a1de5901 (diff)
refactor(tvix/value): explicitly implement PartialEq for value r/4441
There are some notions of equality (due to e.g. different backing
variants for types, or Nix particularities) that don't work correctly
when deriving PartialEq.

Change-Id: Ide83ae67d051cc0b3ca89cefb283f17d0207acce
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6105
Tested-by: BuildkiteCI
Reviewed-by: grfn <grfn@gws.fyi>
-rw-r--r--tvix/eval/src/value/mod.rs27
1 files changed, 26 insertions, 1 deletions
diff --git a/tvix/eval/src/value/mod.rs b/tvix/eval/src/value/mod.rs
index 8a95d00f41..55d44048b6 100644
--- a/tvix/eval/src/value/mod.rs
+++ b/tvix/eval/src/value/mod.rs
@@ -12,7 +12,7 @@ pub use attrs::NixAttrs;
 pub use list::NixList;
 pub use string::NixString;
 
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug)]
 pub enum Value {
     Null,
     Bool(bool),
@@ -89,3 +89,28 @@ impl Display for Value {
         }
     }
 }
+
+impl PartialEq for Value {
+    fn eq(&self, other: &Self) -> bool {
+        match (self, other) {
+            // Trivial comparisons
+            (Value::Null, Value::Null) => true,
+            (Value::Bool(b1), Value::Bool(b2)) => b1 == b2,
+            (Value::List(l1), Value::List(l2)) => l1 == l2,
+            (Value::String(s1), Value::String(s2)) => s1 == s2,
+
+            // Numerical comparisons (they work between float & int)
+            (Value::Integer(i1), Value::Integer(i2)) => i1 == i2,
+            (Value::Integer(i), Value::Float(f)) => *i as f64 == *f,
+            (Value::Float(f1), Value::Float(f2)) => f1 == f2,
+            (Value::Float(f), Value::Integer(i)) => *i as f64 == *f,
+
+            // Optimised attribute set comparison
+            (Value::Attrs(a1), Value::Attrs(a2)) => Rc::ptr_eq(a1, a2) || { a1 == a2 },
+
+            // Everything else is either incomparable (e.g. internal
+            // types) or false.
+            _ => false,
+        }
+    }
+}