From 050d93682e07e0c50667dbfb1468389078b776f2 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 18 Aug 2015 14:54:29 +0200 Subject: dialyzer: Fix a bug concerning parameterized opaque types The example is provided by James Fish in http://erlang.org/pipermail/erlang-questions/2014-December/082204.html. Note that warnings with text such as "the _ variable breaks opaqueness" are still possible. --- .../test/opaque_SUITE_data/src/para/myqueue.erl | 17 +++++++++++++++++ .../test/opaque_SUITE_data/src/para/myqueue_params.erl | 15 +++++++++++++++ lib/hipe/cerl/erl_types.erl | 12 ++++++++---- 3 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 lib/dialyzer/test/opaque_SUITE_data/src/para/myqueue.erl create mode 100644 lib/dialyzer/test/opaque_SUITE_data/src/para/myqueue_params.erl diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/para/myqueue.erl b/lib/dialyzer/test/opaque_SUITE_data/src/para/myqueue.erl new file mode 100644 index 0000000000..0f76680464 --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/src/para/myqueue.erl @@ -0,0 +1,17 @@ +-module(myqueue). + +-export([new/0, in/2]). + +-record(myqueue, {queue = queue:new() :: queue:queue({integer(), _})}). + +-opaque myqueue(Item) :: #myqueue{queue :: queue:queue({integer(), Item})}. + +-export_type([myqueue/1]). + +-spec new() -> myqueue(_). +new() -> + #myqueue{queue=queue:new()}. + +-spec in(Item, myqueue(Item)) -> myqueue(Item). +in(Item, #myqueue{queue=Q}) -> + #myqueue{queue=queue:in({1, Item}, Q)}. diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/para/myqueue_params.erl b/lib/dialyzer/test/opaque_SUITE_data/src/para/myqueue_params.erl new file mode 100644 index 0000000000..8d766b7804 --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/src/para/myqueue_params.erl @@ -0,0 +1,15 @@ +-module(myqueue_params). + +-export([new/0, in/2]). + +-record(myqueue_params, {myqueue = myqueue:new() :: myqueue:myqueue(integer())}). + +-type myqueue_params() :: #myqueue_params{myqueue :: + myqueue:myqueue(integer())}. +-spec new() -> myqueue_params(). +new() -> + #myqueue_params{myqueue=myqueue:new()}. + +-spec in(integer(), myqueue_params()) -> myqueue_params(). +in(Item, #myqueue_params{myqueue=Q} = P) when is_integer(Item) -> + P#myqueue_params{myqueue=myqueue:in(Item, Q)}. diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl index 25cf1a7ae1..a28dfb9e05 100644 --- a/lib/hipe/cerl/erl_types.erl +++ b/lib/hipe/cerl/erl_types.erl @@ -4244,9 +4244,8 @@ type_from_form(Name, Args, TypeNames, ET, M, MR, V, D, L) -> Rep2 = case t_is_none(Rep1) of true -> Rep1; false -> - Args2 = [subst_all_vars_to_any(ArgType) || - ArgType <- ArgTypes], - t_opaque(Module, Name, Args2, Rep1) + ArgTypes2 = subst_all_vars_to_any_list(ArgTypes), + t_opaque(Module, Name, ArgTypes2, Rep1) end, {Rep2, L2}; error -> @@ -4298,7 +4297,9 @@ remote_from_form(RemMod, Name, Args, TypeNames, ET, M, MR, V, D, L) -> NewRep1 = choose_opaque_type(NewRep, Type), NewRep2 = case t_is_none(NewRep1) of true -> NewRep1; - false -> t_opaque(Mod, Name, ArgTypes, NewRep1) + false -> + ArgTypes2 = subst_all_vars_to_any_list(ArgTypes), + t_opaque(Mod, Name, ArgTypes2, NewRep1) end, {NewRep2, L2}; error -> @@ -4313,6 +4314,9 @@ remote_from_form(RemMod, Name, Args, TypeNames, ET, M, MR, V, D, L) -> end end. +subst_all_vars_to_any_list(Types) -> + [subst_all_vars_to_any(Type) || Type <- Types]. + %% Opaque types (both local and remote) are problematic when it comes %% to the limits (TypeNames, D, and L). The reason is that if any() is %% substituted for a more specialized subtype of an opaque type, the -- cgit v1.2.3