Skip to content

Commit 2270d9a

Browse files
mhauruyebai
andauthored
Fix a bug with indirect produce calls in a loop (#192)
* Bump patch version to 0.9.3 * Fix a bug with indirect produce calls in a loop * Fix a typo in a docstring --------- Co-authored-by: Hong Ge <[email protected]>
1 parent 4d606eb commit 2270d9a

File tree

2 files changed

+25
-1
lines changed

2 files changed

+25
-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 resulting `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: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,26 @@
221221
@test Libtask.consume(Libtask.TapedTask(nothing, g)) == 2
222222
end
223223

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
224244
@testset "Return produce" begin
225245
# Test calling a function that does something with the return value of `produce`.
226246
# In this case it just returns it. This used to error, see

0 commit comments

Comments
 (0)