1

Dialyzer complains about Phoenix models when they are set up in the usual way, i.e.

def changeset(model, params \\ :empty)
...

the params instruct how the model is to be updated, with :empty as a default to differentiate between a blank form submission with 'params' equal to an empty map.

Dialyzer warns:

The call 'Elixir.Backend.Plot':
changeset(x0@1::any(),'empty') will never return since it differs in the 2nd argument from the success typing arguments: 
(#{},#{})

if I remove the ':empty' default param the warning disappears.

Is there a spec which satisfies the type checker while keeping the usual default changeset function? Any hints or pointers?

kliew
  • 2,687
  • 1
  • 11
  • 25
user3264325
  • 185
  • 1
  • 6

1 Answers1

1

It's hard to advise you about exactly what you should do to deal with this since I don't know the exact type spec you're providing. However, I think if you mark that second parameter as potentially being an empty map it should work as you want.

Look here. It seems as if maps aren't specifically supported by dialyzer but there seems to be a relatively simple workaround. Make the specification #{ any() => any() } However, as is mentioned in that message it's not totally clear if that will work with empty maps or not.


EDIT:

It appears that I was a little bit unclear in my response. When I say "spec" I mean that annotation that you add above the function to tell dialyzer how you expect your function to behave. For example:

  @spec get_short_name(Path.t)::Path.t
  def get_short_name(path) when is_binary(path) do

If you haven't specified any @spec at all then that may be your issue.

In the case you specified above, I'd suggest that something like this may work:

@spec changeset(#{any() => any()}, #{any() => any()})::returntype
def changeset(model, params \\ :empty)

You'd want to modify returntype to be whatever type changeset returns and I can't tell from the fragment you posted what the type of model should be so I guessed it's a map. As I say, since I don't know the details of what you're doing with changeset and since you don't seem to have specified a @spec, it's sort of tough for me to say.

Onorio Catenacci
  • 14,322
  • 12
  • 75
  • 122
  • hey, there's no spec applied, it's just vanilla code. ideally i want to keep the :empty atom, which isn't an empty map obviously... – user3264325 Apr 07 '16 at 10:25
  • @user3264325 Look at my edit to the answer. By the way, really don't appreciate the downvote. – Onorio Catenacci Apr 07 '16 at 12:10
  • 1
    As @OnorioCatenacci suggests, there is somewhere a type specification for `changeset` which requires the second argument to be a map. If you also want/have to allow the atom `empty`, the specification should reflect that by being e.g. `map() | 'empty'`. – aronisstav Apr 07 '16 at 12:55
  • downvote was not me! (i don't really understand the interface, newish here, but double checked my profile, and in actual fact I never voted on anything here before : ) will investigate the edited reply and get back to you. thx again – user3264325 Apr 09 '16 at 11:51