[eeps] Proposal for -type_assert

Michael Truog mjtruog@REDACTED
Fri Sep 12 19:45:05 CEST 2014


On 09/12/2014 03:45 AM, Hans Bolinder wrote:
> Hi,
>
> I've been pondering your idea for a while now, thinking along the
> lines that it should be possible to do without adding any special
> syntax. It might be possible to use -Wunderspecs (or even the not
> recommended -Wspecdiffs), but there seem to be several things that
> would need to be modified in the dialyzer_contracts module, though.
> I'll try to find some time to look into the details.
>
> BTW, it would be interesting to see how you've implemented the check.
> I couldn't find any examples (looked for nowarn_unused_function), but
> I only downloaded CloudI.

I haven't used nowarn_unused_function to provide a type assertion within the CloudI source code.  A module which I would want a type assertion in (once the httpc:method() type exists, I had thought it already exists) is https://github.com/CloudI/CloudI/blob/develop/src/lib/cloudi_service_http_client/src/cloudi_service_http_client.erl#L520-L535 .  You can see from the module that there is an implicit assumption that "method() :: head | get | put | post | trace | options | delete" which is valid based on the current inets documentation at http://www.erlang.org/doc/man/httpc.html .  A concrete example for what I had meant by "a dirty trick" is the test module at the end of the email.  That approach required using -Wspecdiffs which generates a lot of noise that isn't helpful (and isn't recommended as you mentioned).  So a -type_assert could make this much clearer and the developer could see a basic type assertion fail to understand that assumptions within a module are no longer 
true, making it easier to update the source code.

I started thinking about this problem when using the riak erlang client source code which caused me to create the code below:
-include_lib("riakc/include/riakc.hrl").
-type index_results_check() :: {index_results_v1,
                                 [binary()] | 'undefined',
                                 [{integer() | binary(),
                                   binary()}] | 'undefined',
                                 'undefined' | binary()}.
-export_type([index_results/0]).
% code that uses index_results_check() instead of index_results() is below

That approach can provide something similar, but depends on a local type being hard-coded, replicating an external module's type.  That doesn't necessarily work in the cloudi_service_http_client.erl file but may be made to work by adding more functions (unnecessary complication).  So the suggestion to add -type_assert was just due to not seeing a better path to making sure dialyzer would break.  I haven't attempted to implement changes to support -type_assert syntax and I am not sure about the changes required.  I can help with the changes, but I thought it was important to make sure the addition is agreeable before changes are created.

Thanks,
Michael

>
> Best regards,
>
> Hans Bolinder, Erlang/OTP team, Ericsson
>
% run with:
% erlc +debug_info test.erl
% dialyzer -Wspecdiffs test.beam
-module(test).

-export([test/0]).

test() ->
     ok.

% would normally be an external module's type to assert on,
% making sure that dialyzer will complain if the type changes
%-type method() :: head | get | put | post | trace | options | delete.
-type method() :: head | get | put | post | trace | options | delete | string().

-compile({nowarn_unused_function,
           [{httpc_method_assert, 1},
            {httpc_method_check, 1}]}).

-spec httpc_method_assert(head | get | put | post | trace | options | delete) ->
     ok.
httpc_method_assert(T) ->
     ok = httpc_method_check(T).

-spec httpc_method_check(method()) ->
     ok.
httpc_method_check(_) ->
     ok.




More information about the eeps mailing list