[erlang-questions] Dialyzer and ets:fun2ms

Anthony Molinaro anthonym@REDACTED
Thu Jun 21 19:27:22 CEST 2012


I came across this same issue yesterday, anyone from the dialyzer team want
to comment on a better way to deal with records in matchspecs?

Thanks,

-Anthony

On Tue, May 22, 2012 at 01:39:10PM -0700, Geoff Cant wrote:
> Hi all, I have hit this problem with my code and dialyzer a few times now and wonder what everyone else does to avoid it.
> 
> I have record definitions with type specifications as follows:
> 
> > -module(rec_example).
> > 
> > -export([find_by_colour/1]).
> > 
> > -include_lib("stdlib/include/ms_transform.hrl").
> > 
> > -record(myrecord, {field = 0 :: integer(),
> >                    roses = red :: 'red' | 'blue'}).
> > 
> 
> I then add some functions that use ets matchspecs or a fun2ms transform and have to fill in fields with dummy values as required by the API (e.g. '_' and '$1'):
> 
> > find_by_colour(Colour) when is_atom(Colour) ->
> >     ets:lookup(myrecords, ets:fun2ms(fun (#myrecord{roses=C})
> >                                            when C =:= Colour ->
> >                                              object()
> >                                      end)).
> 
> 
> Dialyzer complains that this function can't succeed:
> 
> > rec_example.erl:10: Function find_by_colour/1 has no local return
> > rec_example.erl:11: Record construction #myrecord{field::'_',roses::'$1'} violates the declared type of field field::integer() and roses::'blue' | 'red'
> 
> 
> 
> To me this seems like reasonable code to want to write, but dialyzer hates it. The two (terrible) solutions I've found to avoid the dialyzer warnings are to add the dummy values to the record type spec:
> 
> > -record(myrecord, {field = 0 :: integer() | '_',
> >                    roses = red :: 'red' | 'blue' | '$1'}).
> 
> 
> Or to hide the record construction from dialyzer by constructing the matchspec using functions. First run fun2ms manually to get:
> 
> > [{#myrecord{field = '_',roses = '$1'},
> >   [{'=:=','$1',Colour}],
> >   ['$_']}]
> 
> 
> Which still complains, so you then do something far worse:
> 
> > [{list_to_tuple([myrecord, '_', '$1']),
> >   [{'=:=','$1',Colour}],
> >   ['$_']}]
> 
> 
> Clearly none of these options are good - what's a better way to have record type specs and matchspecs and no dialyzer warnings? Or is there something I'm missing that replaces my use of matchspecs and avoids the problem?
> 
> 
> Cheers,
> --
> Geoff Cant
> 
> 
> 
> 
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions

-- 
------------------------------------------------------------------------
Anthony Molinaro                           <anthonym@REDACTED>



More information about the erlang-questions mailing list