diff options
author | Vincent Ambo <mail@tazj.in> | 2022-08-14T11·34+0300 |
---|---|---|
committer | tazjin <tazjin@tvl.su> | 2022-08-30T17·13+0000 |
commit | cfe37d36f7977f93dd5b8441d691811bf2b6997b (patch) | |
tree | 761bb85c7b333e6d6739490a7e6f655c7c098ace | |
parent | 76846fe22032546661cdf8649b8f898fc36e5270 (diff) |
fix(tvix/eval): `or` should handle non-attrset values, too r/4543
If a nested attrpath encounters a non-set value, the sentinel value denoting a lack of next values should be emitted. This mirrors the behaviour of Nix. Change-Id: Ia80443d5a11243cc6d98dcab1249a3f5fdf77e27 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6210 Reviewed-by: grfn <grfn@gws.fyi> Tested-by: BuildkiteCI
-rw-r--r-- | tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-non-set.exp | 1 | ||||
-rw-r--r-- | tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-non-set.nix | 2 | ||||
-rw-r--r-- | tvix/eval/src/vm.rs | 14 |
3 files changed, 12 insertions, 5 deletions
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-non-set.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-non-set.exp new file mode 100644 index 000000000000..a833e32892e4 --- /dev/null +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-non-set.exp @@ -0,0 +1 @@ +"works fine" diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-non-set.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-non-set.nix new file mode 100644 index 000000000000..fd09bfee64c2 --- /dev/null +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-non-set.nix @@ -0,0 +1,2 @@ +# `or` operator should keep working if it encounters a non-set type. +{ a.b = 42; }.a.b.c or "works fine" diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs index d050fa807106..d18cd7977bbe 100644 --- a/tvix/eval/src/vm.rs +++ b/tvix/eval/src/vm.rs @@ -182,12 +182,16 @@ impl VM { OpCode::OpAttrOrNotFound => { let key = self.pop().to_string()?; - let attrs = self.pop().to_attrs()?; + let value = match self.pop() { + Value::Attrs(attrs) => match attrs.select(key.as_str()) { + Some(value) => value.clone(), + None => Value::NotFound, + }, - match attrs.select(key.as_str()) { - Some(value) => self.push(value.clone()), - None => self.push(Value::NotFound), - } + _ => Value::NotFound, + }; + + self.push(value); } OpCode::OpAttrsIsSet => { |