Skip to content

Wierd Mapfoldl behaviour #10354

@GGbree

Description

@GGbree

Describe the bug
If you consider the module

-module(test_bug).

-export([test/0]).

test() ->
    List = [{key,[{number,1}]}],
    {_, FinalAcc} =
        lists:mapfoldl(
            fun({_, PropListItem}, Acc) ->
                Number = proplists:get_value(number, PropListItem),
                case Number > 0 of
                    true ->
                        {false, Acc ++ [expected_result]};
                    _ ->
                        {true, Acc}
                end
            end, [], List),
    hd(FinalAcc).

what I would expect to return is the atom expected_result and indeed if you run it dynamically that's the result

1> List = [{key,[{number,1}]}],
       {_, FinalAcc} =
           lists:mapfoldl(
               fun({_, PropListItem}, Acc) ->
                   Number = proplists:get_value(number, PropListItem),
                   case Number > 0 of
                       true ->
                           {false, Acc ++ [expected_result]};
                       _ ->
                           {true, Acc}
                   end
               end, [], List),
       hd(FinalAcc).
expected_result

However if you compile the module and run it comes out something completely different.

1> compile:file("test_bug.erl").
{ok,test_bug}
2> test_bug:test().
{[false],[expected_result]}

It seems to be related to the usage of mapfoldl (if you change it for foldl it works correctly) and the usage of the atoms true and false inside. Analysing the generated bytecode with beam_disasm:file/1 the function abruply stops after the mapfoldl return, and any instruction after gets discarded.

To Reproduce
Create the module

-module(test_bug).

-export([test/0]).

test() ->
    List = [{key,[{number,1}]}],
    {_, FinalAcc} =
        lists:mapfoldl(
            fun({_, PropListItem}, Acc) ->
                Number = proplists:get_value(number, PropListItem),
                case Number > 0 of
                    true ->
                        {false, Acc ++ [expected_result]};
                    _ ->
                        {true, Acc}
                end
            end, [], List),
    hd(FinalAcc).

compile it and use the test/0 function

1> compile:file("test_bug.erl").
{ok,test_bug}
2> test_bug:test().
{[false],[expected_result]}

Expected behavior
The function provided should return expected_result

Affected versions
In OTP 25.x it works correctly, in OTP 26.0 it does not work.

Additional context
I would have loved to come up with a PR myself but I am missing too much knowledge.

Metadata

Metadata

Assignees

Labels

bugIssue is reported as a bugteam:VMAssigned to OTP team VM

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions