[erlang-questions] Understanding dialyzer errors better

Raghav Karol <>
Thu Mar 2 10:39:31 CET 2017


I spent a bit of time yesterday on some dialyzer warnings resulting from
the singleton type 'undefined' no longer automatically to record fields
types OTP-19. What threw me off were several related but hard to decipher
warnings.

Using OTP-19, `rebar3 dialyzer` on this commit
https://github.com/basho/bitcask/commit/cd74f59bfe47a39878d7a56a55ce0ae723723677
produces:

```
src/bitcask.erl
 197: The call
bitcask_fileops:close_for_writing(WriteFile::#filestate{mode::'read_only' |
'read_write' | 'undefined',filename::string(),tstamp::'undefined' |
integer(),fd::'undefined' |
port(),hintfd::port(),hintcrc::integer(),ofs::'undefined' |
non_neg_integer(),l_ofs::non_neg_integer(),l_hbytes::non_neg_integer(),l_hintcrc::non_neg_integer()})
will never return since it differs in the 1st argument from the success
typing arguments: ('fresh' | 'undefined')
 219: The call
bitcask_fileops:close_for_writing(WriteFile::#filestate{mode::'read_only' |
'read_write' | 'undefined',filename::string(),tstamp::'undefined' |
integer(),fd::'undefined' |
port(),hintfd::port(),hintcrc::integer(),ofs::'undefined' |
non_neg_integer(),l_ofs::non_neg_integer(),l_hbytes::non_neg_integer(),l_hintcrc::non_neg_integer()})
will never return since it differs in the 1st argument from the success
typing arguments: ('fresh' | 'undefined')
 520: The created fun has no local return
 529: The call bitcask_fileops:close(FD::{_,_,_,_,_,_,_,_,_,_,_}) will
never return since it differs in the 1st argument from the success typing
arguments: ('fresh' | 'undefined')
 717: The call
bitcask_fileops:close(Outfile::#filestate{mode::'read_write',filename::string(),tstamp::'undefined'
| integer(),fd::'undefined' |
port(),hintfd::port(),hintcrc::integer(),ofs::'undefined' |
non_neg_integer(),l_ofs::non_neg_integer(),l_hbytes::non_neg_integer(),l_hintcrc::non_neg_integer()})
will never return since it differs in the 1st argument from the success
typing arguments: ('fresh' | 'undefined')
 722: The call
bitcask_fileops:close(TFile::#filestate{mode::'read_write',filename::string(),tstamp::'undefined'
| integer(),fd::'undefined' |
port(),hintfd::port(),hintcrc::integer(),ofs::'undefined' |
non_neg_integer(),l_ofs::non_neg_integer(),l_hbytes::non_neg_integer(),l_hintcrc::non_neg_integer()})
will never return since it differs in the 1st argument from the success
typing arguments: ('fresh' | 'undefined')
 774: The call bitcask_fileops:close(F::#filestate{mode::'read_only' |
'read_write' | 'undefined',filename::[any()],tstamp::'undefined' |
integer(),fd::'undefined' |
port(),hintfd::port(),hintcrc::integer(),ofs::'undefined' |
non_neg_integer(),l_ofs::non_neg_integer(),l_hbytes::non_neg_integer(),l_hintcrc::non_neg_integer()})
will never return since it differs in the 1st argument from the success
typing arguments: ('fresh' | 'undefined')
1224: The call
bitcask_fileops:close(File::#filestate{mode::'read_write',filename::string(),tstamp::integer(),fd::'undefined'
| port(),hintfd::port(),hintcrc::non_neg_integer(),ofs::'undefined' |
non_neg_integer(),l_ofs::0,l_hbytes::0,l_hintcrc::0}) will never return
since it differs in the 1st argument from the success typing arguments:
('fresh' | 'undefined')
1719: The pattern <_Key, _Value, State, 0, LastErr> can never match the
type <_,_,#bc_state{dirname::string(),write_file::'fresh' | 'undefined' |
#filestate{mode::'read_only' | 'read_write' |
'undefined',filename::[any()],tstamp::'undefined' |
integer(),fd::'undefined' |
port(),hintfd::port(),hintcrc::integer(),ofs::'undefined' |
non_neg_integer(),l_ofs::non_neg_integer(),l_hbytes::non_neg_integer(),l_hintcrc::non_neg_integer()},write_lock::'undefined'
| reference(),read_files::'undefined' |
[{_,_,_,_,_,_,_,_,_,_,_}],max_file_size::'undefined' |
integer(),opts::'undefined' | [any()],key_transform::'undefined' |
fun(),keydir::reference(),read_write_p::'undefined' |
integer(),tombstone_version::0 | 2},100,'undefined'>
1870: Function wrap_write_file/1 has no local return
1924: Record construction
#filestate{filename::[any()],hintfd::'undefined',hintcrc::0,l_ofs::0,l_hbytes::0,l_hintcrc::0}
violates the declared type of field hintfd::port()

src/bitcask_fileops.erl
 166: Record construction #filestate{mode::'read_only',filename::string() |
#filestate{mode::'read_only' | 'read_write' |
'undefined',filename::string(),tstamp::'undefined' |
integer(),fd::'undefined' |
port(),hintfd::port(),hintcrc::integer(),ofs::'undefined' |
non_neg_integer(),l_ofs::non_neg_integer(),l_hbytes::non_neg_integer(),l_hintcrc::non_neg_integer()},tstamp::integer(),hintfd::'undefined',hintcrc::0,ofs::0,l_ofs::0,l_hbytes::0,l_hintcrc::0}
violates the declared type of field hintfd::port()
 240: Function close_hintfile/1 has no local return
 240: Matching of pattern {'filestate', _, _, _, _, 'undefined', _, _, _,
_, _} tagged with a record name violates the declared type of
#filestate{mode::'read_only' | 'read_write' |
'undefined',filename::string(),tstamp::'undefined' |
integer(),fd::'undefined' |
port(),hintfd::port(),hintcrc::integer(),ofs::'undefined' |
non_neg_integer(),l_ofs::non_neg_integer(),l_hbytes::non_neg_integer(),l_hintcrc::non_neg_integer()}
 251: Record construction #filestate{mode::'read_only' | 'read_write' |
'undefined',filename::string(),tstamp::'undefined' |
integer(),fd::'undefined' |
port(),hintfd::'undefined',hintcrc::0,ofs::'undefined' |
non_neg_integer(),l_ofs::non_neg_integer(),l_hbytes::non_neg_integer(),l_hintcrc::non_neg_integer()}
violates the declared type of field hintfd::port()
 314: The pattern 'undefined' can never match the type port()

src/bitcask_merge_delete.erl
 151: Record construction
#filestate{hintfd::'undefined',hintcrc::0,l_ofs::0,l_hbytes::0,l_hintcrc::0}
violates the declared type of field hintfd::port()
===> Warnings written to
/Users/raghav/github/riak_kv/deps/bitcask/_build/default/19.2.dialyzer_warnings
===> Warnings occured running dialyzer: 17
```

Particularly confusing, are errors like the first one

```
 197: The call
bitcask_fileops:close_for_writing(WriteFile::#filestate{mode::'read_only' |
'read_write' | 'undefined',filename::string(),tstamp::'undefined' |
integer(),fd::'undefined' |
port(),hintfd::port(),hintcrc::integer(),ofs::'undefined' |
non_neg_integer(),l_ofs::non_neg_integer(),l_hbytes::non_neg_integer(),l_hintcrc::non_neg_integer()})
will never return since it differs in the 1st argument from the success
typing arguments: ('fresh' | 'undefined')
```

I _think_ dialyzer is saying that the call
`bitcask_fileops:close_for_writing(WriteFile#filestate{}, ...)` is not
possible because of type violations when creating `#filestate{}` lower down
the call stack.

Would appreciate if someone could help understand this better and also
suggest how one separates noise from real warnings with dialyzer.

Best,
Raghav
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20170302/0f1505cf/attachment.html>


More information about the erlang-questions mailing list