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 <grfn@gws.fyi>
Tested-by: BuildkiteCI
This commit is contained in:
Vincent Ambo 2022-08-14 14:27:02 +03:00 committed by tazjin
parent 43658a5b90
commit 76846fe220
4 changed files with 14 additions and 4 deletions

View file

@ -0,0 +1 @@
[ false false false false ]

View file

@ -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) ]

View file

@ -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]"),
}

View file

@ -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) => {