diff options
author | Aspen Smith <root@gws.fyi> | 2024-02-09T17·59-0500 |
---|---|---|
committer | aspen <root@gws.fyi> | 2024-02-09T19·11+0000 |
commit | 3fb0697a713cdd5b0c22b3c511419ba3a281746a (patch) | |
tree | 4cc88884ea59a3da8d9fcfcdf7e1110757b260d0 /tvix/eval/src/value/attrs.rs | |
parent | 7a589b3ec67e49edc6de1d3378db1c4c594210f1 (diff) |
fix(tvix/eval): Propagate catchables in NixAttrs::construct r/7492
Correctly propagate the case where the *key* of an attrset is a Value::Catchable (eg { "${builtins.throw "c"}" = "b"; }) in `NixAttrs::construct`, by converting the return type to `Result<Result<Self, CatchableErrorKind>, ErrorKind>` (ugh!!) and correctly handling that everywhere (including an `expect` in the Deserialize impl for NixAttrs, since afaict this is impossible to hit when deserializing from stuff like JSON). Change-Id: Ic4bc611fbfdab27c0bd8a40759689a87c4004a17 Reviewed-on: https://cl.tvl.fyi/c/depot/+/10786 Reviewed-by: raitobezarius <tvl@lahfa.xyz> Tested-by: BuildkiteCI
Diffstat (limited to 'tvix/eval/src/value/attrs.rs')
-rw-r--r-- | tvix/eval/src/value/attrs.rs | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/tvix/eval/src/value/attrs.rs b/tvix/eval/src/value/attrs.rs index 6fd43e064cf2..23a2acb0b9a4 100644 --- a/tvix/eval/src/value/attrs.rs +++ b/tvix/eval/src/value/attrs.rs @@ -19,6 +19,7 @@ use super::thunk::ThunkSet; use super::TotalDisplay; use super::Value; use crate::errors::ErrorKind; +use crate::CatchableErrorKind; lazy_static! { static ref NAME_S: NixString = "name".into(); @@ -170,7 +171,9 @@ impl<'de> Deserialize<'de> for NixAttrs { stack_array.push(value); } - NixAttrs::construct(stack_array.len() / 2, stack_array).map_err(A::Error::custom) + Ok(NixAttrs::construct(stack_array.len() / 2, stack_array) + .map_err(A::Error::custom)? + .expect("Catchable values are unreachable here")) } } @@ -333,7 +336,10 @@ impl NixAttrs { /// Implement construction logic of an attribute set, to encapsulate /// logic about attribute set optimisations inside of this module. - pub fn construct(count: usize, mut stack_slice: Vec<Value>) -> Result<Self, ErrorKind> { + pub fn construct( + count: usize, + mut stack_slice: Vec<Value>, + ) -> Result<Result<Self, CatchableErrorKind>, ErrorKind> { debug_assert!( stack_slice.len() == count * 2, "construct_attrs called with count == {}, but slice.len() == {}", @@ -343,13 +349,13 @@ impl NixAttrs { // Optimisation: Empty attribute set if count == 0 { - return Ok(NixAttrs(AttrsRep::Empty)); + return Ok(Ok(NixAttrs(AttrsRep::Empty))); } // Optimisation: KV pattern if count == 2 { if let Some(kv) = attempt_optimise_kv(&mut stack_slice) { - return Ok(kv); + return Ok(Ok(kv)); } } @@ -369,11 +375,13 @@ impl NixAttrs { continue; } + Value::Catchable(err) => return Ok(Err(err)), + other => return Err(ErrorKind::InvalidAttributeName(other)), } } - Ok(attrs) + Ok(Ok(attrs)) } /// Construct an optimized "KV"-style attribute set given the value for the |