about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--tvix/eval/src/builtins/mod.rs2
-rw-r--r--tvix/eval/src/value/mod.rs29
-rw-r--r--tvix/eval/src/vm/macros.rs8
3 files changed, 16 insertions, 23 deletions
diff --git a/tvix/eval/src/builtins/mod.rs b/tvix/eval/src/builtins/mod.rs
index ead916377f94..35b7549ffea0 100644
--- a/tvix/eval/src/builtins/mod.rs
+++ b/tvix/eval/src/builtins/mod.rs
@@ -612,7 +612,7 @@ mod pure_builtins {
     async fn builtin_less_than(co: GenCo, x: Value, y: Value) -> Result<Value, ErrorKind> {
         Ok(Value::Bool(matches!(
             x.nix_cmp_ordering(y, co).await?,
-            Some(Ordering::Less)
+            Ordering::Less
         )))
     }
 
diff --git a/tvix/eval/src/value/mod.rs b/tvix/eval/src/value/mod.rs
index f4ed7733eec4..c0bdc5fc5eb7 100644
--- a/tvix/eval/src/value/mod.rs
+++ b/tvix/eval/src/value/mod.rs
@@ -600,18 +600,9 @@ impl Value {
     // TODO(amjoseph): de-asyncify this (when called directly by the VM)
     /// Compare `self` against other using (fallible) Nix ordering semantics.
     ///
-    /// Note that as this returns an `Option<Ordering>` it can not directly be
-    /// used as a generator function in the VM. The exact use depends on the
-    /// callsite, as the meaning is interpreted in different ways e.g. based on
-    /// the comparison operator used.
-    ///
     /// The function is intended to be used from within other generator
     /// functions or `gen!` blocks.
-    pub async fn nix_cmp_ordering(
-        self,
-        other: Self,
-        co: GenCo,
-    ) -> Result<Option<Ordering>, ErrorKind> {
+    pub async fn nix_cmp_ordering(self, other: Self, co: GenCo) -> Result<Ordering, ErrorKind> {
         Self::nix_cmp_ordering_(self, other, co).await
     }
 
@@ -619,19 +610,21 @@ impl Value {
         mut myself: Self,
         mut other: Self,
         co: GenCo,
-    ) -> Result<Option<Ordering>, ErrorKind> {
+    ) -> Result<Ordering, ErrorKind> {
         'outer: loop {
             match (myself, other) {
                 // same types
-                (Value::Integer(i1), Value::Integer(i2)) => return Ok(i1.partial_cmp(&i2)),
-                (Value::Float(f1), Value::Float(f2)) => return Ok(f1.partial_cmp(&f2)),
-                (Value::String(s1), Value::String(s2)) => return Ok(s1.partial_cmp(&s2)),
+                // Nix does not support NaN or "negative infinity",
+                // so its floats are in fact totally ordered.
+                (Value::Integer(i1), Value::Integer(i2)) => return Ok(i1.cmp(&i2)),
+                (Value::Float(f1), Value::Float(f2)) => return Ok(f1.total_cmp(&f2)),
+                (Value::String(s1), Value::String(s2)) => return Ok(s1.cmp(&s2)),
                 (Value::List(l1), Value::List(l2)) => {
                     for i in 0.. {
                         if i == l2.len() {
-                            return Ok(Some(Ordering::Greater));
+                            return Ok(Ordering::Greater);
                         } else if i == l1.len() {
-                            return Ok(Some(Ordering::Less));
+                            return Ok(Ordering::Less);
                         } else if !generators::check_equality(
                             &co,
                             l1[i].clone(),
@@ -651,8 +644,8 @@ impl Value {
                 }
 
                 // different types
-                (Value::Integer(i1), Value::Float(f2)) => return Ok((i1 as f64).partial_cmp(&f2)),
-                (Value::Float(f1), Value::Integer(i2)) => return Ok(f1.partial_cmp(&(i2 as f64))),
+                (Value::Integer(i1), Value::Float(f2)) => return Ok((i1 as f64).total_cmp(&f2)),
+                (Value::Float(f1), Value::Integer(i2)) => return Ok(f1.total_cmp(&(i2 as f64))),
 
                 // unsupported types
                 (lhs, rhs) => {
diff --git a/tvix/eval/src/vm/macros.rs b/tvix/eval/src/vm/macros.rs
index 969b50807766..8a536ee4664d 100644
--- a/tvix/eval/src/vm/macros.rs
+++ b/tvix/eval/src/vm/macros.rs
@@ -53,18 +53,18 @@ macro_rules! cmp_op {
     }};
 
     (@order < $ordering:expr) => {
-        $ordering == Some(Ordering::Less)
+        $ordering == Ordering::Less
     };
 
     (@order > $ordering:expr) => {
-        $ordering == Some(Ordering::Greater)
+        $ordering == Ordering::Greater
     };
 
     (@order <= $ordering:expr) => {
-        !matches!($ordering, None | Some(Ordering::Greater))
+        matches!($ordering, Ordering::Equal | Ordering::Less)
     };
 
     (@order >= $ordering:expr) => {
-        !matches!($ordering, None | Some(Ordering::Less))
+        matches!($ordering, Ordering::Equal | Ordering::Greater)
     };
 }