tvix: miscompilation in recursive formals
#255
Opened by tazjin at
Recursive formals that capture their siblings through deferred upvalues can be miscompiled, for example:
tvix-repl> ({ b ? !a, a }: b) { a = true; } error[E006]: expected value of type 'bool', but found a 'internal[deferred_upvalue]' --> [code]:1:8 | 1 | ({ b ? !a, a }: b) { a = true; } | ^^
This is compiled as such (note that this is on top of the generator chain, hence OpReturn
is present):
=== compiled thunk @ 0x55ffb46f7170 (4 ops) === 0x0 1 OpConstant("a"@0) 0x1 | OpConstant(true@1) 0x2 | OpAttrs(Count(1)) 0x3 | OpReturn === compiled thunk @ 0x55ffb46fde90 (2 ops) === 0x0 1 OpGetUpvalue(UpvalueIdx(0)) 0x1 | OpReturn === compiled lambda @ 0x55ffb46fe4b0 (18 ops) === 0x0 1 OpForce 0x1 | OpValidateClosedFormals 0x2 | OpGetLocal(StackIdx(0)) 0x3 | OpConstant("b"@0) 0x4 | OpAttrsTrySelect 0x5 | OpJumpIfNotFound(JumpOffset(1)) 0x6 | OpJump(JumpOffset(4)) 0x7 | OpThunkSuspended(ConstantIdx(1)) 0x8 | DataDeferredLocal(StackIdx(2)) 0x9 | OpForce 0xa | OpInvert 0xb | OpGetLocal(StackIdx(0)) 0xc | OpConstant("a"@2) 0xd | OpAttrsSelect 0xe | OpFinalise(StackIdx(1)) 0xf | OpGetLocal(StackIdx(1)) 0x10 | OpCloseScope(Count(3)) 0x11 | OpReturn === compiled thunk @ 0x55ffb46fad00 (5 ops) === 0x0 1 OpConstant(thunk(0x55ffb46f7170)@0) 0x1 | OpConstant(closure(0x55ffb46fe4b0)@1) 0x2 | OpForce 0x3 | OpCall 0x4 | OpReturn === compiled toplevel @ 0x55ffb46faf80 (3 ops) === 0x0 1 OpConstant(thunk(0x55ffb46fad00)@0) 0x1 | OpForce 0x2 | OpReturn
The large lambda in the middle has an issue between 0x5 and 0x9: Something about the jump being issued before we emit finaliser instructions upsets the balance. Need to investigate.
Interesting discovery about this:
tvix-repl> ({ b ? a * a, a }: b) { a = 2; } => 4 :: int
but
tvix-repl> ({ b ? !a, a }: b) { a = true; } error[E006]: expected value of type 'bool', but found a 'internal[deferred_upvalue]'
and
error[E006]: expected value of type 'number (either int or float)', but found a 'internal[deferred_upvalue]' --> [code]:1:8 | 1 | ({ b ? -a, a }: b) { a = 2; } | ^^
It only happens on unary operators? :thonking:
tazjin at 2023-03-03T07·12+00
Fixed in cl/8196
tazjin at 2023-03-03T08·04+00
- tazjin closed this issue at 2023-03-14T09·18+00