[erlang-bugs] dialyzer false positive io_lib:fread

Kostis Sagonas <>
Sun Aug 11 00:20:05 CEST 2013

On 08/10/2013 07:11 AM, Chris King wrote:
> Hi,
> Re-sending this, as it seems (after a month checking the archive) that
> this mailing list silently rejects e-mails from non-subscribers?
> (There's no mention of this behavior in the listinfo page
> http://erlang.org/mailman/listinfo/erlang-bugs.)
> dialyzer produces a false positive when analyzing io_lib:fread with a ~a
> argument – it believes (erroneously) that the parsed value will be a
> string, when in fact it will be an atom.  This does not occur with
> io:fread, or with io_lib:fread with an integer argument.
> The below test program exemplifies this; dialyzer claims that bugged/1
> cannot return, when in fact calling bugged("foo") returns normally in
> the interpreter.
> I would be glad to supply a patch but I haven't the slightest clue where
> to start looking (this seems like either an easy fix, in an "exceptions"
> list somewhere, or a complex fix deep inside dialyzer).

The behaviour you are experiencing is a side-effect of the type and spec 
declarations that exist in modules io_lib and io_lib_fread (*)

(*) Aside: is there a really good reason why io_lib_fread is a separate 
module with cyclic dependencies to io_lib and polluting the module name 
space, instead of being part of io_lib?

In io_lib, the fread/2 function is defined as:

fread(Chars, Format) ->
     io_lib_fread:fread(Chars, Format).

and in io_lib_fread the spec of fread/2 reads:

-spec fread(Format, String) -> Result when
       Format :: string(),
       String :: string(),
       Result :: {'ok', InputList :: io_lib:chars(), LeftOverChars :: 

where the io_lib:chars() type is defined as:

-type chars() :: [char() | chars()].

mentioning nowhere that the InputList also possibly contains atoms 
instead of just chars(), i.e. short integers.

Note that the fact that the spec of io_lib:fread/2 reads:

-spec fread(Format, String) -> Result when
       Format :: string(),
       String :: string(),
       Result :: {'ok', InputList :: [term()], LeftOverChars :: string()}

is irrelevant since dialyzer will take the strongest type information it 
infers when spec declarations are too loose.

Anyway, I am not sure whether the intention of the library developer is 
to document the possibility to return an atom list or not in that 
position, so no patch from me either.

Hope this helps someone at OTP to fix this, possibly also folding the 
io_lib_fread module into io_lib the process.


More information about the erlang-bugs mailing list