How to get rid of "this check/guard will always yield the same result"?

I have predicates that rely on the @dev and @prod module attributes to know in which environment we’re in.

In config/dev.exs, I have the following configuration among other things:

config :myapp,
  dev:  true,
  prod: false

My @dev module attribute is defined like that:

@dev Application.compile_env!(:myapp, :dev)

When I write a predicate like:

cond do
  @dev && ... -> ...

Elixir warns me that this check/guard will always yield the same result which is true but I do not want to be warned because the produced code is ok even if the translation gives false && ... (because we’re in production). Is there a way to disable the warning or to refactor the usage? Is it considered bad style?

A priori without pattern matching on function arguments unless there is no other way.

The cond expression looks like:

cond do
  @dev && <dev condition>   -> <dev expression>
  @prod && <prod condition> -> <prod expression>
  <condition>               -> <expression>
  true                      -> <true expression>
end

You have to push as much of this to compile time.

in this case, you shouldn’t even generate the @prod clause when in dev and vice versa.

At the same time, it is probably already a smell to have this distinction based on the build environment.

1 Like

I flag this as a solution but I would have liked Elixir to provide a way to disable some warnings like e.g. unused default arguments.

There is a certain kind of warnings that you can silence by using macros and set generated: true or so in the returned quote.

Kernel.SpecialForms — Elixir v1.16.3.

Though instead of working around the warnings and silencing them, you should take care to not make them happen.

Why spend cycles/reductions on a clause if you know in advance that it can never become true? Just omit that clause.

And still, changing behavior based on the build environment should be done with care. It would be much more idiomatic to instead introduce an option, that you configure differently between build and prod, that describes the difference in behavior much better.

2 Likes

This was really useful for another bunch of warnings coming from generated code with a few macros. Solved it! :pray: And reached 0 warnings after a few days of refactoring. Afraid to put credo in the build pipeline now :wink:

If you really want to check environment I would just check the name as opposed to a boolean. There are a few ways to get it… like setting it in each config: config :env, <:dev|:test|:prod>. You can also do @env Mix.env() which is safe but sort of sets bad precedent AFAIC.