From 1a23202000716bbc430f1212c06d7ef622acdd3e Mon Sep 17 00:00:00 2001 From: Stavros Aronis Date: Wed, 26 Mar 2014 18:06:09 +0100 Subject: Dialyzer now plays nicely with funs that come as "external" arguments Two steps are needed to make this work: 1) Avoid generating the additional "apply_constraint" in dialyzer_typesig by reporting every function argument as a potential external function (patch on dialyzer_dep). This will produce correct success typings for all functions in the test case, but dataflow would miss the key warnings that help identify the bugs. 2) Patch dialyzer_dataflow so that it uses the "handle just external" path as a fallback whenever there are any external calls. As a result, if we have info about some paths, then: a) use the old "handle known apply" code to mark these functions as used and b) ignore the generalized result and use the one found by typesig for the return value of the apply itself. --- .../small_SUITE_data/results/funs_from_outside | 7 ++ .../small_SUITE_data/src/funs_from_outside.erl | 83 ++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 lib/dialyzer/test/small_SUITE_data/results/funs_from_outside create mode 100644 lib/dialyzer/test/small_SUITE_data/src/funs_from_outside.erl (limited to 'lib/dialyzer/test/small_SUITE_data') diff --git a/lib/dialyzer/test/small_SUITE_data/results/funs_from_outside b/lib/dialyzer/test/small_SUITE_data/results/funs_from_outside new file mode 100644 index 0000000000..3e597ef1bc --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/results/funs_from_outside @@ -0,0 +1,7 @@ + +funs_from_outside.erl:18: The pattern 'error' can never match the type {'ok','nothing' | 'something'} +funs_from_outside.erl:32: Function run2/2 has no local return +funs_from_outside.erl:35: Function testb/3 has no local return +funs_from_outside.erl:41: The pattern 'error' can never match the type {'ok','nothing' | 'something'} +funs_from_outside.erl:78: Function test2/1 has no local return +funs_from_outside.erl:83: The pattern 'error' can never match the type 'ok' diff --git a/lib/dialyzer/test/small_SUITE_data/src/funs_from_outside.erl b/lib/dialyzer/test/small_SUITE_data/src/funs_from_outside.erl new file mode 100644 index 0000000000..f4cbf31160 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/funs_from_outside.erl @@ -0,0 +1,83 @@ +-module(funs_from_outside). + +-export([run1/2, run2/2, run3/2]). +-export([test1/1, test2/1]). + +%%------------------------------------------------------------------------------ + +run1(X, Y) -> + testa(fun do_something/1, X, Y). + +testa(Fun, X, Y) -> + F = case even(X) of + true -> Fun; + false -> fun do_nothing/1 + end, + case F(Y) of + {ok, _} -> ok; + error -> error + end. + +do_nothing(_) -> {ok, nothing}. + +do_something(_) -> {ok, something}. + +even(X) -> + X rem 2 =:= 0. + +%%------------------------------------------------------------------------------ + +%% Duplicating code since we are monovariant... + +run2(X, Y) -> + testb(fun do_something/1, X, Y). + +testb(Fun, X, Y) -> + F = case even(X) of + true -> Fun; + false -> fun do_nothing/1 + end, + case F(Y) of + error -> error + end. + +%%------------------------------------------------------------------------------ + +%% Duplicating code since we are monovariant... + +run3(X, Y) -> + testc(fun do_something_2/1, X, Y). + +testc(Fun, X, Y) -> + F = case even(X) of + true -> Fun; + false -> fun do_nothing/1 + end, + case F(Y) of + {ok, _} -> ok; + %% This pattern can match. + error -> error + end. + +do_something_2(foo) -> {ok, something}; +do_something_2(_) -> error. + +%%------------------------------------------------------------------------------ + +test1(Fun) -> + F = case get(test1) of + test1_t -> Fun; + test1_f -> fun fok/0 + end, + error = F(). + +fok() -> ok. + +%%------------------------------------------------------------------------------ + +test2(Fun) -> + F = case get(test1) of + test1_t -> fun fok/0; + test1_f -> fun fok/0 + end, + error = F(). -- cgit v1.2.3