elixirectodialyzertypespec

Dialyxir error order_by doesnt return Ecto.Query.t


I have this method

@spec modify_query(Ecto.Query.t) :: Ecto.Query.t
def modify_query(query) do
  # modifies a Ecto.Query.t
end

Then I chain that method with a query:

Item
|> where([active: true])
|> order_by([desc: :start])
|> modify_query

The code works correctly but apparently for dialyzer order_by is not returning a Ecto.Query.t because it complains with:

The call 'modify_query'... does not have a term of type atom() | 'Elixir.Ecto.Query':t() (with opaque subterms) as 1st argument

If I comment out # |> order_by([desc: :start]) then dialyzer doesnt complain

I have tested through iex the output of:

Item
|> where([active: true])
|> order_by([desc: :start])

and it says it's data type is Ecto.Query:

Term                                                                         
  #Ecto.Query<from r in Item, where: r.active == true, order_by: [desc: r.start]>
Data type                                                                    
  Ecto.Query

So how can dialyzer complains??


Solution

  • More info here https://elixirforum.com/t/dialyxir-error-when-using-ecto-query-t-as-function-argument/7491

    Basically, order_by is a macro and dialyxir complains about an opaque type.

    I think it's fixed in recent versions of Ecto but if you have this issue in older versions of Ecto you can fix it by swapping the calls:

    Item
    |> order_by([desc: :start])
    |> where([active: true])