[erlang-bugs] Dialyzer unmatched_returns generates false positives
Adam Lindberg
adam@REDACTED
Tue Apr 12 11:05:37 CEST 2011
Ah, I see.
How come dialyzer complains about the list comprehension and not the
lists:foreach/2 call? Is there any difference between them that warrants
the warning in one case but not the other?
As I see it, they still run my code in a sequence and I don't understand
why I would be more interested to match the return value in one case but
not the other.
Cheers,
Adam
Kostis Sagonas wrote:
> Adam Lindberg wrote:
>> Hi,
>>
>> Using the option unmatched_returns in dialyzer seems to generate false
>> positives inside list comprehensions. Consider the following code:
>>
>> f() -> ok.
>>
>> g() -> [f() || _E <- lists:seq(1,3)], ok.
>>
>> It generates the following warning:
>>
>> Expression produces a value of type ['ok'], but this value is unmatched.
>>
>> This is okay, because we don't actually match on the return from f().
>> I would think that the following fix removes the warning, but it does
>> not:
>>
>> g() -> [ok = f() || E <- lists:seq(1,3)], ok.
>>
>> For a list of variable length, the only alternative would be the
>> following (which dialyzer does not complain about):
>>
>> g() -> lists:all(fun(ok) -> true end, [ok = f() || _E <-
>> lists:seq(1,3)]), ok.
>>
>> But it doesn't have the same behavior (will generate a function clause
>> error instead of a badmatch error if something fails).
>
> You misunderstand both the warning and how to fix it. Dialyzer does not
> complain that the f() return is unmatched, but it complains that the
> return from the list comprehension is unmatched. Note that the warning
> does not say 'ok' but it says ['ok'] (i.e., that a list of 'ok' values
> is unmatched). And indeed it is as far as *Erlang* is concerned.
>
> Now, it's true that the BEAM compiler performs an optimization that does
> not construct this list, but this is not something that is reflected in
> the operational semantics of Erlang. Because dialyzer is based on Core
> Erlang and aims to be compiler independent (it's conceivable that in the
> future some other compiler may take the place of BEAM) it does not model
> its optimizations.
>
> Anyway, this is not a false positive. It's a bit unfortunate, but it's
> intentional. The proper way to write this in order not to get the
> dialyzer warning with unmatched return is to write the following:
>
> g() ->
> lists:foreach(fun(_E) -> f() end, lists:seq(1,3)),
> ok.
>
> If you want to write it with the list comprehension, the kosher way to
> write it is:
>
> g() ->
> _ = [f() || E <- lists:seq(1,3)],
> ok.
>
> Kostis
More information about the erlang-bugs
mailing list