[erlang-questions] Tricking dialyzer with an opaque type

Tobias Lindahl <>
Mon Jul 3 15:56:14 CEST 2017


2017-06-30 15:50 GMT+02:00 Paul Guyot <>:

> Alex, Tobias,
>
> Indeed, the function constructs the set using gb_sets API and then the
> result is embedded in the module with erl_parse:abstract/1.
> The current solution consists in adding a call to an identity/1 function
> in the generated replacement code. This function is exported from the parse
> transform module of type fun(any()) -> any(). Since the parse transform is
> in another application, dialyzer seems to take its specification for
> granted (?). It's a cheaper equivalent of binary_to_term(term_to_binary(V)),
> although not free (it's still a remote call).
>

Sorry, I misunderstood.

If you are worried about the remote call, you can probably achieve the same
thing by having a local call and exporting the function. You need the
export to confuse Dialyzer enough to label it as any().


>
> Paul
>
> On 30 Jun 2017, at 15:29, Alex S. <> wrote:
>
> he is constructing it, after parse transform takes place.
>
> 30 июня 2017 г., в 14:27, Tobias Lindahl <>
> написал(а):
>
> It seems to me that the gb_sets:from_list/1 should give the correct type
> for your function even if the spec is not taken into account.
>
> In that case, the value you are getting warnings for comes from somewhere
> else. Could it be that you are deconstructing the opaque type somewhere?
>
>
> 2017-06-25 18:56 GMT+02:00 Paul Guyot <>:
>
>> Hello,
>>
>> I do have a parse transform that replaces the body of a 0-arity function
>> with its result, as evaluated at compile time.
>> I am looking for a way to avoid an opaque violation warning from dialyzer
>> when this function returns, say, a gb_sets:set(). The spec is properly
>> copied into the parsed tree, but dialyzer just ignores it.
>>
>> Typically, such a function would load data from a file and create a
>> gb_sets:set() from this data.
>>
>> -spec f() -> gb_sets:set(unicode:unicode_binary()).
>> f() ->
>>         {ok, Content} = file:read_file(?FILENAME),
>>         List0 = binary:split(Content, <<"\n">>, [global]),
>>         List1 = lists:filter(fun(W) -> W =/= <<>> end, List0),
>>         gb_sets:from_list(List1).
>>
>> With the parse_transform, dialyzer complains on usage, e.g. :
>>
>> [warning] some_module.erl:123 the call gb_sets:add(<VALUE>,Var::{1..1114111,{_,_,_}})
>> does not have an opaque term of type gb_sets:set(_) as 2nd argument
>>
>> Yet, of course, some_module.erl does not violate the opacity of
>> gb_sets:set() itself.
>> I can trick dialyzer with an expensive identity function:
>>
>>         gb_sets:add(Value, binary_to_term(term_to_binary(Var)))
>>
>> Any better idea?
>>
>> Paul
>> _______________________________________________
>> erlang-questions mailing list
>> 
>> http://erlang.org/mailman/listinfo/erlang-questions
>>
>
> _______________________________________________
> erlang-questions mailing list
> 
> http://erlang.org/mailman/listinfo/erlang-questions
>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20170703/ce1a52e0/attachment.html>


More information about the erlang-questions mailing list