aronisstav/otp

Inconsistency between dialyzer's results when a module is in the PLT vs when it is included in the analysis

Opened this issue · 3 comments

On Friday, June 17, 2016 @kostis reported to @aronisstav and @uabboli an inconsistency between dialyzer's results when a module is in the plt vs when it is included in the analysis, detected when working with a branch that

"is essentially the current [no longer] 'master' which also adds some type declarations in the records of 'core_parse.hrl' and then uses these types in 'cerl.erl'. These two are the only files that differ. I am pretty sure all these type declarations are correct, but even if they are not, it is besides the point of the following."

I have rebased his branch on top of OTP-19.0 and pushed it at aronisstav/core_parse-types (currently at 6e5cd3f).

After some preliminary minimization, to see the issue follow these steps:

$ dialyzer --build_plt lib/hipe/ebin/erl_*types.beam lib/compiler/ebin/cerl.beam --apps stdlib
[...]
$ dialyzer --apps dialyzer
[...]
dialyzer_dataflow.erl:237: The pattern 'true' can never match the type 'false'
dialyzer_dataflow.erl:1265: The pattern 'true' can never match the type 'false'
dialyzer_dataflow.erl:3039: Function state__renew_race_list/3 has no local return
dialyzer_dataflow.erl:3041: The attempt to match a term of type dialyzer_races:races() against the variable _ breaks the opaqueness of the term
[...]
$ dialyzer --apps dialyzer stdlib
[...]
dialyzer_dataflow.erl:237: The pattern 'true' can never match the type 'false'
dialyzer_dataflow.erl:1265: The pattern 'true' can never match the type 'false'
dialyzer_dataflow.erl:3039: Function state__renew_race_list/3 has no local return
dialyzer_dataflow.erl:3041: The attempt to match a term of type dialyzer_races:races() against the variable _ breaks the opaqueness of the term
dialyzer_races.erl:208: The attempt to match a term of type dialyzer_dataflow:state() against the variable CleanState breaks the opaqueness of the term
dialyzer_races.erl:222: The attempt to match a term of type dialyzer_dataflow:state() against the variable CleanState breaks the opaqueness of the term
dialyzer_races.erl:248: The attempt to match a term of type dialyzer_dataflow:state() against the variable CleanState breaks the opaqueness of the term
dialyzer_races.erl:2375: The call dialyzer_dataflow:format_args(Args::['bypassed' | 'no_arg' | {'c_binary' | 'c_catch' | 'c_literal' | 'c_tuple' | 'c_values' | 'c_var',[any()],_} | {'c_alias' | 'c_apply' | 'c_case' | 'c_cons' | 'c_fun' | 'c_letrec' | 'c_primop' | 'c_seq',[any()],_,_} | {'c_call' | 'c_clause' | 'c_let' | 'c_map' | 'c_map_pair' | 'c_receive',_,_,_,_} | {'c_module',[any()],{'c_literal',[any()],atom() | bitstring() | [atom() | bitstring() | [any()] | number() | tuple() | map()] | number() | tuple() | map()},[{'c_var',[any()],atom() | integer() | {atom(),byte()}}],[{{'c_literal',[any()],atom() | bitstring() | [atom() | bitstring() | [any()] | number() | tuple() | map()] | number() | tuple() | map()},{'c_literal',[any()],atom() | bitstring() | [atom() | bitstring() | [any()] | number() | tuple() | map()] | number() | tuple() | map()}}],[{{'c_var',[any()],atom() | integer() | {atom(),byte()}},{'c_fun',[any()],[{'c_var',[any()],atom() | integer() | {atom(),byte()}}],_}}]} | {'c_bitstr',_,_,_,_,_,_} | {'c_try',_,_,_,_,_,_}],ArgTypes::[erl_types:erl_type()],State::dialyzer_dataflow:state()) does not have an opaque term of type dialyzer_dataflow:state() as 3rd argument
[...]

Since stdlib is included in the PLT, there shouldn't be a difference in the warnings one gets for dialyzer's files.

I am currently working on minimizing this further, by including less modules from stdlib.

