aboutsummaryrefslogtreecommitdiffstats
path: root/lib/dialyzer/test/small_SUITE_data
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dialyzer/test/small_SUITE_data')
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/refine_failing2
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/refine_failing.erl26
2 files changed, 28 insertions, 0 deletions
diff --git a/lib/dialyzer/test/small_SUITE_data/results/refine_failing b/lib/dialyzer/test/small_SUITE_data/results/refine_failing
new file mode 100644
index 0000000000..2bf67c9d81
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/refine_failing
@@ -0,0 +1,2 @@
+
+refine_failing.erl:25: The call refine_failing:update_one(F::any(),Ds::{_,non_neg_integer()},[{_,non_neg_integer()},...]) will never return since it differs in the 2nd argument from the success typing arguments: (any(),[{_,non_neg_integer()}],[{_,non_neg_integer()}])
diff --git a/lib/dialyzer/test/small_SUITE_data/src/refine_failing.erl b/lib/dialyzer/test/small_SUITE_data/src/refine_failing.erl
new file mode 100644
index 0000000000..243f4806e6
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/refine_failing.erl
@@ -0,0 +1,26 @@
+%% This testcase shows why it's a bad idea to block refinement (by forwarding
+%% any() to all arguments) when a failing call is encountered. The initial
+%% success typing for update_one allows anything to be an element of the list in
+%% the second argument. This will be refined during dataflow by the result from
+%% add_counters to just a list of tuples. This will cause the call in the second
+%% clause of update_one to fail correctly and identify the discrepancy. It could
+%% be a better idea to refuse to add the failing calls but this may lead to a
+%% ton of unused functions,
+%%
+%% by Stavros Aronis<[email protected]>
+
+-module(refine_failing).
+
+-export([foo/2]).
+
+foo(A, B) -> update_all(add_counters(A, []), B).
+
+add_counters( [], Acc) -> Acc;
+add_counters([H|T], Acc) -> add_counters(T, [{H, 0}|Acc]).
+
+update_all(Ds, []) -> Ds;
+update_all(Ds, [F|Fs]) -> update_all(update_one(F, Ds, []), Fs).
+
+update_one(_F, [], Acc) -> Acc;
+update_one( F, [{F, Cr},Ds], Acc) -> update_one(F, Ds, [{F,Cr+1}|Acc]);
+update_one( F, [ D|Ds], Acc) -> update_one(F, Ds, [ D|Acc]).