aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe/cerl
diff options
context:
space:
mode:
authorHans Bolinder <[email protected]>2016-09-16 11:54:57 +0200
committerHans Bolinder <[email protected]>2016-10-06 16:37:59 +0200
commit87a13c257bfd5a53b6803bc2d714afb13106c243 (patch)
treece5b5882e1889649c57ed3466d26c03ec3cfd92d /lib/hipe/cerl
parent5acfcf3758f89ba32d44807cd8cb406a55d39836 (diff)
downloadotp-87a13c257bfd5a53b6803bc2d714afb13106c243.tar.gz
otp-87a13c257bfd5a53b6803bc2d714afb13106c243.tar.bz2
otp-87a13c257bfd5a53b6803bc2d714afb13106c243.zip
dialyzer: Fix opaque bugs
t_from_form() sometimes returned a more general type than it should have done due to a bug in from_form_loop(): it stopped when the limit was exceeded, which could mean a collapsed type. Returning a type with smaller depth should fix this. is_specialization() now handles opaque types before unions, which should fix another problem. The bugs reported by Kostis.
Diffstat (limited to 'lib/hipe/cerl')
-rw-r--r--lib/hipe/cerl/erl_types.erl25
1 files changed, 14 insertions, 11 deletions
diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl
index 15f7b793a1..a6a7efb1de 100644
--- a/lib/hipe/cerl/erl_types.erl
+++ b/lib/hipe/cerl/erl_types.erl
@@ -3109,6 +3109,10 @@ is_specialization(?tuple_set(List1), ?tuple_set(List2)) ->
[sup_tuple_elements(T) || {_Arity, T} <- List2])
catch _:_ -> false
end;
+is_specialization(?opaque(_) = T1, T2) ->
+ is_specialization(t_opaque_structure(T1), T2);
+is_specialization(T1, ?opaque(_) = T2) ->
+ is_specialization(T1, t_opaque_structure(T2));
is_specialization(?union(List1)=T1, ?union(List2)=T2) ->
case specialization_union2(T1, T2) of
{yes, Type1, Type2} -> is_specialization(Type1, Type2);
@@ -3124,10 +3128,6 @@ is_specialization(T1, ?union(List)) ->
{yes, Type} -> is_specialization(T1, Type);
no -> false
end;
-is_specialization(?opaque(_) = T1, T2) ->
- is_specialization(t_opaque_structure(T1), T2);
-is_specialization(T1, ?opaque(_) = T2) ->
- is_specialization(T1, t_opaque_structure(T2));
is_specialization(?var(_), _) -> exit(error);
is_specialization(_, ?var(_)) -> exit(error);
is_specialization(?none, _) -> false;
@@ -4482,28 +4482,31 @@ t_from_form1(Form, ET, Site, MR, V, C) ->
vtab = V,
tnames = TypeNames},
L = ?EXPAND_LIMIT,
- {T1, L1, C1} = from_form(Form, State, ?EXPAND_DEPTH, L, C),
+ {T0, L0, C0} = from_form(Form, State, ?EXPAND_DEPTH, L, C),
if
- L1 =< 0 ->
- from_form_loop(Form, State, 1, L, C1);
+ L0 =< 0 ->
+ {T1, _, C1} = from_form(Form, State, 1, L, C0),
+ from_form_loop(Form, State, 2, L, C1, T1);
true ->
- {T1, C1}
+ {T0, C0}
end.
initial_typenames({type, _MTA}=Site) -> [Site];
initial_typenames({spec, _MFA}) -> [];
initial_typenames({record, _MRA}) -> [].
-from_form_loop(Form, State, D, Limit, C) ->
+from_form_loop(Form, State, D, Limit, C, T0) ->
{T1, L1, C1} = from_form(Form, State, D, Limit, C),
Delta = Limit - L1,
if
- %% Save some time by assuming next depth will exceed the limit.
+ L1 =< 0 ->
+ {T0, C1};
Delta * 8 > Limit ->
+ %% Save some time by assuming next depth will exceed the limit.
{T1, C1};
true ->
D1 = D + 1,
- from_form_loop(Form, State, D1, Limit, C1)
+ from_form_loop(Form, State, D1, Limit, C1, T1)
end.
-spec from_form(parse_form(),