Skip to content

Commit 59ae101

Browse files
committed
Fix a bug with indirect produce calls in a loop
1 parent 3b2cca3 commit 59ae101

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

src/copyable_task.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ end
287287
fresh_copy(mc::T) where {T<:MistyClosure}
288288
289289
Creates an independent copy of `mc` by (carefully) replacing the `Ref`s it
290-
contains it its `captures`. The resuting `MistyClosure` is safe to run.
290+
contains in its `captures`. The resuting `MistyClosure` is safe to run.
291291
292292
This is achieved by replacing most `Ref`s with new `Ref`s of the same (el)type,
293293
but with nothing stored in them -- values will be stored in them when the
@@ -830,6 +830,10 @@ function derive_copyable_task_ir(ir::BBCode)::Tuple{BBCode,Tuple,Vector{Any}}
830830
# terminator. We handle this in a similar way to the statements above.
831831

832832
if stmt isa ReturnNode
833+
# Reset the position counter to `-1`, so that if this function gets
834+
# called again, execution starts from the beginning.
835+
expr = Expr(:call, set_resume_block!, refs_id, Int32(-1))
836+
push!(inst_pairs, (ID(), new_inst(expr)))
833837
# If returning an SSA, it might be one whose value was restored from
834838
# before. Therefore, grab it out of storage, rather than assuming that
835839
# it is def-ed.

test/copyable_task.jl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,4 +220,27 @@
220220
g() = produce(rand() > -1.0 ? 2 : 0.1)
221221
@test Libtask.consume(Libtask.TapedTask(nothing, g)) == 2
222222
end
223+
224+
@testset "Indirect produce in a loop" begin
225+
# Test that we can wrap a `produce` call in another function, and call that function
226+
# in a loop. This used to only produce some of the values, see
227+
# https://github.com/TuringLang/Libtask.jl/issues/190.
228+
produce_wrapper(x) = (Libtask.produce(x); return nothing)
229+
Libtask.might_produce(::Type{<:Tuple{typeof(produce_wrapper),Any}}) = true
230+
function f(obs)
231+
for o in obs
232+
produce_wrapper(o)
233+
end
234+
return nothing
235+
end
236+
237+
# That the eltype of vals is Any is significant for reproducing the original bug.
238+
# Unclear why.
239+
vals = Any[:a, :b, :c]
240+
tt = Libtask.TapedTask(nothing, f, vals)
241+
@test Libtask.consume(tt) === :a
242+
@test Libtask.consume(tt) === :b
243+
@test Libtask.consume(tt) === :c
244+
@test Libtask.consume(tt) === nothing
245+
end
223246
end

0 commit comments

Comments
 (0)