feat(tvix/eval): add CoercionKind::ThunksOnly

Signed-off-by: Adam Joseph <adam@westernsemico.com>
Change-Id: I92acb7e6099a4796d953b2d4d02cca4076ed0fb1
Reviewed-on: https://cl.tvl.fyi/c/depot/+/7426
Reviewed-by: tazjin <tazjin@tvl.su>
Tested-by: BuildkiteCI
This commit is contained in:
Adam Joseph 2022-11-25 16:47:26 -08:00 committed by clbot
parent bab6ae136f
commit 7606e62a2f
2 changed files with 12 additions and 4 deletions

View file

@ -293,6 +293,7 @@ to a missing value in the attribute set(s) included via `with`."#,
ErrorKind::NotCoercibleToString { kind, from } => {
let kindly = match kind {
CoercionKind::ThunksOnly => "thunksonly",
CoercionKind::Strong => "strongly",
CoercionKind::Weak => "weakly",
};

View file

@ -107,8 +107,10 @@ macro_rules! gen_is {
}
/// Describes what input types are allowed when coercing a `Value` to a string
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum CoercionKind {
/// Force thunks, but perform no other coercions.
ThunksOnly,
/// Only coerce already "stringly" types like strings and paths, but also
/// coerce sets that have a `__toString` attribute. Equivalent to
/// `!coerceMore` in C++ Nix.
@ -176,18 +178,21 @@ impl Value {
// coercions that are always done
(Value::String(s), _) => Ok(s.clone()),
// TODO(sterni): Think about proper encoding handling here. This needs
// general consideration anyways, since one current discrepancy between
// C++ Nix and Tvix is that the former's strings are arbitrary byte
// sequences without NUL bytes, whereas Tvix only allows valid
// Unicode. See also b/189.
(Value::Path(p), _) => Ok(p.to_string_lossy().into_owned().into()),
(Value::Path(p), kind) if kind != CoercionKind::ThunksOnly => {
Ok(p.to_string_lossy().into_owned().into())
}
// Attribute sets can be converted to strings if they either have an
// `__toString` attribute which holds a function that receives the
// set itself or an `outPath` attribute which should be a string.
// `__toString` is preferred.
(Value::Attrs(attrs), _) => {
(Value::Attrs(attrs), kind) if kind != CoercionKind::ThunksOnly => {
match (attrs.select("__toString"), attrs.select("outPath")) {
(None, None) => Err(ErrorKind::NotCoercibleToString { from: "set", kind }),
@ -250,7 +255,9 @@ impl Value {
.unwrap_or_else(|| Ok("".into()))
}
(Value::Closure(_), _)
(Value::Path(_), _)
| (Value::Attrs(_), _)
| (Value::Closure(_), _)
| (Value::Builtin(_), _)
| (Value::Null, _)
| (Value::Bool(_), _)