diff options
author | Stavros Aronis <[email protected]> | 2011-01-03 15:07:55 +0200 |
---|---|---|
committer | Niclas Axelsson <[email protected]> | 2011-01-18 15:50:09 +0100 |
commit | 02e0f98ab537b002f2ccb1092d9e7310d9e15c58 (patch) | |
tree | 5b79d80f20e1965d50c1f189449fee4e76a9c151 | |
parent | 326ec4e6a86e7ddb7b49f2465ad43adf86399aac (diff) | |
download | otp-02e0f98ab537b002f2ccb1092d9e7310d9e15c58.tar.gz otp-02e0f98ab537b002f2ccb1092d9e7310d9e15c58.tar.bz2 otp-02e0f98ab537b002f2ccb1092d9e7310d9e15c58.zip |
Fix errors in the handling of 'and'/'or' guards
Apart from the obvious bug in the negative evaluation of an 'and'
guard, Dialyzer handled dont_know cases rather single-mindedly
towards the positive branch. This patch allows for negative results
as well and does some clever guesses to narrow them down. It was
constructed similarly to the handling of the 'not' guard.
-rw-r--r-- | lib/dialyzer/src/dialyzer_dataflow.erl | 47 |
1 files changed, 32 insertions, 15 deletions
diff --git a/lib/dialyzer/src/dialyzer_dataflow.erl b/lib/dialyzer/src/dialyzer_dataflow.erl index 0e51ce059c..1723380c8c 100644 --- a/lib/dialyzer/src/dialyzer_dataflow.erl +++ b/lib/dialyzer/src/dialyzer_dataflow.erl @@ -2250,24 +2250,30 @@ handle_guard_and(Guard, Map, Env, Eval, State) -> catch throw:{fail, _} -> bind_guard(Arg2, Map, Env, pos, State) end, {Map2, Type2} = - try bind_guard(Arg1, Map, Env, neg, State) - catch throw:{fail, _} -> bind_guard(Arg2, Map, Env, pos, State) + try bind_guard(Arg2, Map, Env, neg, State) + catch throw:{fail, _} -> bind_guard(Arg1, Map, Env, pos, State) end, case t_is_atom(false, Type1) orelse t_is_atom(false, Type2) of true -> {join_maps([Map1, Map2], Map), t_atom(false)}; false -> throw({fail, none}) end; dont_know -> - True = t_atom(true), {Map1, Type1} = bind_guard(Arg1, Map, Env, dont_know, State), - case t_is_none(t_inf(Type1, t_boolean())) of - true -> throw({fail, none}); + {Map2, Type2} = bind_guard(Arg2, Map, Env, dont_know, State), + Bool1 = t_inf(Type1, t_boolean()), + Bool2 = t_inf(Type2, t_boolean()), + case t_is_none(Bool1) orelse t_is_none(Bool2) of + true -> throw({fatal_fail, none}); false -> - {Map2, Type2} = bind_guard(Arg2, Map1, Env, Eval, State), - case t_is_none(t_inf(Type2, t_boolean())) of - true -> throw({fail, none}); - false -> {Map2, True} - end + NewMap = join_maps([Map1, Map2], Map), + NewType = + case {t_atom_vals(Bool1), t_atom_vals(Bool2)} of + {['true'] , ['true'] } -> t_atom(true); + {['false'], _ } -> t_atom(false); + {_ , ['false']} -> t_atom(false); + {_ , _ } -> t_boolean() + end, + {NewMap, NewType} end end. @@ -2303,11 +2309,22 @@ handle_guard_or(Guard, Map, Env, Eval, State) -> end end; dont_know -> - {Map1, Bool1} = bind_guard(Arg1, Map, Env, dont_know, State), - {Map2, Bool2} = bind_guard(Arg2, Map, Env, dont_know, State), - case t_is_boolean(Bool1) andalso t_is_boolean(Bool2) of - true -> {join_maps([Map1, Map2], Map), t_sup(Bool1, Bool2)}; - false -> throw({fail, none}) + {Map1, Type1} = bind_guard(Arg1, Map, Env, dont_know, State), + {Map2, Type2} = bind_guard(Arg2, Map, Env, dont_know, State), + Bool1 = t_inf(Type1, t_boolean()), + Bool2 = t_inf(Type2, t_boolean()), + case t_is_none(Bool1) orelse t_is_none(Bool2) of + true -> throw({fatal_fail, none}); + false -> + NewMap = join_maps([Map1, Map2], Map), + NewType = + case {t_atom_vals(Bool1), t_atom_vals(Bool2)} of + {['false'], ['false']} -> t_atom(false); + {['true'] , _ } -> t_atom(true); + {_ , ['true'] } -> t_atom(true); + {_ , _ } -> t_boolean() + end, + {NewMap, NewType} end end. |