aboutsummaryrefslogtreecommitdiffstats
path: root/lib/dialyzer/src/dialyzer_dataflow.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dialyzer/src/dialyzer_dataflow.erl')
-rw-r--r--lib/dialyzer/src/dialyzer_dataflow.erl79
1 files changed, 57 insertions, 22 deletions
diff --git a/lib/dialyzer/src/dialyzer_dataflow.erl b/lib/dialyzer/src/dialyzer_dataflow.erl
index 963c953447..ce292e1140 100644
--- a/lib/dialyzer/src/dialyzer_dataflow.erl
+++ b/lib/dialyzer/src/dialyzer_dataflow.erl
@@ -529,7 +529,7 @@ handle_apply_or_call([{TypeOfApply, {Fun, Sig, Contr, LocalRet}}|Left],
case is_race_analysis_enabled(State) of
true ->
Ann = cerl:get_ann(Tree),
- File = get_file(Ann),
+ File = get_file(Ann, State),
Line = abs(get_line(Ann)),
dialyzer_races:store_race_call(Fun, ArgTypes, Args,
{File, Line}, State);
@@ -1211,7 +1211,7 @@ handle_tuple(Tree, Map, State) ->
TagVal = cerl:atom_val(Tag),
case state__lookup_record(TagVal, length(Left), State1) of
error -> {State1, Map1, TupleType};
- {ok, RecType} ->
+ {ok, RecType, FieldNames} ->
InfTupleType = t_inf(RecType, TupleType),
case t_is_none(InfTupleType) of
true ->
@@ -1232,10 +1232,13 @@ handle_tuple(Tree, Map, State) ->
Tree, Msg),
{State2, Map1, t_none()};
{error, opaque, ErrorPat, ErrorType, OpaqueType} ->
+ OpaqueStr = format_type(OpaqueType, State1),
+ Name = field_name(Elements, ErrorPat, FieldNames),
Msg = {opaque_match,
- [format_patterns(ErrorPat),
- format_type(ErrorType, State1),
- format_type(OpaqueType, State1)]},
+ ["record field" ++ Name ++
+ " declared to be of type " ++
+ format_type(ErrorType, State1),
+ OpaqueStr, OpaqueStr]},
State2 = state__add_warning(State1, ?WARN_OPAQUE,
Tree, Msg),
{State2, Map1, t_none()};
@@ -1252,6 +1255,15 @@ handle_tuple(Tree, Map, State) ->
end
end.
+field_name(Elements, ErrorPat, FieldNames) ->
+ try
+ [Pat] = ErrorPat,
+ Take = lists:takewhile(fun(X) -> X =/= Pat end, Elements),
+ " " ++ format_atom(lists:nth(length(Take), FieldNames))
+ catch
+ _:_ -> ""
+ end.
+
%%----------------------------------------
%% Clauses
%%
@@ -1632,7 +1644,7 @@ bind_pat_vars([Pat|PatLeft], [Type|TypeLeft], Acc, Map, State, Rev) ->
TagAtom = cerl:atom_val(Tag),
case state__lookup_record(TagAtom, length(Left), State) of
error -> {false, t_tuple(length(Es))};
- {ok, Record} ->
+ {ok, Record, _FieldNames} ->
[_Head|AnyTail] = [t_any() || _ <- Es],
UntypedRecord = t_tuple([t_atom(TagAtom)|AnyTail]),
{not t_is_equal(Record, UntypedRecord), Record}
@@ -2160,7 +2172,7 @@ handle_guard_is_record(Guard, Map, Env, Eval, State) ->
TupleType =
case state__lookup_record(Tag, ArityMin1, State) of
error -> Tuple;
- {ok, Prototype} -> Prototype
+ {ok, Prototype, _FieldNames} -> Prototype
end,
Type = t_inf(TupleType, RecType, State#state.opaques),
case t_is_none(Type) of
@@ -2610,7 +2622,7 @@ bind_guard_case_clauses(Arg, Clauses, Map0, Env, Eval, State) ->
Map = join_maps_begin(Map0),
{GenMap, GenArgType} = bind_guard(Arg, Map, Env, dont_know, State),
bind_guard_case_clauses(GenArgType, GenMap, Arg, Clauses1, Map, Env, Eval,
- t_none(), [], State).
+ t_none(), [], [], State).
filter_fail_clauses([Clause|Left]) ->
case (cerl:clause_pats(Clause) =:= []) of
@@ -2629,7 +2641,7 @@ filter_fail_clauses([]) ->
[].
bind_guard_case_clauses(GenArgType, GenMap, ArgExpr, [Clause|Left],
- Map, Env, Eval, AccType, AccMaps, State) ->
+ Map, Env, Eval, AccType, AccMaps, Throws, State) ->
Pats = cerl:clause_pats(Clause),
{NewMap0, ArgType} =
case Pats of
@@ -2673,9 +2685,9 @@ bind_guard_case_clauses(GenArgType, GenMap, ArgExpr, [Clause|Left],
case (NewMap1 =:= none) orelse t_is_none(GenArgType) of
true ->
bind_guard_case_clauses(NewGenArgType, GenMap, ArgExpr, Left, Map, Env,
- Eval, AccType, AccMaps, State);
+ Eval, AccType, AccMaps, Throws, State);
false ->
- {NewAccType, NewAccMaps} =
+ {NewAccType, NewAccMaps, NewThrows} =
try
{NewMap2, GuardType} = bind_guard(Guard, NewMap1, Env, pos, State),
case t_is_none(t_inf(t_atom(true), GuardType)) of
@@ -2699,17 +2711,26 @@ bind_guard_case_clauses(GenArgType, GenMap, ArgExpr, [Clause|Left],
dont_know ->
ok
end,
- {t_sup(AccType, CType), [NewMap3|AccMaps]}
+ {t_sup(AccType, CType), [NewMap3|AccMaps], Throws}
catch
- throw:{fail, _What} -> {AccType, AccMaps}
+ throw:{fail, Reason} ->
+ Throws1 = case Reason of
+ none -> Throws;
+ _ -> Throws ++ [Reason]
+ end,
+ {AccType, AccMaps, Throws1}
end,
bind_guard_case_clauses(NewGenArgType, GenMap, ArgExpr, Left, Map, Env,
- Eval, NewAccType, NewAccMaps, State)
+ Eval, NewAccType, NewAccMaps, NewThrows, State)
end;
bind_guard_case_clauses(_GenArgType, _GenMap, _ArgExpr, [], Map, _Env, _Eval,
- AccType, AccMaps, _State) ->
+ AccType, AccMaps, Throws, _State) ->
case t_is_none(AccType) of
- true -> throw({fail, none});
+ true ->
+ case Throws of
+ [Throw|_] -> throw({fail, Throw});
+ [] -> throw({fail, none})
+ end;
false -> {join_maps_end(AccMaps, Map), AccType}
end.
@@ -3069,7 +3090,7 @@ state__add_warning(#state{warnings = Warnings, warning_mode = true} = State,
Ann = cerl:get_ann(Tree),
case Force of
true ->
- WarningInfo = {get_file(Ann),
+ WarningInfo = {get_file(Ann, State),
abs(get_line(Ann)),
State#state.curr_fun},
Warn = {Tag, WarningInfo, Msg},
@@ -3079,7 +3100,9 @@ state__add_warning(#state{warnings = Warnings, warning_mode = true} = State,
case is_compiler_generated(Ann) of
true -> State;
false ->
- WarningInfo = {get_file(Ann), get_line(Ann), State#state.curr_fun},
+ WarningInfo = {get_file(Ann, State),
+ get_line(Ann),
+ State#state.curr_fun},
Warn = {Tag, WarningInfo, Msg},
case Tag of
?WARN_CONTRACT_RANGE -> ok;
@@ -3207,7 +3230,8 @@ state__lookup_record(Tag, Arity, #state{records = Records}) ->
RecType =
t_tuple([t_atom(Tag)|
[FieldType || {_FieldName, _Abstr, FieldType} <- Fields]]),
- {ok, RecType};
+ FieldNames = [FieldName || {FieldName, _Abstr, _FieldType} <- Fields],
+ {ok, RecType, FieldNames};
error ->
error
end.
@@ -3477,6 +3501,12 @@ state__put_races(Races, State) ->
state__records_only(#state{records = Records}) ->
#state{records = Records}.
+-spec state__translate_file(file:filename(), state()) -> file:filename().
+
+state__translate_file(FakeFile, State) ->
+ #state{codeserver = CodeServer, module = Module} = State,
+ dialyzer_codeserver:translate_fake_file(CodeServer, Module, FakeFile).
+
%%% ===========================================================================
%%%
%%% Races
@@ -3548,9 +3578,11 @@ get_line([Line|_]) when is_integer(Line) -> Line;
get_line([_|Tail]) -> get_line(Tail);
get_line([]) -> -1.
-get_file([]) -> [];
-get_file([{file, File}|_]) -> File;
-get_file([_|Tail]) -> get_file(Tail).
+get_file([], _State) -> [];
+get_file([{file, FakeFile}|_], State) ->
+ state__translate_file(FakeFile, State);
+get_file([_|Tail], State) ->
+ get_file(Tail, State).
is_compiler_generated(Ann) ->
lists:member(compiler_generated, Ann) orelse (get_line(Ann) < 1).
@@ -3660,6 +3692,9 @@ map_pats(Pats) ->
fold_literals(TreeList) ->
[cerl:fold_literal(Tree) || Tree <- TreeList].
+format_atom(A) ->
+ format_cerl(cerl:c_atom(A)).
+
type(Tree) ->
Folded = cerl:fold_literal(Tree),
case cerl:type(Folded) of