fix(tvix/eval): fix b/281 by adding Value::Catchable

This commit makes catchable errors a variant of Value.

The main downside of this approach is that we lose the ability to
use Rust's `?` syntax for propagating catchable errors.

Change-Id: Ibe89438d8a70dcec29e016df692b5bf88a5cad13
Reviewed-on: https://cl.tvl.fyi/c/depot/+/9289
Reviewed-by: tazjin <tazjin@tvl.su>
Autosubmit: Adam Joseph <adam@westernsemico.com>
Tested-by: BuildkiteCI
This commit is contained in:
Adam Joseph 2023-09-09 22:02:56 -07:00 committed by clbot
parent 926459ce69
commit 05f42519b5
16 changed files with 320 additions and 247 deletions

View file

@ -4,15 +4,18 @@
/// as there is internal Nix logic that must happen within the
/// serialisation methods.
use super::{CoercionKind, Value};
use crate::errors::{CatchableErrorKind, ErrorKind};
use crate::generators::{self, GenCo};
use crate::ErrorKind;
use serde_json::value::to_value;
use serde_json::Value as Json; // name clash with *our* `Value`
use serde_json::{Map, Number};
impl Value {
pub(crate) async fn to_json(self, co: &GenCo) -> Result<Json, ErrorKind> {
pub(crate) async fn to_json(
self,
co: &GenCo,
) -> Result<Result<Json, CatchableErrorKind>, ErrorKind> {
let self_forced = generators::request_force(co, self).await;
let value = match self_forced {
@ -42,14 +45,14 @@ impl Value {
// serialise to the string-coerced version of the result of
// calling that.
if let Some(s) = attrs.try_to_string(co, CoercionKind::Weak).await {
return Ok(Json::String(s.as_str().to_string()));
return Ok(Ok(Json::String(s.as_str().to_string())));
}
// Attribute sets with an `outPath` attribute
// serialise to a JSON serialisation of that inner
// value (regardless of what it is!).
if let Some(out_path) = attrs.select("outPath") {
return Ok(generators::request_to_json(co, out_path.clone()).await);
return Ok(Ok(generators::request_to_json(co, out_path.clone()).await));
}
let mut out = Map::with_capacity(attrs.len());
@ -63,6 +66,8 @@ impl Value {
Json::Object(out)
}
Value::Catchable(c) => return Ok(Err(c)),
val @ Value::Closure(_)
| val @ Value::Thunk(_)
| val @ Value::Builtin(_)
@ -76,12 +81,15 @@ impl Value {
}
};
Ok(value)
Ok(Ok(value))
}
/// Generator version of the above, which wraps responses in
/// Value::Json.
pub(crate) async fn to_json_generator(self, co: GenCo) -> Result<Value, ErrorKind> {
Ok(Value::Json(self.to_json(&co).await?))
match self.to_json(&co).await? {
Err(cek) => Ok(Value::Catchable(cek)),
Ok(json) => Ok(Value::Json(json)),
}
}
}