[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