Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failed to parse warning (SQL query as charlist instead of binary) #437

Open
smaximov opened this issue Aug 6, 2021 · 0 comments
Open

Failed to parse warning (SQL query as charlist instead of binary) #437

smaximov opened this issue Aug 6, 2021 · 0 comments

Comments

@smaximov
Copy link

smaximov commented Aug 6, 2021

Environment

  • Elixir & Erlang/OTP versions (elixir --version):

    Erlang/OTP 23 [erts-11.2.2.4] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [hipe]
    
    Elixir 1.11.4 (compiled with Erlang/OTP 23)
    
  • Which version of Dialyxir are you using? (cat mix.lock | grep dialyxir): 1.1.0

Current behavior

Consider this module (requires ecto/ecto_sql/postgrex to compile):

defmodule Repo do
  use Ecto.Repo,
    otp_app: :myapp,
    adapter: Ecto.Adapters.Postgres

  def fails_to_parse_dialyzer_warning do
    'SELECT do_something($1);' |> Repo.query!([1])
  end

  def parses_dialyzer_warning do
    'SELECT $1;' |> Repo.query!([1])
  end
end

The issue with this code is that SQL queries are passed as charlists, but Repo.query/2 expects a binary.

Running mix dialyzer yields:

lib/repo.ex:6:no_return
Function fails_to_parse_dialyzer_warning/0 has no local return.
________________________________________________________________________________
Please file a bug in https://github.com/jeremyjh/dialyxir/issues with this message.
Failed to parse warning:
[{:"(", 1}, {:atom_part, 1, '"'}, {:atom_part, 1, 'S'}, {:atom_part, 1, 'E'}, {:atom_part, 1, 'L'}, {:atom_part, 1, 'E'}, {:atom_part, 1, 'C'}, {:atom_part, 1, 'T'}, {:atom_part, 1, 'd'}, {:atom_part, 1, 'o'}, {:_, 1}, {:atom_part, 1, 's'}, {:atom_part, 1, 'o'}, {:atom_part, 1, 'm'}, {:atom_part,
1, 'e'}, {:atom_part, 1, 't'}, {:atom_part, 1, 'h'}, {:atom_part, 1, 'i'}, {:atom_part, 1, 'n'}, {:atom_part, 1, 'g'}, {:"(", 1}, {:atom_part, 1, '$'}, {:int, 1, 1}, {:")", 1}, {:atom_part, 1, ';'}, {:atom_part, 1, '"'}, {:",", 1}, {:"[", 1}, {:int, 1, 1}, {:"]", 1}, {:")", 1}]


Legacy warning:
lib/repo.ex:7: The call 'Elixir.Repo':'query!'("SELECT do_something($1);",[1]) will never return since it differs in the 1st argument from the success typing arguments: (binary(),[any()])
________________________________________________________________________________
lib/repo.ex:10:no_return
Function parses_dialyzer_warning/0 has no local return.
________________________________________________________________________________
lib/repo.ex:11:call
The function call will not succeed.

Repo.query!(:"\"SELECT$1;\"", [1])

will never return since the 1st arguments differ
from the success typing arguments:

(binary(), [any()])

There're two (maybe unrelated) problems with the result:

  1. In the warning emitted for parses_dialyzer_warning/0, the SQL query (a charlist) is formatted as an atom :"\"SELECT$1;\" (also note that the space between SELECT and $1 is missing).
  2. Dialyxir fails to parse the warning emitted for fails_to_parse_dialyzer_warning/0, but the only difference between the two functions are SQL queries they are using: one uses SELECT $1, the other — SELECT do_something_with($1).

Expected behavior

It gives two warnings similar to the warning emitted for parses_dialyzer_warning/0 (but with SQL queries formatted correctly as charlists).

Alternative outputs

--format dialyzer:

lib/repo.ex:6: Function fails_to_parse_dialyzer_warning/0 has no local return
lib/repo.ex:7: The call 'Elixir.Repo':'query!'("SELECT do_something($1);",[1]) will never return since it differs in the 1st argument from the success typing arguments: (binary(),[any()])
lib/repo.ex:10: Function parses_dialyzer_warning/0 has no local return
lib/repo.ex:11: The call 'Elixir.Repo':'query!'("SELECT $1;",[1]) will never return since it differs in the 1st argument from the success typing arguments: (binary(),[any()])

Note that SQL queries are displayed correctly as charlists (using Erlang syntax).

--format raw:

{:warn_return_no_exit, {'lib/repo.ex', 6}, {:no_return, [:only_normal, :fails_to_parse_dialyzer_warning, 0]}}
{:warn_failing_call, {'lib/repo.ex', 7}, {:call, [Repo, :query!, '("SELECT do_something($1);",[1])', [1], :only_sig, '(binary(),[any()])', '\#{\'num_rows\':=non_neg_integer(), \'rows\':=\'nil\' | [binary() | [any()]], atom()=>_}', {false, :none}]}}
{:warn_return_no_exit, {'lib/repo.ex', 10}, {:no_return, [:only_normal, :parses_dialyzer_warning, 0]}}
{:warn_failing_call, {'lib/repo.ex', 11}, {:call, [Repo, :query!, '("SELECT $1;",[1])', [1], :only_sig, '(binary(),[any()])', '\#{\'num_rows\':=non_neg_integer(), \'rows\':=\'nil\' | [binary() | [any()]], atom()=>_}', {false, :none}]}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant