Fix reduce to preserve its input across init backtracking (#3633)
`reduce f as $x (init; update)` evaluated `f` against a stack slot
that forkpoints created while evaluating `init` restore. Both the
`DUPN` opening the reduction loop and the `LOADVN` retrieving the
result pop that slot destructively, nulling it out, so an `init`
that backtracks (e.g. `0, 0`) made `f` see `null` and fail with
"Cannot iterate over null".
Duplicate the input before the `FORK` instead of inside the loop,
and drop the leftover copy with `POP` once the loop is exhausted.
The slot left live at the `FORK` is then a block pushed after
`init` completed, which no earlier forkpoint can reach, so nulling
it is harmless. This is the same approach `gen_foreach` has used
since c70ae1a.
`DUPN` had no other user, so remove the opcode.
This commit is contained in:
1 parent
4beed4e01a
commit
df24981307
4 files changed
+10
-11
No files matched your search
+7
-1
@@ -2571,7 +2571,13 @@ try ["OK", setpath([[1]]; 1)] catch ["KO", .]
|
||||
[]
|
||||
["KO","Cannot update field at array index of array"]
|
||||
|
||||
# regression test for #3227
|
||||
# regression test for #3227 (reduce)
|
||||
[] | reduce .[] as $x (0, 1; .)
|
||||
null
|
||||
0
|
||||
1
|
||||
|
||||
# regression test for #3227 (foreach)
|
||||
foreach .[] as $x (0, 1; . + $x)
|
||||
[1, 2]
|
||||
1
|
||||
|
||||
Reference in new issue
Block a user