tosbourn
Help understanding dialyzer output of: "The call ... will never return since it differs in the 1st argument from the success typing arguments"
I’ll be honest, there is a lot about dialyzer output that confuses me.
Right now I’m confused by “The call … will never return since it differs in the 1st argument from the success typing arguments”
file.ex:23: The call ‘Elixir.Timber’:add_context(#{‘struct’:=‘Elixir.Timber.Contexts.UserContext’, ‘email’:=, ‘id’:=, ‘name’:=‘nil’}) will never return since it differs in the 1st argument from the success typing arguments: (maybe_improper_list())
My reading of that error is that dialyzer thinks that me calling Timber.add_context will fail because I’m sending in a struct and it is expecting input of maybe_improper_list.
Even though I know this works and Timber is an external dependancy, I wanted to understand why it wanted some type of list. I cracked into their code. Here is the code for add_context/1;
@doc """
Adds a context entry to the stack. See `Timber::Contexts::CustomContext` for examples.
"""
@spec add_context(map | Keyword.t | Context.context_element) :: :ok
def add_context(data) do
CurrentContext.load()
|> Context.add(data)
|> CurrentContext.save()
end
There is no explicit mention of maybe_improper_list, and as far as I know map covers the fact I’m passing in a struct.
Am I interpreting the output correctly? Any help would be much appreciated.
Most Liked
gon782
Same here. Mostly I think if you use it from the beginning you’re always reminded to keep it neat. I started using VS Code in the middle of working on a side project that was already underway for some time (before I got involved) and was bombarded with warnings that just came from undisciplined changes without dialyzing, etc..
It’s too easy to fall behind when you have to do something manually and I think everyone who’s used dialyzer has gotten like 2 screens full of trash thrown at them and it’s easy to become conditioned into not using it because of that. ElixirLS says “We’ll do this little by little together and I’m sure it will be fine in the end” and I like that a lot. It’s more akin to using statically typed languages.
dom
I had a look - there’s a ton of issues with the typespecs in this project. For your specific problem, Dialyzer says that the typespec for add/2 is wrong:
lib/timber/context.ex:48: Invalid type specification for function 'Elixir.Timber.Context':add/2. The success typing is (_,maybe_improper_list()) -> any()
Which is in turn because the spec for sub-functions are wrong. For instance:
https://github.com/timberio/timber-elixir/blob/master/lib/timber/context.ex#L121
https://github.com/timberio/timber-elixir/blob/master/lib/timber/contexts/user_context.ex#L15
The user context spec says id is a string, but to_api_map takes it as an integer. Dialyzer infers this is impossible.
Or take insert/3:
https://github.com/timberio/timber-elixir/blob/master/lib/timber/context.ex#L83
It accepts an atom as the second argument, violating its own typespec a few lines above which says it must be a context struct.
So, at the end of the day the problem is the typespecs are wrong, causing Dialyzer to think that the functions will not work if you pass them a context struct. So it infers the “success type” is a list, because it’s the only thing that would work correctly according to the provided specs.
mbuhot
I’ve hit similar issues in libraries before. It’s frustrating when package authors add typespecs for documentation purposes, but don’t run dialyzer in CI to check that the code and specs agree.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









