Skip to content

Commit 3f0e7c5

Browse files
author
José Valim
committed
Only consider outer halts in flat_map when the op is not halt itself
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
1 parent 49e7683 commit 3f0e7c5

File tree

2 files changed

+16
-2
lines changed

2 files changed

+16
-2
lines changed

lib/elixir/lib/stream.ex

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -699,9 +699,11 @@ defmodule Stream do
699699
next.({:halt, next_acc})
700700
:erlang.raise(kind, reason, stacktrace)
701701
else
702-
{:halted, [:outer|acc]} ->
702+
# Only take into account outer halts when the op is not halt itself.
703+
# Otherwise, we were the ones wishing to halt, so we should just stop.
704+
{:halted, [:outer|acc]} when op != :halt ->
703705
do_transform(user_acc, user, fun, next_acc, next, {:cont, acc}, inner)
704-
{:halted, [:inner|acc]} ->
706+
{:halted, [_|acc]} ->
705707
next.({:halt, next_acc})
706708
{:halted, acc}
707709
{:done, [_|acc]} ->

lib/elixir/test/elixir/stream_test.exs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,18 @@ defmodule StreamTest do
326326
assert Enum.take(stream, 5) == [1, 2, 3, 4, 3]
327327
end
328328

329+
test "flat_map/2 properly halts both inner and outer stream when inner stream is halted" do
330+
# Fixes a bug that, when the inner stream was done,
331+
# sending it a halt would cause it to return the
332+
# inner stream was halted, forcing flat_map to get
333+
# the next value from the outer stream, evaluate it,
334+
# get annother inner stream, just to halt it.
335+
assert [1, 2] # 2 should never be used
336+
|> Stream.flat_map(fn 1 -> Stream.repeatedly(fn -> 1 end) end)
337+
|> Stream.flat_map(fn 1 -> Stream.repeatedly(fn -> 1 end) end)
338+
|> Enum.take(1) == [1]
339+
end
340+
329341
test "interval/1" do
330342
stream = Stream.interval(10)
331343
now = :erlang.now

0 commit comments

Comments
 (0)