eidge
Dialyzer - Function has no local return
Hello guys,
When running dialyzer on this function, it complains that the function get has no local return and that build_forecast will never be called.
def get(%Params{} = params, options \\ []) do http_options = Keyword.merge([timeout: 20000], options) file_url = PathBuilder.path_for(params)
case fetch(file_url, http_options) do {:ok, forecast_grib2} -> {:ok, build_forecast(params, forecast_grib2)} {:error, explanation} -> {:error, explanation} end end
defp build_forecast(params, grib2) do %__MODULE__{ params: params, data: grib2 } end
I can’t quite understand what it is trying to tell me, as I manually tested and build_forecast gets called.
Full file here:
Any ideas?
Thanks
Most Liked
sasajuric
Usually, when you see a has no local return, it means that the cause is an error deeper in the stack. It should be one of the subsequently reported errors.
In this case, your error is The call 'Elixir.Timex':to_date(#{}) breaks the contract ('Elixir.Timex.Convertable') -> 'Elixir.Timex.Date':t() | {'error',term()}
If you look closer, and keep in mind that dialyzer uses Erlang syntax, you can see that you’re passing a map (#{}), while the contract expects 'Elixir.Timex.Convertable'. In Erlang, single quotes denote an atom, so in Elixir syntax this means that according to typespec, Timex.to_date expects Timex.Convertable. I.e. it expects an alias constant, and not a map (which is probably a struct). In other words, a typespec of Timex.to_date is wrong, since the function takes a struct as the first argument (a thing to convert).
Looking at the master, I actually see that the typespec is correct, but it seems that the fix has been done recently. Perhaps you’re not using the latest version, or otherwise it’s not pushed to hex. If that’s the case, you can try using the latest master from GitHub.
sasajuric
Upgrading to Timex 2.2.1 will fix all issues. Once I updated the dep, I rebuilt the code, removed the PLT, generated it again, and there were no errors. I’m not familiar with dialyxir, so not sure if there’s a better way of refreshing PLT.
The root cause of the second error was again a malformed spec in older Timex. The place in your code that triggered it is here. Since Timex spec was wrong, Dialyzer concluded it will always fail, and hence all that call this function unconditionally will also always fail.
It’s unfortunate that dialyzer didn’t report this error, and I’m not quite sure why. Either way, I’ve traced it by starting from get/2 and commenting out parts of it until I narrowed it down to PathBuilder.path_for. A quick glance at PathBuilder revealed the usage of Timex so I suspected that might be the culprit. Substituting the line in question with an empty string "" removed the error, so it was clear that the problem was indeed in Timex. A quick look at its spec in the deps folder confirmed it.
As I said, the required fixes are already done here, so all you need to do is use the more recent version of Timex, rebuild your PLT, and you should be fine.
eidge
Just added you!
Thank you so much
The community is a big part of why I’m having great fun with Elixir.
eidge
That’s very reasonable timing 
Thanks for the quick response. Guess I’m still getting used to tracking weird errors in Elixir.
Mistery solved 
sudostack
Check this post out. I’ve not tried Dialyzer yet, but was just reading about it: http://learningelixir.joekain.com/elixir-type-safety/







