diff options
Diffstat (limited to 'lib/dialyzer/test/small_SUITE_data/src')
7 files changed, 344 insertions, 5 deletions
diff --git a/lib/dialyzer/test/small_SUITE_data/src/chars.erl b/lib/dialyzer/test/small_SUITE_data/src/chars.erl index 1e9c8ab6b9..62b90cf54d 100644 --- a/lib/dialyzer/test/small_SUITE_data/src/chars.erl +++ b/lib/dialyzer/test/small_SUITE_data/src/chars.erl @@ -12,17 +12,25 @@ -spec t() -> $0-$0..$9-$0| $?. t() -> - c(#r{f = $z - 3}), + r(#r{f = $z - 3}), + r(#r{f = 97}), + c($/), c($z - 3), c($B). -spec c(cs()) -> $3-$0..$9-$0. - -c($A + 1) -> 2; +c($A + 1) -> $9-$0; c(C) -> case C of - $z - 3 -> 3; - #r{f = $z - 3} -> 7 + $z - 3 -> $3-$0; + _ -> $7-$0 + end. + +-spec r(#r{f :: $a..$z}) -> ok | error. +r(R) -> + case R of + #r{f = $z - 3} -> error; + _ -> ok end. %% Display contract with character in warning: diff --git a/lib/dialyzer/test/small_SUITE_data/src/extra_range.erl b/lib/dialyzer/test/small_SUITE_data/src/extra_range.erl new file mode 100644 index 0000000000..9d6ba89c95 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/extra_range.erl @@ -0,0 +1,59 @@ +%% Test that a spec containing more items than actually returned +%% (whether by accident or by benign overspeccing) does not prevent +%% detection of impossible matches. + +-module(extra_range). + +-export([t1/2, t2/2, t3/2, t4/2]). + +-dialyzer([no_return]). + +%% this spec matches the behaviour of the code +-spec normal(integer()) -> ok | error. +normal(1) -> ok; +normal(2) -> error. + +t1(X, Y) when is_integer(X), is_integer(Y) -> + ok = normal(X), + error = normal(Y), + ok. + + +%% this spec has a typo, which should cause anyone trying to match on +%% `ok = typo(X)' to get a warning, because `ok' is not in the spec +-spec typo(integer()) -> ook | error. +typo(1) -> ok; +typo(2) -> error. + +t2(X, Y) when is_integer(X), is_integer(Y) -> + ok = typo(X), % warning expected - not allowed according to spec + error = typo(Y), + ok. + + +%% this is overspecified, and should cause a warning for trying +%% to match on `no = over(X)', because it cannot succeed and either +%% the spec should be updated or the code should be extended +-spec over(integer()) -> yes | no | maybe. +over(1) -> yes; +over(_) -> maybe. + +t3(X, Y) when is_integer(X), is_integer(Y) -> + yes = over(X), + no = over(Y), % warning expected - spec or code needs fixing + maybe = over(X + Y), + ok. + + +%% this is underspecified, which should cause anyone trying to match on +%% `maybe = under(X)' to get a warning, because `maybe' is not in the spec +-spec under(integer()) -> yes | no. +under(1) -> yes; +under(2) -> no; +under(_) -> maybe. + +t4(X, Y) when is_integer(X), is_integer(Y) -> + yes = under(X), + no = under(Y), + maybe = under(X + Y), % warning expected - not in spec + ok. diff --git a/lib/dialyzer/test/small_SUITE_data/src/left_assoc.erl b/lib/dialyzer/test/small_SUITE_data/src/left_assoc.erl new file mode 100644 index 0000000000..0250e4ab49 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/left_assoc.erl @@ -0,0 +1,96 @@ +-module(left_assoc). + +%% As pointed out in ERL-680, analyzing guards with short circuit +%% operators becomes very slow as the number of left associations +%% grows. + +-spec from_iso8601('Elixir.String':t(), 'Elixir.Calendar':calendar()) -> + {ok, t()} | {error, atom()}. + +-export_type([t/0]). + +-type t() :: + #{'__struct__' := 'Elixir.Date', + calendar := 'Elixir.Calendar':calendar(), + day := 'Elixir.Calendar':day(), + month := 'Elixir.Calendar':month(), + year := 'Elixir.Calendar':year()}. + +-export([from_iso8601/1, + from_iso8601/2]). + +from_iso8601(__@1) -> + from_iso8601(__@1, 'Elixir.Calendar.ISO'). + +from_iso8601(<<45/integer,_rest@1/binary>>, _calendar@1) -> + case raw_from_iso8601(_rest@1, _calendar@1) of + {ok,#{year := _year@1} = _date@1} -> + {ok,_date@1#{year := - _year@1}}; + __@1 -> + __@1 + end; +from_iso8601(<<_rest@1/binary>>, _calendar@1) -> + raw_from_iso8601(_rest@1, _calendar@1). + +raw_from_iso8601(_string@1, _calendar@1) -> + case _string@1 of + <<_y1@1/integer, + _y2@1/integer, + _y3@1/integer, + _y4@1/integer, + 45/integer, + _m1@1/integer, + _m2@1/integer, + 45/integer, + _d1@1/integer, + _d2@1/integer>> + when + ((((((((((((((_y1@1 >= 48 + andalso + _y1@1 =< 57) + andalso + _y2@1 >= 48) + andalso + _y2@1 =< 57) + andalso + _y3@1 >= 48) + andalso + _y3@1 =< 57) + andalso + _y4@1 >= 48) + andalso + _y4@1 =< 57) + andalso + _m1@1 >= 48) + andalso + _m1@1 =< 57) + andalso + _m2@1 >= 48) + andalso + _m2@1 =< 57) + andalso + _d1@1 >= 48) + andalso + _d1@1 =< 57) + andalso + _d2@1 >= 48) + andalso + _d2@1 =< 57 -> + {ok, + #{year => (_y1@1 - 48) * 1000 + (_y2@1 - 48) * 100 + + + (_y3@1 - 48) * 10 + + + (_y4@1 - 48), + month => (_m1@1 - 48) * 10 + (_m2@1 - 48), + day => (_d1@1 - 48) * 10 + (_d2@1 - 48), + calendar => _calendar@1, + '__struct__' => 'Elixir.Date'}}; + __@1 -> + case __@1 of + _ -> + {error,invalid_format}; + __@2 -> + error({with_clause,__@2}) + end + end. diff --git a/lib/dialyzer/test/small_SUITE_data/src/lists_key_bug.erl b/lib/dialyzer/test/small_SUITE_data/src/lists_key_bug.erl new file mode 100644 index 0000000000..ad5cf3c503 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/lists_key_bug.erl @@ -0,0 +1,75 @@ +-module(lists_key_bug). + +%% OTP-15570 + +-export([is_1/1, is_2/1, i/1, t1/0, t2/0, im/0]). + +%% int_set([3]) +is_1(V) -> + K = ikey(V), + case lists:keyfind(K, 1, [{<<"foo">>, bar}]) of + false -> + a; + {_, _} -> + b + end. + +ikey(1) -> + 3; +ikey(2) -> + <<"foo">>. + +%% int_set([3, 5]) +is_2(V) -> + K = iskey(V), + case lists:keyfind(K, 1, [{<<"foo">>, bar}]) of + false -> + a; + {_, _} -> + b + end. + +iskey(1) -> + 12; +iskey(2) -> + 14; +iskey(3) -> + <<"foo">>. + +%% integer() +i(V) -> + K = intkey(V), + case lists:keyfind(K, 1, [{9.0, foo}]) of + false -> + a; + {_, _} -> + b + end. + +intkey(K) when is_integer(K) -> + K + 9999. + +t1() -> + case lists:keyfind({17}, 1, [{{17.0}, true}]) of + false -> + a; + {_, _} -> + b + end. + +t2() -> + case lists:keyfind({17.0}, 1, [{{17}, true}]) of + false -> + a; + {_, _} -> + b + end. + +%% Note: #{1.0 => a} =/= #{1 => a}. +im() -> + case lists:keyfind(#{1.0 => a}, 1, [{#{1 => a}, foo}]) of + false -> + a; + {_, _} -> + b + end. diff --git a/lib/dialyzer/test/small_SUITE_data/src/spec_other_module.erl b/lib/dialyzer/test/small_SUITE_data/src/spec_other_module.erl new file mode 100644 index 0000000000..b36742b1bd --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/spec_other_module.erl @@ -0,0 +1,7 @@ +-module(spec_other_module). + +%% OTP-15562 and ERL-845. Example provided by Kostis. + +-type deep_list(A) :: [A | deep_list(A)]. + +-spec lists:flatten(deep_list(A)) -> [A]. diff --git a/lib/dialyzer/test/small_SUITE_data/src/stacktrace.erl b/lib/dialyzer/test/small_SUITE_data/src/stacktrace.erl new file mode 100644 index 0000000000..de79e710e9 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/stacktrace.erl @@ -0,0 +1,73 @@ +-module(stacktrace). + +%% Check the stacktrace variable introduced in Erlang/OTP 21.0 + +-export([t1/0, t2/0, t3/0, t4/0, s1/0, s2/0, s3/0, s4/0]). + +t1() -> + try foo:bar() + catch + E:P:S -> + {a,b} = S, % can never match + {E, P} + end. + +t2() -> + try foo:bar() + catch + E:P:S -> + [a,b] = S, % can never match + {E, P} + end. + +t3() -> + try foo:bar() + catch + E:P:S -> + [{m,f,[],[]}] = S, + {E, P} + end. + +t4() -> + try foo:bar() + catch + E:P:S -> + [{m,f,1,[{file,"tjo"},{line,95}]}] = S, + {E, P} + end. + +s1() -> + try foo:bar() + catch + E:P -> + S = erlang:get_stacktrace(), + {a,b} = S, % can never match + {E, P} + end. + +s2() -> + try foo:bar() + catch + E:P -> + S = erlang:get_stacktrace(), + [a,b] = S, % can never match + {E, P} + end. + +s3() -> + try foo:bar() + catch + E:P -> + S = erlang:get_stacktrace(), + [{m,f,[],[]}] = S, + {E, P} + end. + +s4() -> + try foo:bar() + catch + E:P -> + S = erlang:get_stacktrace(), + [{m,f,1,[{file,"tjo"},{line,95}]}] = S, + {E, P} + end. diff --git a/lib/dialyzer/test/small_SUITE_data/src/unused_funs.erl b/lib/dialyzer/test/small_SUITE_data/src/unused_funs.erl new file mode 100644 index 0000000000..c24cf3ea81 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/unused_funs.erl @@ -0,0 +1,21 @@ +%% See also ERL-593. + +-module(unused_funs). + +-export([test/0]). + +test() -> % "has no local return" + Var = outer_scope, + case other_error of + error -> % "can never match" + %% No warnings "no local return" and "_ = 1 can never match 0" (!) + foo(fun() -> {Var, 1 = 0} end) + end. + +not_used() -> % "will never be called" + %% No warnings "no local return" and "1 can never match 0". + foo(fun() -> 1 = 0 end). + +foo(Fun) -> % "will never be called" + 1 = 0, % No pattern match warning (foo/1 is not traversed at all). + Fun(). |