fix(tvix/eval): correctly account for slots during list construction

Similarly to attribute sets, list elements can be arbitrary
expressions and their (temporary) stack slots during construction must
be accounted for by the compiler.

Change-Id: I3b6f7927860627fd867c64d0cab9104fd636d4f5
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6470
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
This commit is contained in:
Vincent Ambo 2022-09-06 20:43:49 +03:00 committed by tazjin
parent 33059de431
commit fd14eefed6
3 changed files with 32 additions and 1 deletions

View file

@ -443,12 +443,29 @@ impl Compiler<'_, '_> {
fn compile_list(&mut self, slot: LocalIdx, node: ast::List) {
let mut count = 0;
// Open a temporary scope to correctly account for stack items
// that exist during the construction.
self.begin_scope();
for item in node.items() {
// Start tracing new stack slots from the second list
// element onwards. The first list element is located in
// the stack slot of the list itself.
let item_slot = match count {
0 => slot,
_ => {
let item_span = self.span_for(&item);
self.scope_mut().declare_phantom(item_span, false)
}
};
count += 1;
self.compile(slot, item);
self.compile(item_slot, item);
self.scope_mut().mark_initialised(item_slot);
}
self.push_op(OpCode::OpList(Count(count)), &node);
self.scope_mut().end_scope();
}
/// Compiles inherited values in an attribute set. Inherited

View file

@ -0,0 +1 @@
[ 1 2 3 ]

View file

@ -0,0 +1,13 @@
# This code causes a situation where a list element causes an
# additional phantom value to temporarily be placed on the locals
# stack, which must be correctly accounted for by the compiler.
let
set = {
value = 2;
};
in [
1
(with set; value)
3
]