diff options
author | Vincent Ambo <mail@tazj.in> | 2022-08-28T03·07+0300 |
---|---|---|
committer | tazjin <tazjin@tvl.su> | 2022-09-06T07·45+0000 |
commit | 776120de05fc9f26d1af5da92d8b25ec26648365 (patch) | |
tree | 21e04f3aa6575e54d0cf4dd074a9536326502cf6 /tvix/eval/src/value | |
parent | ccfb971dc54cb77522d70f1ecbf1e9080e7ba0ca (diff) |
fix(tvix/eval): instantiate *new* closures from blueprints each time r/4659
The previous closure refactoring introduced a bug in which the same closure object would get mutated constantly for each instance of a closure, which is incorrect behaviour. This commit instead introduces an explicit new Value variant for the internal "blueprint" that the compiler generates (essentially just the lambda) and uses this variant to construct the closure at runtime. If the blueprint ever leaks out to a user somehow that is a critical bug and tvix-eval will panic. As a ~treat~ test for this, the fibonacci function is being used as it is a self-recursive closure (i.e. different instantiations of the same "blueprint") getting called with different values and it's good to have it around. Change-Id: I485de675e9bb0c599ed7d5dc0f001eb34ab4c15f Reviewed-on: https://cl.tvl.fyi/c/depot/+/6323 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
Diffstat (limited to 'tvix/eval/src/value')
-rw-r--r-- | tvix/eval/src/value/function.rs | 4 | ||||
-rw-r--r-- | tvix/eval/src/value/mod.rs | 9 |
2 files changed, 8 insertions, 5 deletions
diff --git a/tvix/eval/src/value/function.rs b/tvix/eval/src/value/function.rs index d0209cc50725..e5db43d58ace 100644 --- a/tvix/eval/src/value/function.rs +++ b/tvix/eval/src/value/function.rs @@ -29,7 +29,7 @@ impl Lambda { #[derive(Clone, Debug)] pub struct InnerClosure { - pub lambda: Lambda, + pub lambda: Rc<Lambda>, pub upvalues: Vec<Value>, } @@ -38,7 +38,7 @@ pub struct InnerClosure { pub struct Closure(Rc<RefCell<InnerClosure>>); impl Closure { - pub fn new(lambda: Lambda) -> Self { + pub fn new(lambda: Rc<Lambda>) -> Self { Closure(Rc::new(RefCell::new(InnerClosure { upvalues: Vec::with_capacity(lambda.upvalue_count), lambda, diff --git a/tvix/eval/src/value/mod.rs b/tvix/eval/src/value/mod.rs index 54211e8ba313..911af9d6ae12 100644 --- a/tvix/eval/src/value/mod.rs +++ b/tvix/eval/src/value/mod.rs @@ -35,6 +35,7 @@ pub enum Value { AttrPath(Vec<NixString>), AttrNotFound, DynamicUpvalueMissing(NixString), + Blueprint(Rc<Lambda>), } impl Value { @@ -55,9 +56,10 @@ impl Value { Value::Closure(_) | Value::Builtin(_) => "lambda", // Internal types - Value::AttrPath(_) | Value::AttrNotFound | Value::DynamicUpvalueMissing(_) => { - "internal" - } + Value::AttrPath(_) + | Value::AttrNotFound + | Value::DynamicUpvalueMissing(_) + | Value::Blueprint(_) => "internal", } } @@ -166,6 +168,7 @@ impl Display for Value { // internal types Value::AttrPath(path) => write!(f, "internal[attrpath({})]", path.len()), Value::AttrNotFound => f.write_str("internal[not found]"), + Value::Blueprint(_) => f.write_str("internal[blueprint]"), Value::DynamicUpvalueMissing(name) => { write!(f, "internal[no_dyn_upvalue({name})]") } |