aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStavros Aronis <[email protected]>2011-11-30 20:19:31 +0100
committerStavros Aronis <[email protected]>2011-12-01 11:55:09 +0100
commit9949c1e03cdde87548371d5a9b53a997e3088dc6 (patch)
treeae512f43e1e7fb0b0160b641ff586579bd93e965
parent0290bed50ccbba067619c5829b0a090a8a60a2ff (diff)
downloadotp-9949c1e03cdde87548371d5a9b53a997e3088dc6.tar.gz
otp-9949c1e03cdde87548371d5a9b53a997e3088dc6.tar.bz2
otp-9949c1e03cdde87548371d5a9b53a997e3088dc6.zip
Fix crash in Dialyzer
Variable substitution was not generalizing any unknown variables.
-rw-r--r--lib/dialyzer/src/dialyzer_typesig.erl3
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/maybe_improper.erl7
-rw-r--r--lib/hipe/cerl/erl_types.erl37
3 files changed, 25 insertions, 22 deletions
diff --git a/lib/dialyzer/src/dialyzer_typesig.erl b/lib/dialyzer/src/dialyzer_typesig.erl
index 92868b6878..4268814859 100644
--- a/lib/dialyzer/src/dialyzer_typesig.erl
+++ b/lib/dialyzer/src/dialyzer_typesig.erl
@@ -2046,8 +2046,7 @@ lookup_type(Key, Map) ->
%% case cerl:is_literal(Key) of
%% true -> t_from_term(cerl:concrete(Key));
%% false ->
- Subst = t_subst(Key, Map),
- t_sup(Subst, Subst).
+ t_subst(Key, Map).
%% end.
mk_var(Var) ->
diff --git a/lib/dialyzer/test/small_SUITE_data/src/maybe_improper.erl b/lib/dialyzer/test/small_SUITE_data/src/maybe_improper.erl
new file mode 100644
index 0000000000..1743d81493
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/maybe_improper.erl
@@ -0,0 +1,7 @@
+-module(maybe_improper).
+
+-export([s/1]).
+
+-spec s(maybe_improper_list(X,Y)) -> {[X], maybe_improper_list(X,Y)}.
+s(A) ->
+ lists:split(2,A).
diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl
index 0ff827ac37..387690df43 100644
--- a/lib/hipe/cerl/erl_types.erl
+++ b/lib/hipe/cerl/erl_types.erl
@@ -2533,29 +2533,26 @@ findfirst(N1, N2, U1, B1, U2, B2) ->
t_subst(T, Dict) ->
case t_has_var(T) of
- true -> t_subst(T, Dict, fun(X) -> X end);
+ true -> t_subst_aux(T, Dict);
false -> T
end.
-spec subst_all_vars_to_any(erl_type()) -> erl_type().
subst_all_vars_to_any(T) ->
- case t_has_var(T) of
- true -> t_subst(T, dict:new(), fun(_) -> ?any end);
- false -> T
- end.
+ t_subst(T, dict:new()).
-t_subst(?var(Id) = V, Dict, Fun) ->
+t_subst_aux(?var(Id), Dict) ->
case dict:find(Id, Dict) of
- error -> Fun(V);
+ error -> ?any;
{ok, Type} -> Type
end;
-t_subst(?list(Contents, Termination, Size), Dict, Fun) ->
- case t_subst(Contents, Dict, Fun) of
+t_subst_aux(?list(Contents, Termination, Size), Dict) ->
+ case t_subst_aux(Contents, Dict) of
?none -> ?none;
NewContents ->
%% Be careful here to make the termination collapse if necessary.
- case t_subst(Termination, Dict, Fun) of
+ case t_subst_aux(Termination, Dict) of
?nil -> ?list(NewContents, ?nil, Size);
?any -> ?list(NewContents, ?any, Size);
Other ->
@@ -2563,17 +2560,17 @@ t_subst(?list(Contents, Termination, Size), Dict, Fun) ->
?list(NewContents, NewTermination, Size)
end
end;
-t_subst(?function(Domain, Range), Dict, Fun) ->
- ?function(t_subst(Domain, Dict, Fun), t_subst(Range, Dict, Fun));
-t_subst(?product(Types), Dict, Fun) ->
- ?product([t_subst(T, Dict, Fun) || T <- Types]);
-t_subst(?tuple(?any, ?any, ?any) = T, _Dict, _Fun) ->
+t_subst_aux(?function(Domain, Range), Dict) ->
+ ?function(t_subst_aux(Domain, Dict), t_subst_aux(Range, Dict));
+t_subst_aux(?product(Types), Dict) ->
+ ?product([t_subst_aux(T, Dict) || T <- Types]);
+t_subst_aux(?tuple(?any, ?any, ?any) = T, _Dict) ->
T;
-t_subst(?tuple(Elements, _Arity, _Tag), Dict, Fun) ->
- t_tuple([t_subst(E, Dict, Fun) || E <- Elements]);
-t_subst(?tuple_set(_) = TS, Dict, Fun) ->
- t_sup([t_subst(T, Dict, Fun) || T <- t_tuple_subtypes(TS)]);
-t_subst(T, _Dict, _Fun) ->
+t_subst_aux(?tuple(Elements, _Arity, _Tag), Dict) ->
+ t_tuple([t_subst_aux(E, Dict) || E <- Elements]);
+t_subst_aux(?tuple_set(_) = TS, Dict) ->
+ t_sup([t_subst_aux(T, Dict) || T <- t_tuple_subtypes(TS)]);
+t_subst_aux(T, _Dict) ->
T.
%%-----------------------------------------------------------------------------