From 76846fe22032546661cdf8649b8f898fc36e5270 Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Sun, 14 Aug 2022 14:27:02 +0300 Subject: fix(tvix/eval): allow use of ? operator on non-set types Nix allows this, but always returns false. Tvix needs to do the same. Change-Id: Ic9eec90834a0d0969eea5316d5c25032d3691d94 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6209 Reviewed-by: grfn Tested-by: BuildkiteCI --- .../eval/src/tests/tvix_tests/eval-okay-contains-non-set.exp | 1 + .../eval/src/tests/tvix_tests/eval-okay-contains-non-set.nix | 3 +++ tvix/eval/src/value/mod.rs | 2 +- tvix/eval/src/vm.rs | 12 +++++++++--- 4 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 tvix/eval/src/tests/tvix_tests/eval-okay-contains-non-set.exp create mode 100644 tvix/eval/src/tests/tvix_tests/eval-okay-contains-non-set.nix diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-contains-non-set.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-contains-non-set.exp new file mode 100644 index 000000000000..ca00e3c049d6 --- /dev/null +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-contains-non-set.exp @@ -0,0 +1 @@ +[ false false false false ] diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-contains-non-set.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-contains-non-set.nix new file mode 100644 index 000000000000..c086759f456b --- /dev/null +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-contains-non-set.nix @@ -0,0 +1,3 @@ +# Nix allows using the ? operator on non-set types, in which case it +# should always return false. +[ (123 ? key) ("foo" ? key) (null ? key) ([ "key" ] ? key) ] diff --git a/tvix/eval/src/value/mod.rs b/tvix/eval/src/value/mod.rs index 46021a167b27..f0cc86eedac4 100644 --- a/tvix/eval/src/value/mod.rs +++ b/tvix/eval/src/value/mod.rs @@ -116,7 +116,7 @@ impl Display for Value { } // internal types - Value::AttrPath(_) => f.write_str("internal[attrpath]"), + Value::AttrPath(path) => write!(f, "internal[attrpath({})]", path.len()), Value::Blackhole => f.write_str("internal[blackhole]"), Value::NotFound => f.write_str("internal[not found]"), } diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs index f96a5dcbddaf..d050fa807106 100644 --- a/tvix/eval/src/vm.rs +++ b/tvix/eval/src/vm.rs @@ -192,9 +192,15 @@ impl VM { OpCode::OpAttrsIsSet => { let key = self.pop().to_string()?; - let attrs = self.pop().to_attrs()?; - let result = Value::Bool(attrs.select(key.as_str()).is_some()); - self.push(result); + let result = match self.pop() { + Value::Attrs(attrs) => attrs.select(key.as_str()).is_some(), + + // Nix allows use of `?` on non-set types, but + // always returns false in those cases. + _ => false, + }; + + self.push(Value::Bool(result)); } OpCode::OpList(count) => { -- cgit 1.4.1