aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe/cerl
diff options
context:
space:
mode:
authorHans Bolinder <[email protected]>2016-09-22 10:36:14 +0200
committerHans Bolinder <[email protected]>2016-10-06 16:37:59 +0200
commit5ac2943cee51f0f9e453243bb94e637378d7c838 (patch)
tree3cdf1b98d80d8506c79732fe994db6ea8a537c6f /lib/hipe/cerl
parent87a13c257bfd5a53b6803bc2d714afb13106c243 (diff)
downloadotp-5ac2943cee51f0f9e453243bb94e637378d7c838.tar.gz
otp-5ac2943cee51f0f9e453243bb94e637378d7c838.tar.bz2
otp-5ac2943cee51f0f9e453243bb94e637378d7c838.zip
dialyzer: Fix opaque bug
The "decoration" of opaque types works better than before when opaque types are used by other opaque types.
Diffstat (limited to 'lib/hipe/cerl')
-rw-r--r--lib/hipe/cerl/erl_types.erl82
1 files changed, 40 insertions, 42 deletions
diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl
index a6a7efb1de..9ef119ba46 100644
--- a/lib/hipe/cerl/erl_types.erl
+++ b/lib/hipe/cerl/erl_types.erl
@@ -611,9 +611,13 @@ t_decorate_with_opaque(T1, T2, Opaques) ->
false -> T1;
true ->
R = decorate(T1, T, Opaques),
- ?debug(case catch t_is_equal(t_unopaque(R), t_unopaque(T1)) of
- true -> ok;
- false ->
+ ?debug(case catch
+ not t_is_equal(t_unopaque(R), t_unopaque(T1))
+ orelse
+ t_is_equal(T1, T) andalso not t_is_equal(T1, R)
+ of
+ false -> ok;
+ _ ->
io:format("T1 = ~p,\n", [T1]),
io:format("T2 = ~p,\n", [T2]),
io:format("O = ~p,\n", [Opaques]),
@@ -642,7 +646,6 @@ decorate(?tuple_set(List), ?tuple_set(L), Opaques) ->
decorate(?union(List), T, Opaques) when T =/= ?any ->
?union(L) = force_union(T),
union_decorate(List, L, Opaques);
-decorate(?opaque(_)=T, _, _Opaques) -> T;
decorate(T, ?union(L), Opaques) when T =/= ?any ->
?union(List) = force_union(T),
union_decorate(List, L, Opaques);
@@ -656,7 +659,7 @@ decorate_with_opaque(Type, ?opaque(Set2), Opaques) ->
case decoration(set_to_list(Set2), Type, Opaques, [], false) of
{[], false} -> Type;
{List, All} when List =/= [] ->
- NewType = ?opaque(ordsets:from_list(List)),
+ NewType = sup_opaque(List),
case All of
true -> NewType;
false -> t_sup(NewType, Type)
@@ -670,9 +673,10 @@ decoration([#opaque{struct = S} = Opaque|OpaqueTypes], Type, Opaques,
case not IsOpaque orelse t_is_none(I) of
true -> decoration(OpaqueTypes, Type, Opaques, NewOpaqueTypes0, All);
false ->
- NewOpaque = Opaque#opaque{struct = decorate(I, S, Opaques)},
+ NewI = decorate(I, S, Opaques),
+ NewOpaque = combine(NewI, [Opaque]),
NewAll = All orelse t_is_equal(I, Type),
- NewOpaqueTypes = [NewOpaque|NewOpaqueTypes0],
+ NewOpaqueTypes = NewOpaque ++ NewOpaqueTypes0,
decoration(OpaqueTypes, Type, Opaques, NewOpaqueTypes, NewAll)
end;
decoration([], _Type, _Opaques, NewOpaqueTypes, All) ->
@@ -2991,27 +2995,21 @@ inf_collect(_T1, [], _Opaques, OpL) ->
OpL.
combine(S, T1, T2) ->
- #opaque{mod = Mod1, name = Name1, args = Args1} = T1,
- #opaque{mod = Mod2, name = Name2, args = Args2} = T2,
- Comb1 = comb(Mod1, Name1, Args1, S, T1),
- case is_compat_opaque_names({Mod1, Name1, Args1}, {Mod2, Name2, Args2}) of
- true -> Comb1;
- false -> Comb1 ++ comb(Mod2, Name2, Args2, S, T2)
+ case is_compat_opaque_names(T1, T2) of
+ true -> combine(S, [T1]);
+ false -> combine(S, [T1, T2])
end.
-comb(Mod, Name, Args, S, T) ->
- case can_combine_opaque_names(Mod, Name, Args, S) of
- true ->
- ?opaque(Set) = S,
- Set;
- false ->
- [T#opaque{struct = S}]
- end.
+combine(?opaque(Set), Ts) ->
+ [comb2(O, T) || O <- Set, T <- Ts];
+combine(S, Ts) ->
+ [T#opaque{struct = S} || T <- Ts].
-can_combine_opaque_names(Mod1, Name1, Args1,
- ?opaque([#opaque{mod = Mod2, name = Name2, args = Args2}])) ->
- is_compat_opaque_names({Mod1, Name1, Args1}, {Mod2, Name2, Args2});
-can_combine_opaque_names(_, _, _, _) -> false.
+comb2(O, T) ->
+ case is_compat_opaque_names(O, T) of
+ true -> O;
+ false -> T#opaque{struct = ?opaque(set_singleton(O))}
+ end.
%% Combining two lists this way can be very time consuming...
%% Note: two parameterized opaque types are not the same if their
@@ -3020,32 +3018,27 @@ inf_opaque(Set1, Set2, Opaques) ->
List1 = inf_look_up(Set1, Opaques),
List2 = inf_look_up(Set2, Opaques),
List0 = [combine(Inf, T1, T2) ||
- {Is1, ModNameArgs1, T1} <- List1,
- {Is2, ModNameArgs2, T2} <- List2,
- not t_is_none(Inf = inf_opaque_types(Is1, ModNameArgs1, T1,
- Is2, ModNameArgs2, T2,
- Opaques))],
- List = lists:sort(lists:append(List0)),
+ {Is1, T1} <- List1,
+ {Is2, T2} <- List2,
+ not t_is_none(Inf = inf_opaque_types(Is1, T1, Is2, T2, Opaques))],
+ List = lists:append(List0),
sup_opaque(List).
%% Optimization: do just one lookup.
inf_look_up(Set, Opaques) ->
- [{Opaques =:= 'universe' orelse inf_is_opaque_type2(T, Opaques),
- {M, N, Args}, T} ||
- #opaque{mod = M, name = N, args = Args} = T <- set_to_list(Set)].
+ [{Opaques =:= 'universe' orelse inf_is_opaque_type2(T, Opaques), T} ||
+ T <- set_to_list(Set)].
inf_is_opaque_type2(T, {match, Opaques}) ->
is_opaque_type2(T, Opaques);
inf_is_opaque_type2(T, Opaques) ->
is_opaque_type2(T, Opaques).
-inf_opaque_types(IsOpaque1, ModNameArgs1, T1,
- IsOpaque2, ModNameArgs2, T2, Opaques) ->
+inf_opaque_types(IsOpaque1, T1, IsOpaque2, T2, Opaques) ->
#opaque{struct = S1}=T1,
#opaque{struct = S2}=T2,
case
- Opaques =:= 'universe' orelse
- is_compat_opaque_names(ModNameArgs1, ModNameArgs2)
+ Opaques =:= 'universe' orelse is_compat_opaque_names(T1, T2)
of
true -> t_inf(S1, S2, Opaques);
false ->
@@ -3059,10 +3052,15 @@ inf_opaque_types(IsOpaque1, ModNameArgs1, T1,
end
end.
-is_compat_opaque_names(ModNameArgs, ModNameArgs) -> true;
-is_compat_opaque_names({Mod,Name,Args1}, {Mod,Name,Args2}) ->
- is_compat_args(Args1, Args2);
-is_compat_opaque_names(_, _) -> false.
+is_compat_opaque_names(Opaque1, Opaque2) ->
+ #opaque{mod = Mod1, name = Name1, args = Args1} = Opaque1,
+ #opaque{mod = Mod2, name = Name2, args = Args2} = Opaque2,
+ case {{Mod1, Name1, Args1}, {Mod2, Name2, Args2}} of
+ {ModNameArgs, ModNameArgs} -> true;
+ {{Mod, Name, Args1}, {Mod, Name, Args2}} ->
+ is_compat_args(Args1, Args2);
+ _ -> false
+ end.
is_compat_args([A1|Args1], [A2|Args2]) ->
is_compat_arg(A1, A2) andalso is_compat_args(Args1, Args2);