diff options
author | Ryan Lahfa <tvl@lahfa.xyz> | 2023-12-25T23·39+0100 |
---|---|---|
committer | clbot <clbot@tvl.fyi> | 2023-12-29T22·00+0000 |
commit | 3e63d7be42c57f9724dcf5ff2ff3121ceb428f00 (patch) | |
tree | 128db7366ba199d20f1437fb5752a2dcd39bbd7d /tvix/eval/src/value/mod.rs | |
parent | 343ee0de57c4d44e6f4ac725eca7e7c4c34eab0d (diff) |
feat(tvix/eval): context-aware casting to strings r/7282
By default, we don't want contextful strings and we almost always want contextless strings. To this end, we make taking a contextful string a very explicit operation under `to_contextful_str` and we implement manually the `to_str` cast which requires a `if !s.has_context()` guard that the macro cannot cover. Change-Id: I7aae8e57a7d73e547e62b1edb0b1cc7e8c0c69b6 Reviewed-on: https://cl.tvl.fyi/c/depot/+/10425 Autosubmit: raitobezarius <tvl@lahfa.xyz> Reviewed-by: tazjin <tazjin@tvl.su> Tested-by: BuildkiteCI
Diffstat (limited to 'tvix/eval/src/value/mod.rs')
-rw-r--r-- | tvix/eval/src/value/mod.rs | 25 |
1 files changed, 23 insertions, 2 deletions
diff --git a/tvix/eval/src/value/mod.rs b/tvix/eval/src/value/mod.rs index 2eb382d0db74..16eb2a66b3fb 100644 --- a/tvix/eval/src/value/mod.rs +++ b/tvix/eval/src/value/mod.rs @@ -662,7 +662,27 @@ impl Value { gen_cast!(as_bool, bool, "bool", Value::Bool(b), *b); gen_cast!(as_int, i64, "int", Value::Integer(x), *x); gen_cast!(as_float, f64, "float", Value::Float(x), *x); - gen_cast!(to_str, NixString, "string", Value::String(s), s.clone()); + + /// Cast the current value into a **context-less** string. + /// If you wanted to cast it into a potentially contextful string, + /// you have to explicitly use `to_contextful_str`. + /// Contextful strings are special, they should not be obtained + /// everytime you want a string. + pub fn to_str(&self) -> Result<NixString, ErrorKind> { + match self { + Value::String(s) if !s.has_context() => Ok(s.clone()), + Value::Thunk(thunk) => Self::to_str(&thunk.value()), + other => Err(type_error("contextless strings", other)), + } + } + + gen_cast!( + to_contextful_str, + NixString, + "contextful string", + Value::String(s), + s.clone() + ); gen_cast!(to_path, Box<PathBuf>, "path", Value::Path(p), p.clone()); gen_cast!(to_attrs, Box<NixAttrs>, "set", Value::Attrs(a), a.clone()); gen_cast!(to_list, NixList, "list", Value::List(l), l.clone()); @@ -790,7 +810,8 @@ impl Value { Value::Bool(b) => format!("the boolean value '{}'", b), Value::Integer(i) => format!("the integer '{}'", i), Value::Float(f) => format!("the float '{}'", f), - Value::String(s) => format!("the string '{}'", s), + Value::String(s) if s.has_context() => format!("the contextful string '{}'", s), + Value::String(s) => format!("the contextless string '{}'", s), Value::Path(p) => format!("the path '{}'", p.to_string_lossy()), Value::Attrs(attrs) => format!("a {}-item attribute set", attrs.len()), Value::List(list) => format!("a {}-item list", list.len()), |