diff options
author | Stavros Aronis <[email protected]> | 2011-03-20 23:43:53 +0200 |
---|---|---|
committer | Stavros Aronis <[email protected]> | 2011-08-29 09:31:36 +0300 |
commit | 45537dc582a4fe44a3407e97acb0e1e391fdcd6d (patch) | |
tree | ad8d3c87ff020889158a460a352c6cd15e64611f /lib/dialyzer/src/dialyzer_dataflow.erl | |
parent | e7f7a3052096286a3df0b6c2217a9fe3248be7f4 (diff) | |
download | otp-45537dc582a4fe44a3407e97acb0e1e391fdcd6d.tar.gz otp-45537dc582a4fe44a3407e97acb0e1e391fdcd6d.tar.bz2 otp-45537dc582a4fe44a3407e97acb0e1e391fdcd6d.zip |
Suppress some warnings about generation of non-returning funs
No warnings are emitted for funs that are non-returning when the
function that generates them has a contract that specifies that
it will return such a non-returning fun.
The actual bug, reported by Tuncer Ayaz and simplified by Maria
Christakis is included in Dialyzer's tests.
Diffstat (limited to 'lib/dialyzer/src/dialyzer_dataflow.erl')
-rw-r--r-- | lib/dialyzer/src/dialyzer_dataflow.erl | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/lib/dialyzer/src/dialyzer_dataflow.erl b/lib/dialyzer/src/dialyzer_dataflow.erl index df411342cb..659297f993 100644 --- a/lib/dialyzer/src/dialyzer_dataflow.erl +++ b/lib/dialyzer/src/dialyzer_dataflow.erl @@ -2952,7 +2952,7 @@ state__get_warnings(#state{tree_map = TreeMap, fun_tab = FunTab, %% Check if the function has a contract that allows this. Warn = case Contract of - none -> true; + none -> not parent_allows_this(FunLbl, State); {value, C} -> GenRet = dialyzer_contracts:get_contract_return(C), not t_is_unit(GenRet) @@ -3440,6 +3440,33 @@ map_pats(Pats) -> end, cerl_trees:map(Fun, Pats). +parent_allows_this(FunLbl, #state{callgraph = Callgraph, plt = Plt} =State) -> + case state__is_escaping(FunLbl, State) of + false -> false; % if it isn't escaping it can't be a return value + true -> + case state__lookup_name(FunLbl, State) of + {_M, _F, _A} -> false; % if it has a name it is not a fun + _ -> + case dialyzer_callgraph:in_neighbours(FunLbl, Callgraph) of + [Parent] -> + case state__lookup_name(Parent, State) of + {_M, _F, _A} = PMFA -> + case dialyzer_plt:lookup_contract(Plt, PMFA) of + none -> false; + {value, C} -> + GenRet = dialyzer_contracts:get_contract_return(C), + case erl_types:t_is_fun(GenRet) of + false -> false; % element of structure? far-fetched... + true -> t_is_unit(t_fun_range(GenRet)) + end + end; + _ -> false % parent should have a name to have a contract + end; + _ -> false % called in other funs? far-fetched... + end + end + end. + classify_returns(Tree) -> case find_terminals(cerl:fun_body(Tree)) of {false, false} -> no_match; |