Issues with Credo, Dialyzer, and compiler warnings for `<app_name>Web.ErrorView.template_not_found/2` in Phoenix

Phoenix generates the following module:

defmodule IslandsInterfaceWeb.ErrorView do
  use IslandsInterfaceWeb, :view

  def template_not_found(template, _assigns) do
    Phoenix.Controller.status_message_from_template(template)
  end
end

I implement Credo in my codebases and run it in strict mode. The function template_not_found/2 fails the Credo.Check.Readability.Specs Credo check, despite there being a typespec defined for it in the Phoenix.Template module in Phoenix.View.

If I add any @spec to IslandsInterfaceWeb.ErrorView.template_not_found/2, including the exact spec listed in the link above, then I get the following Dialyzer error:

Overloaded contract for IslandsInterfaceWeb.ErrorView.template_not_found/2 has
overlapping domains; such contracts are currently unsupported and
are simply ignored.

So then I thought, maybe it’s a callback. The documentation linked above does mention that it is a callback, but only in the documentation. But if I add @impl true to IslandsInterfaceWeb.ErrorView.template_not_found/2 with no @spec, then I get the compiler warning:

warning: got “@impl true” for function template_not_found/2 but no behaviour was declared

Even if that worked, I enforce the Credo.Check.Readability.ImplTrue Credo check, so I need an explicit behaviour name.

My guesses are either that:

  1. Credo or something it uses does not appropriately pick up the @spec for template_not_found/2,

or

  1. template_not_found/2 is a callback, but either the callback or behaviour is not defined properly. I’m not yet familiar enough with Phoenix, macros, or defoverridable to be able to efficiently debug this. Perhaps this is related to the post Behaviours, defoverridable and implementations?

How do I solve this such that I can run the Credo checks, Dialyzer, and mix compile --warnings-as-errors all successfully? At present, I am unable to do so.

2 Likes

Since they are not supported and ignored you can just:

# credo:disable-for-next-line Credo.Check.Readability.Specs
def template_not_found(template, _assigns) do
  Phoenix.Controller.status_message_from_template(template)
end

Don’t think we have many more options

1 Like

Thanks for the response. Yes, that is a workaround, but I think that it’s likely there’s an implementation issue somewhere here. It will be good to figure it out and make a fix.

Does anyone have any more thoughts on where the issue might lie here?

I am thinking that if not, filing this as a bug against Credo and the Credo.Check.Readability.Specs check may be the next step.

Maybe Phoenix should declare this as a callback. phoenix_view/template.ex at 79ed7e428270f7b150c71990d92302db34f2672f · phoenixframework/phoenix_view · GitHub