Currently working with this PLT:

$ dialyzer --build_plt lib/hipe/ebin/erl_*types.beam lib/compiler/ebin/cerl.beam

And running dialyzer like:

$ dialyzer lib/dialyzer/ebin/dialyzer_{dataflow,races}.beam lib/stdlib/ebin/<some>.beam

If <some> is * then the second sets of warnings comes up. Now trying to trigger it with less.

Smallest set that produces the warnings:

$ dialyzer lib/dialyzer/ebin/dialyzer_{dataflow,races}.beam lib/stdlib/ebin/{dict,erl_parse,erl_anno}.beam

Reproduced original issue with smaller PLT:

$ dialyzer --build_plt lib/hipe/ebin/erl_*types.beam lib/compiler/ebin/cerl.beam lib/stdlib/ebin/{dict,erl_parse,erl_anno}.beam
[...]
$ dialyzer lib/dialyzer/ebin/dialyzer_{dataflow,races}.beam
[...]
dialyzer_dataflow.erl:237: The pattern 'true' can never match the type 'false'
dialyzer_dataflow.erl:1265: The pattern 'true' can never match the type 'false'
dialyzer_dataflow.erl:3039: Function state__renew_race_list/3 has no local return
dialyzer_dataflow.erl:3041: The attempt to match a term of type dialyzer_races:races() against the variable _ breaks the opaqueness of the term
[...]
$ dialyzer lib/dialyzer/ebin/dialyzer_{dataflow,races}.beam lib/stdlib/ebin/erl_anno.beam
[...]
dialyzer_dataflow.erl:237: The pattern 'true' can never match the type 'false'
dialyzer_dataflow.erl:1265: The pattern 'true' can never match the type 'false'
dialyzer_dataflow.erl:3039: Function state__renew_race_list/3 has no local return
dialyzer_dataflow.erl:3041: The attempt to match a term of type dialyzer_races:races() against the variable _ breaks the opaqueness of the term
dialyzer_races.erl:208: The attempt to match a term of type dialyzer_dataflow:state() against the variable CleanState breaks the opaqueness of the term
dialyzer_races.erl:222: The attempt to match a term of type dialyzer_dataflow:state() against the variable CleanState breaks the opaqueness of the term
dialyzer_races.erl:248: The attempt to match a term of type dialyzer_dataflow:state() against the variable CleanState breaks the opaqueness of the term
dialyzer_races.erl:2375: The call dialyzer_dataflow:format_args(Args::['bypassed' | 'no_arg' | {'c_binary' | 'c_catch' | 'c_literal' | 'c_tuple' | 'c_values' | 'c_var',[any()],_} | {'c_alias' | 'c_apply' | 'c_case' | 'c_cons' | 'c_fun' | 'c_letrec' | 'c_primop' | 'c_seq',[any()],_,_} | {'c_call' | 'c_clause' | 'c_let' | 'c_map' | 'c_map_pair' | 'c_receive',_,_,_,_} | {'c_module',[any()],{'c_literal',[any()],atom() | bitstring() | [atom() | bitstring() | [any()] | number() | tuple() | map()] | number() | tuple() | map()},[{'c_var',[any()],atom() | integer() | {atom(),byte()}}],[{{'c_literal',[any()],atom() | bitstring() | [atom() | bitstring() | [any()] | number() | tuple() | map()] | number() | tuple() | map()},{'c_literal',[any()],atom() | bitstring() | [atom() | bitstring() | [any()] | number() | tuple() | map()] | number() | tuple() | map()}}],[{{'c_var',[any()],atom() | integer() | {atom(),byte()}},{'c_fun',[any()],[{'c_var',[any()],atom() | integer() | {atom(),byte()}}],_}}]} | {'c_bitstr',_,_,_,_,_,_} | {'c_try',_,_,_,_,_,_}],ArgTypes::[erl_types:erl_type()],State::dialyzer_dataflow:state()) does not have an opaque term of type dialyzer_dataflow:state() as 3rd argument
[...]

Notice that for the full set to appear only erl_anno.beam needs to be analyzed together with dialyzer's files.