[erlang-bugs] Compiler bug with unsafe variables in nested try statements.

Paul Davis <>
Sun Jul 21 00:33:57 CEST 2013


I seem to have uncovered a bug when detecting or displaying "variable
'Acc' unsafe in 'try'" errors. I managed to reduce this to a fairly
small test case:

-module(bam).
-export([bang/0]).
bang() ->
    case 1 of
        nil ->
            Acc = 2;
        _ ->
            try
                Acc = 3,
                Acc
            catch _:_ ->
                ok
            end
    end,
    Acc.

The important point that I found is that its necessary to reference
Acc in the try body after its been bound. Without that the unsafe
error is generated properly.

The error I'm seeing is:

Function: bang/0
bam.erl:none: internal error in core_dsetel_module;
crash reason: {{badmatch,error},
               [{sys_core_dsetel,visit,2,
                                 [{file,"sys_core_dsetel.erl"},{line,98}]},
                {sys_core_dsetel,visit,2,
                                 [{file,"sys_core_dsetel.erl"},{line,117}]},
                {sys_core_dsetel,visit_module_1,3,
                                 [{file,"sys_core_dsetel.erl"},{line,79}]},
                {sys_core_dsetel,visit_module,1,
                                 [{file,"sys_core_dsetel.erl"},{line,75}]},
                {sys_core_dsetel,module,2,
                                 [{file,"sys_core_dsetel.erl"},{line,70}]},
                {compile,core_dsetel_module,1,
                         [{file,"compile.erl"},{line,1159}]},
                {compile,'-internal_comp/4-anonymous-1-',2,
                         [{file,"compile.erl"},{line,276}]},
                {compile,fold_comp,3,[{file,"compile.erl"},{line,294}]}]}

I discovered this on R14B01 but its still present on R16B01 as well.

Out of curiosity I also reproduced it with an if statement as well:

#!/usr/bin/env escript

-mode(compile).

main(_) ->
    Maybe = bar(),
    if Maybe ->
        Acc = 1;
    true ->
      try
          Acc = 2,
          Acc %, throw(foo)
      catch _ ->
        ok
      end
  end,
  erlang:display(Acc).

bar() -> false.

Somewhat fun is that if we comment out -mode(compile) for interpreted
mode we can get all three values (1, 2, unbound) of Acc by changing
bar/0 and/or uncommenting the throw statement.

Obviously my code is broken trying to reference a variable like that;
I was just a bit surprised to see a compiler error.


More information about the erlang-bugs mailing list