2

I have a function that intentionally throws when its first argument is the atom throw.

A simplified version of this code is:

-module(sample).

-export([main/1, throw_or_ok/1]).

main(_Args) ->
    throw_or_ok(throw).


throw_or_ok(Action) ->
    case Action of
        throw -> throw("throwing");
        ok -> ok
    end.

Dialyzer errors on the call to throw_or_ok:

sample.erl:7: The call sample:throw_or_ok
         ('throw') will never return since it differs in the 1st argument from the success typing arguments:
         ('ok')

Adding specs doesn't help, the error message is the same:

-module(sample).

-export([main/1, throw_or_ok/1]).

-spec main(_) -> no_return().
main(_Args) ->
    throw_or_ok(throw).

-spec throw_or_ok(throw) -> no_return(); (ok) -> ok.
throw_or_ok(Action) ->
    case Action of
        throw -> throw("throwing");
        ok -> ok
    end.

How can I get Dialyzer to accept calls to throw_or_ok/1 that are guaranteed to throw?

legoscia
  • 39,593
  • 22
  • 116
  • 167
Max Heiber
  • 14,346
  • 12
  • 59
  • 97

2 Answers2

0

Unfortunately there is currently no clean way to mark this as acceptable for Dialyzer via specs.

Perhaps you can use an ignore warning annotation, however.

aronisstav
  • 7,755
  • 5
  • 23
  • 48
0

Looks like if will put throw it will never return, if will put ok the pattern will never match with throw. See topic with similar issue. The logic of main/1 need to change, eg:

main(Args) ->
    MaybeOk = case Args of
        0 -> throw;
        _ -> ok
    end,
    throw_or_ok(MaybeOk).

OR

main(_Args) ->
    throw_or_ok(_Args).
vkatsuba
  • 1,411
  • 1
  • 7
  • 19