Being able to parametrize types ([pos_integer()]) is a critical feature of dialyzer. Support for parametrization is extended to some of remote types (:queue.queue(pos_integer())) but unfortunately not to all of them.
One I miss it the most ability to parametrize Enum (Enum.t(pos_integer())).
Parameterized types for protocols can be useful for documentation but I don't believe they will help dialyzer analysis.
@ericmj they should help once protocols are consolidated, which are most of the cases now.
It won't help with protocols themselves, but it should with things that use them. For example, we could make spec for Enum.map to be @spec map(t(a), (a -> b)) :: t(b). It is my understanding, it would improve analysis in places where Enum.map is used (but not for Enum.map itself - that's perfectly fine).
@josevalim Do we consolidate the typespecs as well? Otherwise I don't think Dialyzer can make the connection since the type has to be based on term: @type t(inner) :: term.
@ericmj that will be part of the work that needs to be done. :) Yes.
Can you elaborate on how would that work?
We know the shape of the types we dispatch on, so we can leverage that and
consolidate it in the same way we consolidate dispatch. However, for things
Jos茅 Valimwww.plataformatec.com.br
http://www.plataformatec.com.br/Founder and Director of R&D
How do we know the shape of the types we dispatch on, do you mean we should assume that ImplModule.t is the type? What if the implementation type has a different number of parameters?
We will need a way to declare that the protocol type is parameterized.
Jos茅 Valimwww.plataformatec.com.br
http://www.plataformatec.com.br/Founder and Director of R&D
Here is an idea.
Protocol might use a module attribute @typeprotocol (or @type_protocol) or a macro to define the signature of the types; and the implementation might optionally define the types specified in the protocol using the regular @type syntax. During the consolidation process, the types defined in the protocol would be generated by inspecting the typespecs of the different implementations.
Here is an example:
defprotocol MyProtocol do
@typeprotocol t()
@typeprotocol t(my_type)
@spec my_fun(t) :: boolean
def my_fun(term)
end
defimpl MyProtocol, for: Foo do
@type t(a) :: list(a)
def my_fun(term) do
true
end
end
Thoughts?
@fertapric that's a step in the right direction. The only issue is that @type/@spec/@opaque/@typep are specialish and I wouldn't want to introduce another special module attribute. But we could do it with something like:
defprotocol MyProtocol do
@type t()
@type t(my_type)
@protocol_types t: 0, t: 1
@spec my_fun(t) :: boolean
def my_fun(term)
end
Or something of sorts.
Most helpful comment
@fertapric that's a step in the right direction. The only issue is that
@type/@spec/@opaque/@typepare specialish and I wouldn't want to introduce another special module attribute. But we could do it with something like:Or something of sorts.