Quieting dialyzer for unmatched Logger calls

I have Logger lines like:

Logger.debug("Unhandled menu/4 for module: #{inspect view_module}")

And when dialyzed it returns:

layout_view.ex:34: Expression produces a value of type 'ok' | {'error',_}, but this value is unmatched

Should I really just write ok = in front of those lines everywhere or is there a better way to silence those, and better yet why is it complaining about them but not other unmatched areas either?

1 Like

I can’t explain right now, why other situations aren’t complained about. Perhaps you are piping the results somewhere?

So, there are some ways to silence these warnings:

  1. :ok = Logger.…, this will crash your process when Logger can’t log.
  2. _ = Logger.…, your process will continue regardless of the result of the call
  3. You can put a module attribute @dialyzer which configures dialyzer on the fly for a certain module, but I am unsure how you need to set it, to actually disable that particular warning.

Also there has been some discussion about this on elixirs issue-tracker, but thats been very short:

1 Like

It appears you’re running dialyzer with unmatched_returns option turned on. From the docs, this option:

Include warnings for function calls which ignore a structured return value or do not match against one of many possible return value(s).

It looks like that check is an opt-in, so you must have specified it somewhere (or maybe your dialyzer tool, e.g. dialyxir includes that option by default).

So other than explicitly matching every call (e.g. with _ = Logger.debug(...)), you can also consider removing that option.

I do indeed use dialyxir, and I actually prefer the option as it has caught a few things that should have been caught. I just wish there were a way to have it ignore a specific function return (or a module’s worth of functions).

From what I can tell, dialyzer doesn’t support unmatched_returns (since that option is an explicit opt-in). It might be possible to hack dialyxir to support it, since it could filter away needless messages. It would be a hacky solution, so not sure if it’s worth doing, but you may consider discussing it with Jeremy.

As it is, your errors are a consequence of the unmatched_returns option. If you want to use the option, you’ll need to handle these errors :slight_smile:

You can override the default warning flags that Dialyxir specifies in your mix.exs config file. Then you can exclude the unmatched_returns flag.

def project do
  [
    dialyzer: [flags: ["-Werror_handling", "-Wrace_conditions", "-Wunderspecs"]]
  ]
end

The default flags for Dialyxir are “-Wunmatched_returns”, “-Werror_handling”, “-Wrace_conditions”, “-Wunderspecs”.

I do not like to silence unmatched returns in general. Sometimes I actually miss to assign the result of a function call to a variable, or I have an effectfull operation that uses :ok and :error to communicate success. If an error happens those were hard to find, but dialyzers warnung about the unmatched returns can give you a hint in such cases.

2 Likes

Ditto, I’m a fan of tight detailed warnings like that, it has caught things that I’ve missed before.

Wondering what approach you took? I like to use dialyzer and Logger, and I can life with _ = Logger.error... but it is kinda ugly.

I was considering just wrapping Logger in a module so that I can expose a clean interface that does not require the _ =.

Another approach is to add the warnings into a local dialyzer.ignore-warnings file and config project in mix.exs

def project do
    [
... 
      dialyzer: [
        ignore_warnings: "dialyzer.ignore-warnings"
      ]
...
  end

I think there’s value in unmatched_return when there’s actually something to match against.

{a, b} = some_func()

but not really a fan of it when you don’t care about the return type

Logger.info(...)

Side effects have clear use cases and it would be awesome to figure out a way to support this use case while still not hacking a _ = to support it. Might there be an easy fix in dialyzer itself to support something like that?