Compiler warning "this clause cannot match because a previous clause"

Good morning

I’m seeing this warning at compile time and while I know what the issue is, the warning message doesn’t give me much to go on.

My situation (vastly simplified) is that I’ve got a module that implements various versions of a function. Let’s call that function parse_line/3. I also have some other versions of that function in a module (to be shared across different modules). Here’s the main module:

defmodule UseThisModule do 
  defmacro __using__(_opts) do
    quote do
      def parse_line("a", b, c), do: ...
      def parse_line(a, "b", c), do: ...
     end
  end
end

And here is the module that uses it:

defmodule NeedsThatModule do
  use UseThisModule

  def parse_lin("a", 234, _), do: ...

end

It’s pretty easy to see that the parse_line in NeedsThatModule is going to never be found because of the first one in UseThisModule. I understand that and I know how to deal with it. My problem is that in UseThisModule there are 10+ versions of parse_line/3 and in NeatModule there are 15+. The warning says, as expected:

“warning: this clause cannot match because a previous clause at line 4 always matches
neat_module.ex:2”

In my example, line 2 is where the “use” expression is found. Conceptually, I know what is going on, but given the sheer number of versions of the parse_line/3 function, it’s extremely painful to identify WHICH of the versions in UseThisModule is the one to check on.

I guess I’m looking for strategies to simplify this situation, or even better, a way to get more details in the warning.

At any rate, if this is unclear, let me know and I’ll try again :slight_smile:
thanks

Sounds like you want to pass location: :keep to quote, that may give you a better stack trace according to the docs.

To me this sounds like you have too many heads for parse_line, given that you’re struggling to keep track of them. Doubly-so because you’re apparently building more than one giant parse_line function.

1 Like

oh, perfect! I’ll look into this.

And yeah, there are a TON of heads for parse_line. We’re basically using them to parse lines without having to write more formal parsers. For example, we’ve got things like this:

# KEY/2323 VALUE/something

def parse_line(<<"KEY/", the_key::binary_size(4), " VALUE/", value::binary>>, _, _), do: %Output{key: key, value: value)

and so on and so forth.

And thank you for the suggestion! Much appreciated.

1 Like