jeremyjh / dialyxir

Mix tasks to simplify use of Dialyzer in Elixir projects.
Apache License 2.0
1.69k stars 141 forks source link

Failed to parse warning when a function matches on a field not in the passed map #434

Open Sinc63 opened 3 years ago

Sinc63 commented 3 years ago

Precheck

Environment

Elixir 1.7.4 (compiled with Erlang/OTP 20)

Current behavior

Failed to parse warning: [{:"#", 1}, {:"{", 1}, {:atom_full, 1, '\'type\''}, {:":=", 1}, {:<, 1}, {:<, 1}, {:int, 1, 115}, {:":", 1}, {:int, 1, 8}, {:atom_part, 1, '/'}, {:atom_part, 1, 'i'}, {:atom_part, 1, 'n'}, {:atom_part, 1, 't'}, {:atom_part, 1, 'e'}, {:atom_part, 1, 'g'}, {:atom_part, 1, 'e'}, {:atom_part, 1, 'r'}, {:atom_part, 1, '-'}, {:atom_part, 1, 'u'}, {:atom_part, 1, 'n'}, {:atom_part, 1, 'i'}, {:atom_part, 1, 't'}, {:":", 1}, {:int, 1, 1}, {:",", 1}, {:int, 1, 101}, {:":", 1}, {:int, 1, 8}, {:atom_part, 1, '/'}, {:atom_part, 1, 'i'}, {:atom_part, 1, 'n'}, {:atom_part, 1, 't'}, {:atom_part, 1, 'e'}, {:atom_part, 1, 'g'}, {:atom_part, 1, 'e'}, {:atom_part, 1, 'r'}, {:atom_part, 1, '-'}, {:atom_part, 1, 'u'}, {:atom_part, 1, 'n'}, {:atom_part, 1, 'i'}, {:atom_part, 1, 't'}, {:":", 1}, {:int, 1, 1}, {:",", 1}, {:int, 1, 116}, {:":", 1}, {:int, 1, 8}, {:atom_part, 1, ...}, {:atom_part, ...}, {...}, ...]

Legacy warning: lib/field_mismatch.ex:5: The pattern #{'type':=<<115:8/integer-unit:1,101:8/integer-unit:1,116:8/integer-unit:1>>} can never match the type #{'mytype':=<<:24>>}



Warning, the error looks a little different if you give a name to the map in the header e.g. `%{type: "set"} = _my_map` or `= my_map`.
(Don't blame me for the _my_map instead of deleting the thing, my colleague did that!)

### Expected behavior
* A short description of the expected behavior.
No errors in the tool (because all of my code is perfect so yours should be too! ;-) ) 
Sinc63 commented 3 years ago

I did some digging. The dialyxir code uses Erlex to pretty_print the string, which ends up calling :parser.parse which returns {:error, {1, :parser, ['syntax error before: ', '\':\'']}}.

My conclusion is that either dialyzer is printing something that it shouldn't (like the actual character values in the parameter string instead of just <<_:24>>, or maybe the :1 after integer-unit), or that :parser.parse needs to learn a new syntax, either of which you are probably going to have push onto the Erlang folks, but I'm going to leave you to do that since I haven't a clue how or where to do that.

If you can get this fixed in Erlang I would bet you would be able to close a bunch of issues, if only you had sample code for them.