fix(tvix/eval): preserve catchables in nix_cmp_ordering(), fix b/338

This commit fixes b/338 by properly propagating catchables through
comparison operations.

Change-Id: I6b0283a40f228ecf9a6398d24c060bdacb1077cf
Reviewed-on: https://cl.tvl.fyi/c/depot/+/10221
Reviewed-by: tazjin <tazjin@tvl.su>
Tested-by: BuildkiteCI
Autosubmit: Adam Joseph <adam@westernsemico.com>
This commit is contained in:
Adam Joseph 2023-12-09 00:58:30 -08:00 committed by clbot
parent ae28dc3ca6
commit ad566999ca
5 changed files with 15 additions and 9 deletions

View file

@ -611,10 +611,11 @@ mod pure_builtins {
#[builtin("lessThan")] #[builtin("lessThan")]
async fn builtin_less_than(co: GenCo, x: Value, y: Value) -> Result<Value, ErrorKind> { async fn builtin_less_than(co: GenCo, x: Value, y: Value) -> Result<Value, ErrorKind> {
let span = generators::request_span(&co).await; let span = generators::request_span(&co).await;
Ok(Value::Bool(matches!( match x.nix_cmp_ordering(y, co, span).await? {
x.nix_cmp_ordering(y, co, span).await?, Err(cek) => Ok(Value::Catchable(cek)),
Ordering::Less Ok(Ordering::Less) => Ok(Value::Bool(true)),
))) Ok(_) => Ok(Value::Bool(false)),
}
} }
#[builtin("listToAttrs")] #[builtin("listToAttrs")]

View file

@ -616,7 +616,7 @@ impl Value {
other: Self, other: Self,
co: GenCo, co: GenCo,
span: LightSpan, span: LightSpan,
) -> Result<Ordering, ErrorKind> { ) -> Result<Result<Ordering, CatchableErrorKind>, ErrorKind> {
Self::nix_cmp_ordering_(self, other, co, span).await Self::nix_cmp_ordering_(self, other, co, span).await
} }
@ -625,7 +625,7 @@ impl Value {
other: Self, other: Self,
co: GenCo, co: GenCo,
span: LightSpan, span: LightSpan,
) -> Result<Ordering, ErrorKind> { ) -> Result<Result<Ordering, CatchableErrorKind>, ErrorKind> {
// this is a stack of ((v1,v2),peq) triples to be compared; // this is a stack of ((v1,v2),peq) triples to be compared;
// after each triple is popped off of the stack, v1 is // after each triple is popped off of the stack, v1 is
// compared to v2 using peq-mode PointerEquality // compared to v2 using peq-mode PointerEquality
@ -636,7 +636,7 @@ impl Value {
abp abp
} else { } else {
// stack is empty, so they are equal // stack is empty, so they are equal
return Ok(Ordering::Equal); return Ok(Ok(Ordering::Equal));
}; };
if ptr_eq == PointerEquality::AllowAll { if ptr_eq == PointerEquality::AllowAll {
if a.clone() if a.clone()
@ -650,6 +650,8 @@ impl Value {
b = b.force(&co, span.clone()).await?; b = b.force(&co, span.clone()).await?;
} }
let result = match (a, b) { let result = match (a, b) {
(Value::Catchable(c), _) => return Ok(Err(c)),
(_, Value::Catchable(c)) => return Ok(Err(c)),
// same types // same types
(Value::Integer(i1), Value::Integer(i2)) => i1.cmp(&i2), (Value::Integer(i1), Value::Integer(i2)) => i1.cmp(&i2),
(Value::Float(f1), Value::Float(f2)) => f1.total_cmp(&f2), (Value::Float(f1), Value::Float(f2)) => f1.total_cmp(&f2),
@ -682,7 +684,7 @@ impl Value {
} }
}; };
if result != Ordering::Equal { if result != Ordering::Equal {
return Ok(result); return Ok(Ok(result));
} }
} }
} }

View file

@ -44,7 +44,10 @@ macro_rules! cmp_op {
let b = generators::request_force(&co, b).await; let b = generators::request_force(&co, b).await;
let span = generators::request_span(&co).await; let span = generators::request_span(&co).await;
let ordering = a.nix_cmp_ordering(b, co, span).await?; let ordering = a.nix_cmp_ordering(b, co, span).await?;
Ok(Value::Bool(cmp_op!(@order $op ordering))) match ordering {
Err(cek) => Ok(Value::Catchable(cek)),
Ok(ordering) => Ok(Value::Bool(cmp_op!(@order $op ordering))),
}
} }
let gen_span = $frame.current_light_span(); let gen_span = $frame.current_light_span();