aboutsummaryrefslogtreecommitdiffstats
path: root/lib/dialyzer/test/small_SUITE_data/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dialyzer/test/small_SUITE_data/src')
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/behaviour_info/with_bad_format_status.erl12
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/behaviour_info/with_format_status.erl13
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/big_external_type.erl528
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/big_local_type.erl525
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/blame_contract_range_suppressed.erl15
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/contracts_with_subtypes.erl12
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/ditrap.erl47
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/maps1.erl36
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/predef2.erl56
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/request1.erl12
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/suppress_request.erl50
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/suppression1.erl33
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/suppression2.erl32
13 files changed, 1275 insertions, 96 deletions
diff --git a/lib/dialyzer/test/small_SUITE_data/src/behaviour_info/with_bad_format_status.erl b/lib/dialyzer/test/small_SUITE_data/src/behaviour_info/with_bad_format_status.erl
new file mode 100644
index 0000000000..24591e08fa
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/behaviour_info/with_bad_format_status.erl
@@ -0,0 +1,12 @@
+-module(with_bad_format_status).
+
+-behaviour(gen_server).
+-export([handle_call/3,handle_cast/2,handle_info/2,
+ code_change/3, init/1, terminate/2, format_status/2]).
+handle_call(_, _, S) -> {noreply, S}.
+handle_cast(_, S) -> {noreply, S}.
+handle_info(_, S) -> {noreply, S}.
+code_change(_, _, _) -> {error, not_implemented}.
+init(_) -> {ok, state}.
+terminate(_, _) -> ok.
+format_status(bad_arg, _) -> ok. % optional callback
diff --git a/lib/dialyzer/test/small_SUITE_data/src/behaviour_info/with_format_status.erl b/lib/dialyzer/test/small_SUITE_data/src/behaviour_info/with_format_status.erl
new file mode 100644
index 0000000000..a56ff63d1d
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/behaviour_info/with_format_status.erl
@@ -0,0 +1,13 @@
+-module(with_format_status).
+
+-behaviour(gen_server).
+-export([handle_call/3,handle_cast/2,handle_info/2,
+ code_change/3, init/1, terminate/2, format_status/2]).
+-export([handle_call/3,handle_cast/2,handle_info/2]).
+handle_call(_, _, S) -> {noreply, S}.
+handle_cast(_, S) -> {noreply, S}.
+handle_info(_, S) -> {noreply, S}.
+code_change(_, _, _) -> {error, not_implemented}.
+init(_) -> {ok, state}.
+terminate(_, _) -> ok.
+format_status(normal, _) -> ok. % optional callback
diff --git a/lib/dialyzer/test/small_SUITE_data/src/big_external_type.erl b/lib/dialyzer/test/small_SUITE_data/src/big_external_type.erl
new file mode 100644
index 0000000000..91a157b17f
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/big_external_type.erl
@@ -0,0 +1,528 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2001-2015. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%% A stripped version of erl_parse.yrl.
+%%%
+%%% A type for the abstract format with *external* types has been added.
+%%% The type of the abstract format is not up-to-date, but it does not
+%%% matter since the purpose of the type is to stress the conversion
+%%% of type forms to erl_type().
+
+-module(big_external_type).
+
+-export([parse_form/1,parse_exprs/1,parse_term/1]).
+-export([normalise/1,tokens/1,tokens/2]).
+-export([inop_prec/1,preop_prec/1,func_prec/0,max_prec/0]).
+
+-export_type([abstract_clause/0, abstract_expr/0, abstract_form/0,
+ error_info/0]).
+
+%% Start of Abstract Format
+
+-type line() :: erl_scan:line().
+
+-export_type([af_record_index/0, af_record_field/1, af_record_name/0,
+ af_field_name/0, af_function_decl/0]).
+
+-export_type([af_module/0, af_export/0, af_import/0, af_fa_list/0,
+ af_compile/0, af_file/0, af_record_decl/0,
+ af_field_decl/0, af_wild_attribute/0,
+ af_record_update/1, af_catch/0, af_local_call/0,
+ af_remote_call/0, af_args/0, af_local_function/0,
+ af_remote_function/0, af_list_comprehension/0,
+ af_binary_comprehension/0, af_template/0,
+ af_qualifier_seq/0, af_qualifier/0, af_generator/0,
+ af_filter/0, af_block/0, af_if/0, af_case/0, af_try/0,
+ af_clause_seq/0, af_catch_clause_seq/0, af_receive/0,
+ af_local_fun/0, af_remote_fun/0, af_fun/0, af_query/0,
+ af_query_access/0, af_clause/0,
+ af_catch_clause/0, af_catch_pattern/0, af_catch_class/0,
+ af_body/0, af_guard_seq/0, af_guard/0, af_guard_test/0,
+ af_record_access/1, af_guard_call/0,
+ af_remote_guard_call/0, af_pattern/0, af_literal/0,
+ af_atom/0, af_lit_atom/1, af_integer/0, af_float/0,
+ af_string/0, af_match/1, af_variable/0,
+ af_anon_variable/0, af_tuple/1, af_nil/0, af_cons/1,
+ af_bin/1, af_binelement/1, af_binelement_size/0,
+ af_binary_op/1, af_binop/0, af_unary_op/1, af_unop/0]).
+
+-type abstract_form() :: ?MODULE:af_module()
+ | ?MODULE:af_export()
+ | ?MODULE:af_import()
+ | ?MODULE:af_compile()
+ | ?MODULE:af_file()
+ | ?MODULE:af_record_decl()
+ | ?MODULE:af_wild_attribute()
+ | ?MODULE:af_function_decl().
+
+-type af_module() :: {attribute, line(), module, module()}.
+
+-type af_export() :: {attribute, line(), export, ?MODULE:af_fa_list()}.
+
+-type af_import() :: {attribute, line(), import, ?MODULE:af_fa_list()}.
+
+-type af_fa_list() :: [{function(), arity()}].
+
+-type af_compile() :: {attribute, line(), compile, any()}.
+
+-type af_file() :: {attribute, line(), file, {string(), line()}}.
+
+-type af_record_decl() ::
+ {attribute, line(), record, ?MODULE:af_record_name(), [?MODULE:af_field_decl()]}.
+
+-type af_field_decl() :: {record_field, line(), ?MODULE:af_atom()}
+ | {record_field, line(), ?MODULE:af_atom(), ?MODULE:abstract_expr()}.
+
+%% Types and specs, among other things...
+-type af_wild_attribute() :: {attribute, line(), ?MODULE:af_atom(), any()}.
+
+-type af_function_decl() ::
+ {function, line(), function(), arity(), ?MODULE:af_clause_seq()}.
+
+-type abstract_expr() :: ?MODULE:af_literal()
+ | ?MODULE:af_match(?MODULE:abstract_expr())
+ | ?MODULE:af_variable()
+ | ?MODULE:af_tuple(?MODULE:abstract_expr())
+ | ?MODULE:af_nil()
+ | ?MODULE:af_cons(?MODULE:abstract_expr())
+ | ?MODULE:af_bin(?MODULE:abstract_expr())
+ | ?MODULE:af_binary_op(?MODULE:abstract_expr())
+ | ?MODULE:af_unary_op(?MODULE:abstract_expr())
+ | ?MODULE:af_record_access(?MODULE:abstract_expr())
+ | ?MODULE:af_record_update(?MODULE:abstract_expr())
+ | ?MODULE:af_record_index()
+ | ?MODULE:af_record_field(?MODULE:abstract_expr())
+ | ?MODULE:af_catch()
+ | ?MODULE:af_local_call()
+ | ?MODULE:af_remote_call()
+ | ?MODULE:af_list_comprehension()
+ | ?MODULE:af_binary_comprehension()
+ | ?MODULE:af_block()
+ | ?MODULE:af_if()
+ | ?MODULE:af_case()
+ | ?MODULE:af_try()
+ | ?MODULE:af_receive()
+ | ?MODULE:af_local_fun()
+ | ?MODULE:af_remote_fun()
+ | ?MODULE:af_fun()
+ | ?MODULE:af_query()
+ | ?MODULE:af_query_access().
+
+-type af_record_update(T) :: {record,
+ line(),
+ ?MODULE:abstract_expr(),
+ ?MODULE:af_record_name(),
+ [?MODULE:af_record_field(T)]}.
+
+-type af_catch() :: {'catch', line(), ?MODULE:abstract_expr()}.
+
+-type af_local_call() :: {call, line(), ?MODULE:af_local_function(), ?MODULE:af_args()}.
+
+-type af_remote_call() :: {call, line(), ?MODULE:af_remote_function(), ?MODULE:af_args()}.
+
+-type af_args() :: [?MODULE:abstract_expr()].
+
+-type af_local_function() :: ?MODULE:abstract_expr().
+
+-type af_remote_function() ::
+ {remote, line(), ?MODULE:abstract_expr(), ?MODULE:abstract_expr()}.
+
+-type af_list_comprehension() ::
+ {lc, line(), ?MODULE:af_template(), ?MODULE:af_qualifier_seq()}.
+
+-type af_binary_comprehension() ::
+ {bc, line(), ?MODULE:af_template(), ?MODULE:af_qualifier_seq()}.
+
+-type af_template() :: ?MODULE:abstract_expr().
+
+-type af_qualifier_seq() :: [?MODULE:af_qualifier()].
+
+-type af_qualifier() :: ?MODULE:af_generator() | ?MODULE:af_filter().
+
+-type af_generator() :: {generate, line(), ?MODULE:af_pattern(), ?MODULE:abstract_expr()}
+ | {b_generate, line(), ?MODULE:af_pattern(), ?MODULE:abstract_expr()}.
+
+-type af_filter() :: ?MODULE:abstract_expr().
+
+-type af_block() :: {block, line(), ?MODULE:af_body()}.
+
+-type af_if() :: {'if', line(), ?MODULE:af_clause_seq()}.
+
+-type af_case() :: {'case', line(), ?MODULE:abstract_expr(), ?MODULE:af_clause_seq()}.
+
+-type af_try() :: {'try',
+ line(),
+ ?MODULE:af_body(),
+ ?MODULE:af_clause_seq(),
+ ?MODULE:af_catch_clause_seq(),
+ ?MODULE:af_body()}.
+
+-type af_clause_seq() :: [?MODULE:af_clause(), ...].
+
+-type af_catch_clause_seq() :: [?MODULE:af_clause(), ...].
+
+-type af_receive() ::
+ {'receive', line(), ?MODULE:af_clause_seq()}
+ | {'receive', line(), ?MODULE:af_clause_seq(), ?MODULE:abstract_expr(), ?MODULE:af_body()}.
+
+-type af_local_fun() :: {'fun', line(), {function, function(), arity()}}.
+
+-type af_remote_fun() ::
+ {'fun', line(), {function, module(), function(), arity()}}
+ | {'fun', line(), {function, ?MODULE:af_atom(), ?MODULE:af_atom(), ?MODULE:af_integer()}}.
+
+-type af_fun() :: {'fun', line(), {clauses, ?MODULE:af_clause_seq()}}.
+
+-type af_query() :: {'query', line(), ?MODULE:af_list_comprehension()}.
+
+-type af_query_access() ::
+ {record_field, line(), ?MODULE:abstract_expr(), ?MODULE:af_field_name()}.
+
+-type abstract_clause() :: ?MODULE:af_clause() | ?MODULE:af_catch_clause().
+
+-type af_clause() ::
+ {clause, line(), [?MODULE:af_pattern()], ?MODULE:af_guard_seq(), ?MODULE:af_body()}.
+
+-type af_catch_clause() ::
+ {clause, line(), [?MODULE:af_catch_pattern()], ?MODULE:af_guard_seq(), ?MODULE:af_body()}.
+
+-type af_catch_pattern() ::
+ {?MODULE:af_catch_class(), ?MODULE:af_pattern(), ?MODULE:af_anon_variable()}.
+
+-type af_catch_class() ::
+ ?MODULE:af_variable()
+ | ?MODULE:af_lit_atom(throw) | ?MODULE:af_lit_atom(error) | ?MODULE:af_lit_atom(exit).
+
+-type af_body() :: [?MODULE:abstract_expr(), ...].
+
+-type af_guard_seq() :: [?MODULE:af_guard()].
+
+-type af_guard() :: [?MODULE:af_guard_test(), ...].
+
+-type af_guard_test() :: ?MODULE:af_literal()
+ | ?MODULE:af_variable()
+ | ?MODULE:af_tuple(?MODULE:af_guard_test())
+ | ?MODULE:af_nil()
+ | ?MODULE:af_cons(?MODULE:af_guard_test())
+ | ?MODULE:af_bin(?MODULE:af_guard_test())
+ | ?MODULE:af_binary_op(?MODULE:af_guard_test())
+ | ?MODULE:af_unary_op(?MODULE:af_guard_test())
+ | ?MODULE:af_record_access(?MODULE:af_guard_test())
+ | ?MODULE:af_record_index()
+ | ?MODULE:af_record_field(?MODULE:af_guard_test())
+ | ?MODULE:af_guard_call()
+ | ?MODULE:af_remote_guard_call().
+
+-type af_record_access(T) ::
+ {record, line(), ?MODULE:af_record_name(), [?MODULE:af_record_field(T)]}.
+
+-type af_guard_call() :: {call, line(), function(), [?MODULE:af_guard_test()]}.
+
+-type af_remote_guard_call() ::
+ {call, line(), atom(), ?MODULE:af_lit_atom(erlang), [?MODULE:af_guard_test()]}.
+
+-type af_pattern() :: ?MODULE:af_literal()
+ | ?MODULE:af_match(?MODULE:af_pattern())
+ | ?MODULE:af_variable()
+ | ?MODULE:af_anon_variable()
+ | ?MODULE:af_tuple(?MODULE:af_pattern())
+ | ?MODULE:af_nil()
+ | ?MODULE:af_cons(?MODULE:af_pattern())
+ | ?MODULE:af_bin(?MODULE:af_pattern())
+ | ?MODULE:af_binary_op(?MODULE:af_pattern())
+ | ?MODULE:af_unary_op(?MODULE:af_pattern())
+ | ?MODULE:af_record_index()
+ | ?MODULE:af_record_field(?MODULE:af_pattern()).
+
+-type af_literal() :: ?MODULE:af_atom() | ?MODULE:af_integer() | ?MODULE:af_float() | ?MODULE:af_string().
+
+-type af_atom() :: ?MODULE:af_lit_atom(atom()).
+
+-type af_lit_atom(A) :: {atom, line(), A}.
+
+-type af_integer() :: {integer, line(), non_neg_integer()}.
+
+-type af_float() :: {float, line(), float()}.
+
+-type af_string() :: {string, line(), [byte()]}.
+
+-type af_match(T) :: {match, line(), T, T}.
+
+-type af_variable() :: {var, line(), atom()}.
+
+-type af_anon_variable() :: {var, line(), '_'}.
+
+-type af_tuple(T) :: {tuple, line(), [T]}.
+
+-type af_nil() :: {nil, line()}.
+
+-type af_cons(T) :: {cons, line, T, T}.
+
+-type af_bin(T) :: {bin, line(), [?MODULE:af_binelement(T)]}.
+
+-type af_binelement(T) :: {bin_element,
+ line(),
+ T,
+ ?MODULE:af_binelement_size(),
+ type_specifier_list()}.
+
+-type af_binelement_size() :: default | ?MODULE:abstract_expr().
+
+-type af_binary_op(T) :: {op, line(), T, ?MODULE:af_binop(), T}.
+
+-type af_binop() :: '/' | '*' | 'div' | 'rem' | 'band' | 'and' | '+' | '-'
+ | 'bor' | 'bxor' | 'bsl' | 'bsr' | 'or' | 'xor' | '++'
+ | '--' | '==' | '/=' | '=<' | '<' | '>=' | '>' | '=:='
+ | '=/='.
+
+-type af_unary_op(T) :: {op, line(), ?MODULE:af_unop(), T}.
+
+-type af_unop() :: '+' | '*' | 'bnot' | 'not'.
+
+%% See also lib/stdlib/{src/erl_bits.erl,include/erl_bits.hrl}.
+-type type_specifier_list() :: default | [type_specifier(), ...].
+
+-type type_specifier() :: af_type()
+ | af_signedness()
+ | af_endianness()
+ | af_unit().
+
+-type af_type() :: integer
+ | float
+ | binary
+ | bytes
+ | bitstring
+ | bits
+ | utf8
+ | utf16
+ | utf32.
+
+-type af_signedness() :: signed | unsigned.
+
+-type af_endianness() :: big | little | native.
+
+-type af_unit() :: {unit, 1..256}.
+
+-type af_record_index() ::
+ {record_index, line(), af_record_name(), af_field_name()}.
+
+-type af_record_field(T) :: {record_field, line(), af_field_name(), T}.
+
+-type af_record_name() :: atom().
+
+-type af_field_name() :: atom().
+
+%% End of Abstract Format
+
+-type error_description() :: term().
+-type error_info() :: {erl_scan:line(), module(), error_description()}.
+-type token() :: {Tag :: atom(), Line :: erl_scan:line()}.
+
+%% mkop(Op, Arg) -> {op,Line,Op,Arg}.
+%% mkop(Left, Op, Right) -> {op,Line,Op,Left,Right}.
+
+-define(mkop2(L, OpPos, R),
+ begin
+ {Op,Pos} = OpPos,
+ {op,Pos,Op,L,R}
+ end).
+
+-define(mkop1(OpPos, A),
+ begin
+ {Op,Pos} = OpPos,
+ {op,Pos,Op,A}
+ end).
+
+%% keep track of line info in tokens
+-define(line(Tup), element(2, Tup)).
+
+%% Entry points compatible to old erl_parse.
+%% These really suck and are only here until Calle gets multiple
+%% entry points working.
+
+-spec parse_form(Tokens) -> {ok, AbsForm} | {error, ErrorInfo} when
+ Tokens :: [token()],
+ AbsForm :: abstract_form(),
+ ErrorInfo :: error_info().
+parse_form([{'-',L1},{atom,L2,spec}|Tokens]) ->
+ parse([{'-',L1},{'spec',L2}|Tokens]);
+parse_form([{'-',L1},{atom,L2,callback}|Tokens]) ->
+ parse([{'-',L1},{'callback',L2}|Tokens]);
+parse_form(Tokens) ->
+ parse(Tokens).
+
+-spec parse_exprs(Tokens) -> {ok, ExprList} | {error, ErrorInfo} when
+ Tokens :: [token()],
+ ExprList :: [abstract_expr()],
+ ErrorInfo :: error_info().
+parse_exprs(Tokens) ->
+ case parse([{atom,0,f},{'(',0},{')',0},{'->',0}|Tokens]) of
+ {ok,{function,_Lf,f,0,[{clause,_Lc,[],[],Exprs}]}} ->
+ {ok,Exprs};
+ {error,_} = Err -> Err
+ end.
+
+-spec parse_term(Tokens) -> {ok, Term} | {error, ErrorInfo} when
+ Tokens :: [token()],
+ Term :: term(),
+ ErrorInfo :: error_info().
+parse_term(Tokens) ->
+ case parse([{atom,0,f},{'(',0},{')',0},{'->',0}|Tokens]) of
+ {ok,{function,_Lf,f,0,[{clause,_Lc,[],[],[Expr]}]}} ->
+ try normalise(Expr) of
+ Term -> {ok,Term}
+ catch
+ _:_R -> {error,{?line(Expr),?MODULE,"bad term"}}
+ end;
+ {ok,{function,_Lf,f,0,[{clause,_Lc,[],[],[_E1,E2|_Es]}]}} ->
+ {error,{?line(E2),?MODULE,"bad term"}};
+ {error,_} = Err -> Err
+ end.
+
+%% Convert between the abstract form of a term and a term.
+
+-spec normalise(AbsTerm) -> Data when
+ AbsTerm :: abstract_expr(),
+ Data :: term().
+normalise({char,_,C}) -> C;
+normalise({integer,_,I}) -> I;
+normalise({float,_,F}) -> F;
+normalise({atom,_,A}) -> A;
+normalise({string,_,S}) -> S;
+normalise({nil,_}) -> [];
+normalise({bin,_,Fs}) ->
+ {value, B, _} =
+ eval_bits:expr_grp(Fs, [],
+ fun(E, _) ->
+ {value, normalise(E), []}
+ end, [], true),
+ B;
+normalise({cons,_,Head,Tail}) ->
+ [normalise(Head)|normalise(Tail)];
+normalise({tuple,_,Args}) ->
+ list_to_tuple(normalise_list(Args));
+%% Atom dot-notation, as in 'foo.bar.baz'
+%% Special case for unary +/-.
+normalise({op,_,'+',{char,_,I}}) -> I;
+normalise({op,_,'+',{integer,_,I}}) -> I;
+normalise({op,_,'+',{float,_,F}}) -> F;
+normalise({op,_,'-',{char,_,I}}) -> -I; %Weird, but compatible!
+normalise({op,_,'-',{integer,_,I}}) -> -I;
+normalise({op,_,'-',{float,_,F}}) -> -F;
+normalise(X) -> erlang:error({badarg, X}).
+
+normalise_list([H|T]) ->
+ [normalise(H)|normalise_list(T)];
+normalise_list([]) ->
+ [].
+
+%% Generate a list of tokens representing the abstract term.
+
+-spec tokens(AbsTerm) -> Tokens when
+ AbsTerm :: abstract_expr(),
+ Tokens :: [token()].
+tokens(Abs) ->
+ tokens(Abs, []).
+
+-spec tokens(AbsTerm, MoreTokens) -> Tokens when
+ AbsTerm :: abstract_expr(),
+ MoreTokens :: [token()],
+ Tokens :: [token()].
+tokens({char,L,C}, More) -> [{char,L,C}|More];
+tokens({integer,L,N}, More) -> [{integer,L,N}|More];
+tokens({float,L,F}, More) -> [{float,L,F}|More];
+tokens({atom,L,A}, More) -> [{atom,L,A}|More];
+tokens({var,L,V}, More) -> [{var,L,V}|More];
+tokens({string,L,S}, More) -> [{string,L,S}|More];
+tokens({nil,L}, More) -> [{'[',L},{']',L}|More];
+tokens({cons,L,Head,Tail}, More) ->
+ [{'[',L}|tokens(Head, tokens_tail(Tail, More))];
+tokens({tuple,L,[]}, More) ->
+ [{'{',L},{'}',L}|More];
+tokens({tuple,L,[E|Es]}, More) ->
+ [{'{',L}|tokens(E, tokens_tuple(Es, ?line(E), More))].
+
+tokens_tail({cons,L,Head,Tail}, More) ->
+ [{',',L}|tokens(Head, tokens_tail(Tail, More))];
+tokens_tail({nil,L}, More) ->
+ [{']',L}|More];
+tokens_tail(Other, More) ->
+ L = ?line(Other),
+ [{'|',L}|tokens(Other, [{']',L}|More])].
+
+tokens_tuple([E|Es], Line, More) ->
+ [{',',Line}|tokens(E, tokens_tuple(Es, ?line(E), More))];
+tokens_tuple([], Line, More) ->
+ [{'}',Line}|More].
+
+%% Give the relative precedences of operators.
+
+inop_prec('=') -> {150,100,100};
+inop_prec('!') -> {150,100,100};
+inop_prec('orelse') -> {160,150,150};
+inop_prec('andalso') -> {200,160,160};
+inop_prec('==') -> {300,200,300};
+inop_prec('/=') -> {300,200,300};
+inop_prec('=<') -> {300,200,300};
+inop_prec('<') -> {300,200,300};
+inop_prec('>=') -> {300,200,300};
+inop_prec('>') -> {300,200,300};
+inop_prec('=:=') -> {300,200,300};
+inop_prec('=/=') -> {300,200,300};
+inop_prec('++') -> {400,300,300};
+inop_prec('--') -> {400,300,300};
+inop_prec('+') -> {400,400,500};
+inop_prec('-') -> {400,400,500};
+inop_prec('bor') -> {400,400,500};
+inop_prec('bxor') -> {400,400,500};
+inop_prec('bsl') -> {400,400,500};
+inop_prec('bsr') -> {400,400,500};
+inop_prec('or') -> {400,400,500};
+inop_prec('xor') -> {400,400,500};
+inop_prec('*') -> {500,500,600};
+inop_prec('/') -> {500,500,600};
+inop_prec('div') -> {500,500,600};
+inop_prec('rem') -> {500,500,600};
+inop_prec('band') -> {500,500,600};
+inop_prec('and') -> {500,500,600};
+inop_prec('#') -> {800,700,800};
+inop_prec(':') -> {900,800,900};
+inop_prec('.') -> {900,900,1000}.
+
+-type pre_op() :: 'catch' | '+' | '-' | 'bnot' | 'not' | '#'.
+
+-spec preop_prec(pre_op()) -> {0 | 600 | 700, 100 | 700 | 800}.
+
+preop_prec('catch') -> {0,100};
+preop_prec('+') -> {600,700};
+preop_prec('-') -> {600,700};
+preop_prec('bnot') -> {600,700};
+preop_prec('not') -> {600,700};
+preop_prec('#') -> {700,800}.
+
+-spec func_prec() -> {800,700}.
+
+func_prec() -> {800,700}.
+
+-spec max_prec() -> 1000.
+
+max_prec() -> 1000.
+
+parse(T) ->
+ bar:foo(T).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/big_local_type.erl b/lib/dialyzer/test/small_SUITE_data/src/big_local_type.erl
new file mode 100644
index 0000000000..6de263eda1
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/big_local_type.erl
@@ -0,0 +1,525 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2001-2015. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%% A stripped version of erl_parse.yrl.
+%%%
+%%% A type for the abstract format with *local* types has been added.
+%%% The type of the abstract format is not up-to-date, but it does not
+%%% matter since the purpose of the type is to stress the conversion
+%%% of type forms to erl_type().
+
+-module(big_local_type).
+
+-export([parse_form/1,parse_exprs/1,parse_term/1]).
+-export([normalise/1,tokens/1,tokens/2]).
+-export([inop_prec/1,preop_prec/1,func_prec/0,max_prec/0]).
+
+-export_type([abstract_clause/0, abstract_expr/0, abstract_form/0,
+ error_info/0]).
+
+%% Start of Abstract Format
+
+-type line() :: erl_scan:line().
+
+-export_type([af_module/0, af_export/0, af_import/0, af_fa_list/0,
+ af_compile/0, af_file/0, af_record_decl/0,
+ af_field_decl/0, af_wild_attribute/0,
+ af_record_update/1, af_catch/0, af_local_call/0,
+ af_remote_call/0, af_args/0, af_local_function/0,
+ af_remote_function/0, af_list_comprehension/0,
+ af_binary_comprehension/0, af_template/0,
+ af_qualifier_seq/0, af_qualifier/0, af_generator/0,
+ af_filter/0, af_block/0, af_if/0, af_case/0, af_try/0,
+ af_clause_seq/0, af_catch_clause_seq/0, af_receive/0,
+ af_local_fun/0, af_remote_fun/0, af_fun/0, af_query/0,
+ af_query_access/0, af_clause/0,
+ af_catch_clause/0, af_catch_pattern/0, af_catch_class/0,
+ af_body/0, af_guard_seq/0, af_guard/0, af_guard_test/0,
+ af_record_access/1, af_guard_call/0,
+ af_remote_guard_call/0, af_pattern/0, af_literal/0,
+ af_atom/0, af_lit_atom/1, af_integer/0, af_float/0,
+ af_string/0, af_match/1, af_variable/0,
+ af_anon_variable/0, af_tuple/1, af_nil/0, af_cons/1,
+ af_bin/1, af_binelement/1, af_binelement_size/0,
+ af_binary_op/1, af_binop/0, af_unary_op/1, af_unop/0]).
+
+-type abstract_form() :: af_module()
+ | af_export()
+ | af_import()
+ | af_compile()
+ | af_file()
+ | af_record_decl()
+ | af_wild_attribute()
+ | af_function_decl().
+
+-type af_module() :: {attribute, line(), module, module()}.
+
+-type af_export() :: {attribute, line(), export, af_fa_list()}.
+
+-type af_import() :: {attribute, line(), import, af_fa_list()}.
+
+-type af_fa_list() :: [{function(), arity()}].
+
+-type af_compile() :: {attribute, line(), compile, any()}.
+
+-type af_file() :: {attribute, line(), file, {string(), line()}}.
+
+-type af_record_decl() ::
+ {attribute, line(), record, af_record_name(), [af_field_decl()]}.
+
+-type af_field_decl() :: {record_field, line(), af_atom()}
+ | {record_field, line(), af_atom(), abstract_expr()}.
+
+%% Types and specs, among other things...
+-type af_wild_attribute() :: {attribute, line(), af_atom(), any()}.
+
+-type af_function_decl() ::
+ {function, line(), function(), arity(), af_clause_seq()}.
+
+-type abstract_expr() :: af_literal()
+ | af_match(abstract_expr())
+ | af_variable()
+ | af_tuple(abstract_expr())
+ | af_nil()
+ | af_cons(abstract_expr())
+ | af_bin(abstract_expr())
+ | af_binary_op(abstract_expr())
+ | af_unary_op(abstract_expr())
+ | af_record_access(abstract_expr())
+ | af_record_update(abstract_expr())
+ | af_record_index()
+ | af_record_field(abstract_expr())
+ | af_catch()
+ | af_local_call()
+ | af_remote_call()
+ | af_list_comprehension()
+ | af_binary_comprehension()
+ | af_block()
+ | af_if()
+ | af_case()
+ | af_try()
+ | af_receive()
+ | af_local_fun()
+ | af_remote_fun()
+ | af_fun()
+ | af_query()
+ | af_query_access().
+
+-type af_record_update(T) :: {record,
+ line(),
+ abstract_expr(),
+ af_record_name(),
+ [af_record_field(T)]}.
+
+-type af_catch() :: {'catch', line(), abstract_expr()}.
+
+-type af_local_call() :: {call, line(), af_local_function(), af_args()}.
+
+-type af_remote_call() :: {call, line(), af_remote_function(), af_args()}.
+
+-type af_args() :: [abstract_expr()].
+
+-type af_local_function() :: abstract_expr().
+
+-type af_remote_function() ::
+ {remote, line(), abstract_expr(), abstract_expr()}.
+
+-type af_list_comprehension() ::
+ {lc, line(), af_template(), af_qualifier_seq()}.
+
+-type af_binary_comprehension() ::
+ {bc, line(), af_template(), af_qualifier_seq()}.
+
+-type af_template() :: abstract_expr().
+
+-type af_qualifier_seq() :: [af_qualifier()].
+
+-type af_qualifier() :: af_generator() | af_filter().
+
+-type af_generator() :: {generate, line(), af_pattern(), abstract_expr()}
+ | {b_generate, line(), af_pattern(), abstract_expr()}.
+
+-type af_filter() :: abstract_expr().
+
+-type af_block() :: {block, line(), af_body()}.
+
+-type af_if() :: {'if', line(), af_clause_seq()}.
+
+-type af_case() :: {'case', line(), abstract_expr(), af_clause_seq()}.
+
+-type af_try() :: {'try',
+ line(),
+ af_body(),
+ af_clause_seq(),
+ af_catch_clause_seq(),
+ af_body()}.
+
+-type af_clause_seq() :: [af_clause(), ...].
+
+-type af_catch_clause_seq() :: [af_clause(), ...].
+
+-type af_receive() ::
+ {'receive', line(), af_clause_seq()}
+ | {'receive', line(), af_clause_seq(), abstract_expr(), af_body()}.
+
+-type af_local_fun() :: {'fun', line(), {function, function(), arity()}}.
+
+-type af_remote_fun() ::
+ {'fun', line(), {function, module(), function(), arity()}}
+ | {'fun', line(), {function, af_atom(), af_atom(), af_integer()}}.
+
+-type af_fun() :: {'fun', line(), {clauses, af_clause_seq()}}.
+
+-type af_query() :: {'query', line(), af_list_comprehension()}.
+
+-type af_query_access() ::
+ {record_field, line(), abstract_expr(), af_field_name()}.
+
+-type abstract_clause() :: af_clause() | af_catch_clause().
+
+-type af_clause() ::
+ {clause, line(), [af_pattern()], af_guard_seq(), af_body()}.
+
+-type af_catch_clause() ::
+ {clause, line(), [af_catch_pattern()], af_guard_seq(), af_body()}.
+
+-type af_catch_pattern() ::
+ {af_catch_class(), af_pattern(), af_anon_variable()}.
+
+-type af_catch_class() ::
+ af_variable()
+ | af_lit_atom(throw) | af_lit_atom(error) | af_lit_atom(exit).
+
+-type af_body() :: [abstract_expr(), ...].
+
+-type af_guard_seq() :: [af_guard()].
+
+-type af_guard() :: [af_guard_test(), ...].
+
+-type af_guard_test() :: af_literal()
+ | af_variable()
+ | af_tuple(af_guard_test())
+ | af_nil()
+ | af_cons(af_guard_test())
+ | af_bin(af_guard_test())
+ | af_binary_op(af_guard_test())
+ | af_unary_op(af_guard_test())
+ | af_record_access(af_guard_test())
+ | af_record_index()
+ | af_record_field(af_guard_test())
+ | af_guard_call()
+ | af_remote_guard_call().
+
+-type af_record_access(T) ::
+ {record, line(), af_record_name(), [af_record_field(T)]}.
+
+-type af_guard_call() :: {call, line(), function(), [af_guard_test()]}.
+
+-type af_remote_guard_call() ::
+ {call, line(), atom(), af_lit_atom(erlang), [af_guard_test()]}.
+
+-type af_pattern() :: af_literal()
+ | af_match(af_pattern())
+ | af_variable()
+ | af_anon_variable()
+ | af_tuple(af_pattern())
+ | af_nil()
+ | af_cons(af_pattern())
+ | af_bin(af_pattern())
+ | af_binary_op(af_pattern())
+ | af_unary_op(af_pattern())
+ | af_record_index()
+ | af_record_field(af_pattern()).
+
+-type af_literal() :: af_atom() | af_integer() | af_float() | af_string().
+
+-type af_atom() :: af_lit_atom(atom()).
+
+-type af_lit_atom(A) :: {atom, line(), A}.
+
+-type af_integer() :: {integer, line(), non_neg_integer()}.
+
+-type af_float() :: {float, line(), float()}.
+
+-type af_string() :: {string, line(), [byte()]}.
+
+-type af_match(T) :: {match, line(), T, T}.
+
+-type af_variable() :: {var, line(), atom()}.
+
+-type af_anon_variable() :: {var, line(), '_'}.
+
+-type af_tuple(T) :: {tuple, line(), [T]}.
+
+-type af_nil() :: {nil, line()}.
+
+-type af_cons(T) :: {cons, line, T, T}.
+
+-type af_bin(T) :: {bin, line(), [af_binelement(T)]}.
+
+-type af_binelement(T) :: {bin_element,
+ line(),
+ T,
+ af_binelement_size(),
+ type_specifier_list()}.
+
+-type af_binelement_size() :: default | abstract_expr().
+
+-type af_binary_op(T) :: {op, line(), T, af_binop(), T}.
+
+-type af_binop() :: '/' | '*' | 'div' | 'rem' | 'band' | 'and' | '+' | '-'
+ | 'bor' | 'bxor' | 'bsl' | 'bsr' | 'or' | 'xor' | '++'
+ | '--' | '==' | '/=' | '=<' | '<' | '>=' | '>' | '=:='
+ | '=/='.
+
+-type af_unary_op(T) :: {op, line(), af_unop(), T}.
+
+-type af_unop() :: '+' | '*' | 'bnot' | 'not'.
+
+%% See also lib/stdlib/{src/erl_bits.erl,include/erl_bits.hrl}.
+-type type_specifier_list() :: default | [type_specifier(), ...].
+
+-type type_specifier() :: af_type()
+ | af_signedness()
+ | af_endianness()
+ | af_unit().
+
+-type af_type() :: integer
+ | float
+ | binary
+ | bytes
+ | bitstring
+ | bits
+ | utf8
+ | utf16
+ | utf32.
+
+-type af_signedness() :: signed | unsigned.
+
+-type af_endianness() :: big | little | native.
+
+-type af_unit() :: {unit, 1..256}.
+
+-type af_record_index() ::
+ {record_index, line(), af_record_name(), af_field_name()}.
+
+-type af_record_field(T) :: {record_field, line(), af_field_name(), T}.
+
+-type af_record_name() :: atom().
+
+-type af_field_name() :: atom().
+
+%% End of Abstract Format
+
+-type error_description() :: term().
+-type error_info() :: {erl_scan:line(), module(), error_description()}.
+-type token() :: {Tag :: atom(), Line :: erl_scan:line()}.
+
+%% mkop(Op, Arg) -> {op,Line,Op,Arg}.
+%% mkop(Left, Op, Right) -> {op,Line,Op,Left,Right}.
+
+-define(mkop2(L, OpPos, R),
+ begin
+ {Op,Pos} = OpPos,
+ {op,Pos,Op,L,R}
+ end).
+
+-define(mkop1(OpPos, A),
+ begin
+ {Op,Pos} = OpPos,
+ {op,Pos,Op,A}
+ end).
+
+%% keep track of line info in tokens
+-define(line(Tup), element(2, Tup)).
+
+%% Entry points compatible to old erl_parse.
+%% These really suck and are only here until Calle gets multiple
+%% entry points working.
+
+-spec parse_form(Tokens) -> {ok, AbsForm} | {error, ErrorInfo} when
+ Tokens :: [token()],
+ AbsForm :: abstract_form(),
+ ErrorInfo :: error_info().
+parse_form([{'-',L1},{atom,L2,spec}|Tokens]) ->
+ parse([{'-',L1},{'spec',L2}|Tokens]);
+parse_form([{'-',L1},{atom,L2,callback}|Tokens]) ->
+ parse([{'-',L1},{'callback',L2}|Tokens]);
+parse_form(Tokens) ->
+ parse(Tokens).
+
+-spec parse_exprs(Tokens) -> {ok, ExprList} | {error, ErrorInfo} when
+ Tokens :: [token()],
+ ExprList :: [abstract_expr()],
+ ErrorInfo :: error_info().
+parse_exprs(Tokens) ->
+ case parse([{atom,0,f},{'(',0},{')',0},{'->',0}|Tokens]) of
+ {ok,{function,_Lf,f,0,[{clause,_Lc,[],[],Exprs}]}} ->
+ {ok,Exprs};
+ {error,_} = Err -> Err
+ end.
+
+-spec parse_term(Tokens) -> {ok, Term} | {error, ErrorInfo} when
+ Tokens :: [token()],
+ Term :: term(),
+ ErrorInfo :: error_info().
+parse_term(Tokens) ->
+ case parse([{atom,0,f},{'(',0},{')',0},{'->',0}|Tokens]) of
+ {ok,{function,_Lf,f,0,[{clause,_Lc,[],[],[Expr]}]}} ->
+ try normalise(Expr) of
+ Term -> {ok,Term}
+ catch
+ _:_R -> {error,{?line(Expr),?MODULE,"bad term"}}
+ end;
+ {ok,{function,_Lf,f,0,[{clause,_Lc,[],[],[_E1,E2|_Es]}]}} ->
+ {error,{?line(E2),?MODULE,"bad term"}};
+ {error,_} = Err -> Err
+ end.
+
+%% Convert between the abstract form of a term and a term.
+
+-spec normalise(AbsTerm) -> Data when
+ AbsTerm :: abstract_expr(),
+ Data :: term().
+normalise({char,_,C}) -> C;
+normalise({integer,_,I}) -> I;
+normalise({float,_,F}) -> F;
+normalise({atom,_,A}) -> A;
+normalise({string,_,S}) -> S;
+normalise({nil,_}) -> [];
+normalise({bin,_,Fs}) ->
+ {value, B, _} =
+ eval_bits:expr_grp(Fs, [],
+ fun(E, _) ->
+ {value, normalise(E), []}
+ end, [], true),
+ B;
+normalise({cons,_,Head,Tail}) ->
+ [normalise(Head)|normalise(Tail)];
+normalise({tuple,_,Args}) ->
+ list_to_tuple(normalise_list(Args));
+%% Atom dot-notation, as in 'foo.bar.baz'
+%% Special case for unary +/-.
+normalise({op,_,'+',{char,_,I}}) -> I;
+normalise({op,_,'+',{integer,_,I}}) -> I;
+normalise({op,_,'+',{float,_,F}}) -> F;
+normalise({op,_,'-',{char,_,I}}) -> -I; %Weird, but compatible!
+normalise({op,_,'-',{integer,_,I}}) -> -I;
+normalise({op,_,'-',{float,_,F}}) -> -F;
+normalise(X) -> erlang:error({badarg, X}).
+
+normalise_list([H|T]) ->
+ [normalise(H)|normalise_list(T)];
+normalise_list([]) ->
+ [].
+
+%% Generate a list of tokens representing the abstract term.
+
+-spec tokens(AbsTerm) -> Tokens when
+ AbsTerm :: abstract_expr(),
+ Tokens :: [token()].
+tokens(Abs) ->
+ tokens(Abs, []).
+
+-spec tokens(AbsTerm, MoreTokens) -> Tokens when
+ AbsTerm :: abstract_expr(),
+ MoreTokens :: [token()],
+ Tokens :: [token()].
+tokens({char,L,C}, More) -> [{char,L,C}|More];
+tokens({integer,L,N}, More) -> [{integer,L,N}|More];
+tokens({float,L,F}, More) -> [{float,L,F}|More];
+tokens({atom,L,A}, More) -> [{atom,L,A}|More];
+tokens({var,L,V}, More) -> [{var,L,V}|More];
+tokens({string,L,S}, More) -> [{string,L,S}|More];
+tokens({nil,L}, More) -> [{'[',L},{']',L}|More];
+tokens({cons,L,Head,Tail}, More) ->
+ [{'[',L}|tokens(Head, tokens_tail(Tail, More))];
+tokens({tuple,L,[]}, More) ->
+ [{'{',L},{'}',L}|More];
+tokens({tuple,L,[E|Es]}, More) ->
+ [{'{',L}|tokens(E, tokens_tuple(Es, ?line(E), More))].
+
+tokens_tail({cons,L,Head,Tail}, More) ->
+ [{',',L}|tokens(Head, tokens_tail(Tail, More))];
+tokens_tail({nil,L}, More) ->
+ [{']',L}|More];
+tokens_tail(Other, More) ->
+ L = ?line(Other),
+ [{'|',L}|tokens(Other, [{']',L}|More])].
+
+tokens_tuple([E|Es], Line, More) ->
+ [{',',Line}|tokens(E, tokens_tuple(Es, ?line(E), More))];
+tokens_tuple([], Line, More) ->
+ [{'}',Line}|More].
+
+%% Give the relative precedences of operators.
+
+inop_prec('=') -> {150,100,100};
+inop_prec('!') -> {150,100,100};
+inop_prec('orelse') -> {160,150,150};
+inop_prec('andalso') -> {200,160,160};
+inop_prec('==') -> {300,200,300};
+inop_prec('/=') -> {300,200,300};
+inop_prec('=<') -> {300,200,300};
+inop_prec('<') -> {300,200,300};
+inop_prec('>=') -> {300,200,300};
+inop_prec('>') -> {300,200,300};
+inop_prec('=:=') -> {300,200,300};
+inop_prec('=/=') -> {300,200,300};
+inop_prec('++') -> {400,300,300};
+inop_prec('--') -> {400,300,300};
+inop_prec('+') -> {400,400,500};
+inop_prec('-') -> {400,400,500};
+inop_prec('bor') -> {400,400,500};
+inop_prec('bxor') -> {400,400,500};
+inop_prec('bsl') -> {400,400,500};
+inop_prec('bsr') -> {400,400,500};
+inop_prec('or') -> {400,400,500};
+inop_prec('xor') -> {400,400,500};
+inop_prec('*') -> {500,500,600};
+inop_prec('/') -> {500,500,600};
+inop_prec('div') -> {500,500,600};
+inop_prec('rem') -> {500,500,600};
+inop_prec('band') -> {500,500,600};
+inop_prec('and') -> {500,500,600};
+inop_prec('#') -> {800,700,800};
+inop_prec(':') -> {900,800,900};
+inop_prec('.') -> {900,900,1000}.
+
+-type pre_op() :: 'catch' | '+' | '-' | 'bnot' | 'not' | '#'.
+
+-spec preop_prec(pre_op()) -> {0 | 600 | 700, 100 | 700 | 800}.
+
+preop_prec('catch') -> {0,100};
+preop_prec('+') -> {600,700};
+preop_prec('-') -> {600,700};
+preop_prec('bnot') -> {600,700};
+preop_prec('not') -> {600,700};
+preop_prec('#') -> {700,800}.
+
+-spec func_prec() -> {800,700}.
+
+func_prec() -> {800,700}.
+
+-spec max_prec() -> 1000.
+
+max_prec() -> 1000.
+
+parse(T) ->
+ bar:foo(T).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/blame_contract_range_suppressed.erl b/lib/dialyzer/test/small_SUITE_data/src/blame_contract_range_suppressed.erl
new file mode 100644
index 0000000000..8b66d35083
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/blame_contract_range_suppressed.erl
@@ -0,0 +1,15 @@
+%%-----------------------------------------------------------------------
+%% Like ./blame_contract_range.erl, but warning is suppressed.
+%%-----------------------------------------------------------------------
+-module(blame_contract_range_suppressed).
+
+-export([foo/0]).
+
+foo() ->
+ bar(b).
+
+-dialyzer({nowarn_function, bar/1}).
+
+-spec bar(atom()) -> a.
+bar(a) -> a;
+bar(b) -> b.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/contracts_with_subtypes.erl b/lib/dialyzer/test/small_SUITE_data/src/contracts_with_subtypes.erl
index d7dfd9752e..dbabd904c2 100644
--- a/lib/dialyzer/test/small_SUITE_data/src/contracts_with_subtypes.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/contracts_with_subtypes.erl
@@ -136,10 +136,14 @@ q(ab) -> rec2({a, b}); % breaks the contract
q(ba) -> rec2({b, a}); % breaks the contract
q(aba) -> rec2({a, {b, a}}); % breaks the contract
q(bab) -> rec2({b, {a, b}}); % breaks the contract
-q(abab) -> rec2({a, {b, {a, b}}});
-q(baba) -> rec2({b, {a, {b, a}}});
-q(ababa) -> rec2({a, {b, {a, {b, a}}}});
-q(babab) -> rec2({b, {a, {b, {a, b}}}}).
+q(abab) -> rec2({a, {b, {a, b}}}); % breaks the contract
+q(baba) -> rec2({b, {a, {b, a}}}); % breaks the contract
+q(ababa) -> rec2({a, {b, {a, {b, a}}}}); % breaks the contract
+q(babab) -> rec2({b, {a, {b, {a, b}}}}); % breaks the contract
+q(ababab) -> rec2({a, {b, {a, {b, {a, b}}}}});
+q(bababa) -> rec2({b, {a, {b, {a, {b, a}}}}});
+q(abababa) -> rec2({a, {b, {a, {b, {a, {b, a}}}}}});
+q(bababab) -> rec2({b, {a, {b, {a, {b, {a, b}}}}}}).
%===============================================================================
diff --git a/lib/dialyzer/test/small_SUITE_data/src/ditrap.erl b/lib/dialyzer/test/small_SUITE_data/src/ditrap.erl
new file mode 100644
index 0000000000..2d75f25bd5
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/ditrap.erl
@@ -0,0 +1,47 @@
+%% A bug reported by Tail-f Systems. The problem is that record types
+%% are included without properly limiting their depth.
+
+-module(ditrap).
+
+-define(tref(T), ?MODULE:T).
+-define(fref(T), ?MODULE:T).
+
+-export_type([ module_rec/0
+ , typedef_rec/0
+ , type_spec_fun/0
+ ]).
+
+-record(type, {
+ base :: 'builtin' | external:random_type() | ?tref(typedef_rec()),
+ type_spec_fun :: ?fref(type_spec_fun())
+ }).
+
+-record(typedef, {type :: #type{}}).
+
+-record(typedefs, {
+ map :: ?tref(typedef_rec()),
+ parent :: 'undefined' | #typedefs{}
+ }).
+
+-record(sn, {
+ module :: ?tref(module_rec()),
+ typedefs :: #typedefs{},
+ type :: 'undefined' | #type{},
+ keys :: 'undefined' | [#sn{}],
+ children = [] :: [#sn{}]
+ }).
+
+-record(augment, {children = [] :: [#sn{}]}).
+
+-record(module, {
+ submodules = [] :: [{#module{}, external:pos()}],
+ typedefs = #typedefs{} :: #typedefs{},
+ children = [] :: [#sn{}],
+ remote_augments = [] :: [{ModuleName :: atom(), [#augment{}]}],
+ local_augments = [] :: [#augment{}]
+ }).
+
+-type typedef_rec() :: #typedef{}.
+-type module_rec() :: #module{}.
+
+-type type_spec_fun() :: undefined | fun((#type{}, #module{}) -> any()).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/maps1.erl b/lib/dialyzer/test/small_SUITE_data/src/maps1.erl
index 228ffe2c22..06ced5b69e 100644
--- a/lib/dialyzer/test/small_SUITE_data/src/maps1.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/maps1.erl
@@ -10,7 +10,6 @@
-export([recv/3, decode/1]).
--export([get_my_map/0,is_my_map/1]).
%-record(can_pkt, {id, data :: binary(), timestamp}).
@@ -40,38 +39,3 @@ t2() -> ok.
update(#{ id := Id, val := Val } = M, X) when is_integer(Id) ->
M#{ val := [Val,X] }.
-
-%% key coalescing
-
--spec get_my_map() -> map().
-
-get_my_map() ->
- #{labels => [one, two],
- number => 27,
- [1,2,3] => wer,
- {4,5,6} => sdf,
- kvok => #{
- <<"wat">> => v,
- a => qwe,
- 2 => asd,
- [1,2,3] => wer,
- {4,5,6} => sdf,
- "abc" => zxc
- }
- }.
-
--spec is_my_map(map()) -> 'ok'.
-
-is_my_map(#{labels := [one, two],
- number := 27,
- [1,2,3] := wer,
- {4,5,6} := sdf,
- kvok := #{
- <<"wat">> := v,
- a := qwe,
- 2 := asd,
- [1,2,3] := wer,
- {4,5,6} := sdf,
- "abc" := zxc
- }
- }) -> ok.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/predef2.erl b/lib/dialyzer/test/small_SUITE_data/src/predef2.erl
deleted file mode 100644
index b1d941a49a..0000000000
--- a/lib/dialyzer/test/small_SUITE_data/src/predef2.erl
+++ /dev/null
@@ -1,56 +0,0 @@
--module(predef2).
-
--export([array/1, dict/1, digraph/1, digraph2/1, gb_set/1, gb_tree/1,
- queue/1, set/1, tid/0, tid2/0]).
-
--export_type([array/0, digraph/0, gb_set/0]).
-
--spec array(array()) -> array:array().
-
-array(A) ->
- array:relax(A).
-
--spec dict(dict()) -> dict:dict().
-
-dict(D) ->
- dict:store(1, a, D).
-
--spec digraph(digraph()) -> [digraph:edge()].
-
-digraph(G) ->
- digraph:edges(G).
-
--spec digraph2(digraph:graph()) -> [digraph:edge()].
-
-digraph2(G) ->
- digraph:edges(G).
-
--spec gb_set(gb_set()) -> gb_sets:set().
-
-gb_set(S) ->
- gb_sets:balance(S).
-
--spec gb_tree(gb_tree()) -> gb_trees:tree().
-
-gb_tree(S) ->
- gb_trees:balance(S).
-
--spec queue(queue()) -> queue:queue().
-
-queue(Q) ->
- queue:reverse(Q).
-
--spec set(set()) -> sets:set().
-
-set(S) ->
- sets:union([S]).
-
--spec tid() -> tid().
-
-tid() ->
- ets:new(tid, []).
-
--spec tid2() -> ets:tid().
-
-tid2() ->
- ets:new(tid, []).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/request1.erl b/lib/dialyzer/test/small_SUITE_data/src/request1.erl
new file mode 100644
index 0000000000..a6c4ab8dbd
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/request1.erl
@@ -0,0 +1,12 @@
+-module(request1).
+
+-export([a/0]).
+
+-dialyzer(unmatched_returns).
+
+a() ->
+ b(),
+ 1.
+
+b() ->
+ {a, b}.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/suppress_request.erl b/lib/dialyzer/test/small_SUITE_data/src/suppress_request.erl
new file mode 100644
index 0000000000..c4275fa110
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/suppress_request.erl
@@ -0,0 +1,50 @@
+-module(suppress_request).
+
+-export([test1/1, test1_b/1, test2/0, test2_b/0,
+ test3/0, test3_b/0, test4/0, test4_b/0]).
+
+-dialyzer({[specdiffs], test1/1}).
+-spec test1(a | b) -> ok. % spec is subtype
+test1(A) ->
+ ok = test1_1(A).
+
+-spec test1_b(a | b) -> ok. % spec is subtype (suppressed by default)
+test1_b(A) ->
+ ok = test1_1(A).
+
+-spec test1_1(a | b | c) -> ok.
+test1_1(_) ->
+ ok.
+
+-dialyzer(unmatched_returns).
+test2() ->
+ tuple(), % unmatched
+ ok.
+
+test2_b() ->
+ tuple(), % unmatched
+ ok.
+
+-dialyzer({[no_return, no_match], [test3/0]}).
+test3() -> % no local return (suppressed)
+ A = fun(_) ->
+ 1
+ end,
+ A = 2. % can never succeed (suppressed)
+
+test3_b() -> % no local return (requested by default)
+ A = fun(_) ->
+ 1
+ end,
+ A = 2. % can never succeed (requested by default)
+
+-dialyzer(no_improper_lists).
+test4() ->
+ [1 | 2]. % improper list (suppressed)
+
+-dialyzer({no_improper_lists, test4_b/0}).
+test4_b() ->
+ [1 | 2]. % improper list (suppressed)
+
+tuple() ->
+ {a, b}.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/suppression1.erl b/lib/dialyzer/test/small_SUITE_data/src/suppression1.erl
new file mode 100644
index 0000000000..00534704c3
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/suppression1.erl
@@ -0,0 +1,33 @@
+-module(suppression1).
+
+-export([a/1, b/1, c/0]).
+
+-dialyzer({nowarn_function, a/1}).
+
+-spec a(_) -> integer().
+
+a(_) ->
+ A = fun(_) ->
+ B = fun(_) ->
+ x = 7
+ end,
+ B = 1
+ end,
+ A.
+
+-spec b(_) -> integer().
+
+-dialyzer({nowarn_function, b/1}).
+
+b(_) ->
+ A = fun(_) ->
+ 1
+ end,
+ A = 2.
+
+-record(r, {a = a :: integer()}).
+
+-dialyzer({nowarn_function, c/0}).
+
+c() ->
+ #r{}.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/suppression2.erl b/lib/dialyzer/test/small_SUITE_data/src/suppression2.erl
new file mode 100644
index 0000000000..4cba53fdce
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/suppression2.erl
@@ -0,0 +1,32 @@
+-module(suppression2).
+
+-export([a/1, b/1, c/0]).
+
+-dialyzer({nowarn_function, [a/1, b/1, c/0]}).
+-dialyzer([no_undefined_callbacks]).
+
+-behaviour(not_a_behaviour).
+
+-spec a(_) -> integer().
+
+a(_) ->
+ A = fun(_) ->
+ B = fun(_) ->
+ x = 7
+ end,
+ B = 1
+ end,
+ A.
+
+-spec b(_) -> integer().
+
+b(_) ->
+ A = fun(_) ->
+ 1
+ end,
+ A = 2.
+
+-record(r, {a = a :: integer()}).
+
+c() ->
+ #r{}.