From 7606e62a2ffa5db2b47b0a31f5a4642f303eda12 Mon Sep 17 00:00:00 2001 From: Adam Joseph Date: Fri, 25 Nov 2022 16:47:26 -0800 Subject: feat(tvix/eval): add CoercionKind::ThunksOnly Signed-off-by: Adam Joseph Change-Id: I92acb7e6099a4796d953b2d4d02cca4076ed0fb1 Reviewed-on: https://cl.tvl.fyi/c/depot/+/7426 Reviewed-by: tazjin Tested-by: BuildkiteCI --- tvix/eval/src/errors.rs | 1 + tvix/eval/src/value/mod.rs | 15 +++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'tvix/eval/src') diff --git a/tvix/eval/src/errors.rs b/tvix/eval/src/errors.rs index ba9d6cb98ba6..107b8b154abd 100644 --- a/tvix/eval/src/errors.rs +++ b/tvix/eval/src/errors.rs @@ -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", }; diff --git a/tvix/eval/src/value/mod.rs b/tvix/eval/src/value/mod.rs index ffcb094eef5a..f0e3b84b9251 100644 --- a/tvix/eval/src/value/mod.rs +++ b/tvix/eval/src/value/mod.rs @@ -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(_), _) -- cgit 1.4.1