Say I have a function,foo/1
, whose spec is -spec foo(atom()) -> #r{}.
, where #r{}
is a record defined as -record(r, {a :: 1..789}).
, however, I have foo(a) -> 800.
in my code, when I run dialyzer against it, it didn't warn me about this, (800
is not a "valid" return value for function foo/1
), can I make dialyzer warn me about this?
Edit
Learn You Some Erlang says:
Dialyzer reserves the right to expand this range into a bigger one.
But I couldn't find how to disable this.
As of Erlang 18, the handling of integer ranges is done by
erl_types:t_from_range/2
. As you can see, there are a lot of generalizations happening to get a "safe" overapproximation of a range.If you tried to
?USE_UNSAFE_RANGES
(see the code) it is likely that your particular error would be caught, but at a terrible cost: native compilation and dialyzing of recursive integer functions would not ever finish!The reason is that the type analysis for recursive functions uses a simple fixpoint approach, where the initial types accept the base cases and are repeatedly expanded using the recursive cases to include more values. At some point overapproximations must happen if the process is to terminate. Here is a concrete example:
Initially
fact/1
is assumed to have typefun(none()) -> none()
. Using that to analyse the code, the second clause is 'failing' and only the first one is ok. Therefore after the first iteration the new type isfun(1) -> 1
. Using the new type the second clause can succeed, expanding the type tofun(1|2) -> 1|2
. Thenfun(1|2|3) -> 1|2|6
this continues until the?SET_LIMIT
is reached in which caset_from_range
stops using the individual values and type becomesfun(1..255) -> pos_integer()
. The next iteration expands1..255
topos_integer()
and thenfun(pos_integer()) -> pos_integer()
is a fixpoint!Incorrect answer follows (explains the first comment below):
You should get a warning for this code if you use the-Woverspecs
option. This option is not enabled by default, since Dialyzer operates under the assumption that it is 'ok' to over-approximate the return values of a function. In your particular case, however, you actually want any extra values to produce warnings.