Give warning on unused require

113 views
Skip to first unread message

Mário Guimarães

unread,
Apr 5, 2019, 11:48:56 AM4/5/19
to elixir-lang-core
Hi,

I suggest for Elixir to warn on unused requires, like it does for unused aliases.

Thanks 

Łukasz Niemier

unread,
Apr 8, 2019, 4:19:48 AM4/8/19
to elixir-lang-core
Not possible as `require`s are always used - by the compiler, as this marks that required module need to be compiled before compilation of module with require.

Louis Pilfold

unread,
Apr 8, 2019, 4:40:22 AM4/8/19
to elixir-lang-core
Hey

Wouldn't it be possible to track if any macros have been used by the requiring module? I'm not familiar with the compiler here but it seems like it is always possible as all information is available at compile time.

Cheers,
Louis

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/57e4a930-f4f2-4efa-a0bf-35f470a652a6%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Łukasz Niemier

unread,
Apr 8, 2019, 4:45:28 AM4/8/19
to elixir-l...@googlegroups.com
You do not need to use macro to require compilation. You can use function or even just depending on fact that this module is already compiled in some highly hacky code with metaprogramming. I cannot give you any reasonable example right now. Also remember that you can require something just to call functions during compile time, it do not need to be macro.

Wiadomość napisana przez Louis Pilfold <lo...@lpil.uk> w dniu 08.04.2019, o godz. 10:39:

You received this message because you are subscribed to a topic in the Google Groups "elixir-lang-core" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elixir-lang-core/d9ZjViQaOY8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CABu8xFBrM7LuJoZT0HzPQ-ifxOSgVZT03XwRu%3D-pC%3DQ%3D5Ow21Q%40mail.gmail.com.

Mário Guimarães

unread,
Apr 8, 2019, 5:22:15 AM4/8/19
to elixir-lang-core
Lukasz,

it should be possible to warn on unused "require".

The thing is that "import" does what "require" does plus much more, and still the compiler warns on unused "import". Check this by playing with this code

defmodule X do
def foo, do: " hello"
defmacro xpto
, do: "Hey"
end

defmodule Y
do
import X
#require X
#def bar, do: X.xpto() <> X.foo() <> " world"
end

Regards
Mário


segunda-feira, 8 de Abril de 2019 às 09:45:28 UTC+1, Łukasz Niemier escreveu:
You do not need to use macro to require compilation. You can use function or even just depending on fact that this module is already compiled in some highly hacky code with metaprogramming. I cannot give you any reasonable example right now. Also remember that you can require something just to call functions during compile time, it do not need to be macro.
Wiadomość napisana przez Louis Pilfold <lo...@lpil.uk> w dniu 08.04.2019, o godz. 10:39:

Hey

Wouldn't it be possible to track if any macros have been used by the requiring module? I'm not familiar with the compiler here but it seems like it is always possible as all information is available at compile time.

Cheers,
Louis

On Mon, 8 Apr 2019, 09:19 Łukasz Niemier, <luk...@niemier.pl> wrote:
Not possible as `require`s are always used - by the compiler, as this marks that required module need to be compiled before compilation of module with require.

W dniu piątek, 5 kwietnia 2019 17:48:56 UTC+2 użytkownik Mário Guimarães napisał:
Hi,

I suggest for Elixir to warn on unused requires, like it does for unused aliases.

Thanks 

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-l...@googlegroups.com.

--
You received this message because you are subscribed to a topic in the Google Groups "elixir-lang-core" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elixir-lang-core/d9ZjViQaOY8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elixir-l...@googlegroups.com.

Łukasz Niemier

unread,
Apr 8, 2019, 5:37:25 AM4/8/19
to elixir-l...@googlegroups.com
The problem is that `import` does more, and you can detect that `import` is unused and it can be replaced by `require`, but compiler cannot reason that `require` is unneeded as for example imagine that we have 2 modules (in separate files, as this will not work within single file):

defmodule A do
  def foo, do: 10
end

And in second file

defmodule AllFoos do
  require A

  @foos for module <- :code.all_loaded(), function_exported?(module, :foo, 0), do: module

  def foos, do: @foos
end

And without that `require` this code will depend on compilation order (which isn’t guaranteed by Elixir compiler) to work properly. So as you can see the compiler has no knowledge whether it can alter compilation order restricted by user.

Of course this is highly unlike scenario for `require`, but is perfectly valid code right now, with very well defined behaviour.

Wiadomość napisana przez Mário Guimarães <mario.luis...@gmail.com> w dniu 08.04.2019, o godz. 11:22:

To unsubscribe from this group and all its topics, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/130d4573-9194-4d91-be5b-c2ed909f2001%40googlegroups.com.

Mário Guimarães

unread,
Apr 8, 2019, 6:03:00 AM4/8/19
to elixir-lang-core
Hi  Łukasz,

your code is using knowledge that "require" puts the compilation of the requiring module on hold until the required module is compiled.

Even though "require" has this effect, it should not be used in the way you do. At least, what I understand from here is that "require" is meant to bring other module's defined macros into the compilation context of the current module, and nothing more, so I think it should be used only with this intent, and not for the purpose of what your code shows. (Hint: For what your code wants to do, you should be using "Code.ensure_loaded" or "Code.ensure_compiled", but never "require" to simply get its side-effect when you are not calling anything from module A).

As such,  and like already done for its cousin "import" and "alias", which are meant to facilitate access to the definitions in other modules, "require" should be returning a warning when a required module's definitions are not being used, otherwise it seems that "require" is being somehow treated like a second-citizen, regarding "import" and "alias", in the Elixir world, which to me would be "strange".

I think this is something for the Elixir core team to decide: if they want "require" to stay as it is now, or if they want to provide consistent behavior with "import" and "alias" when nothing required is being used.

Regards
Mário


segunda-feira, 8 de Abril de 2019 às 10:37:25 UTC+1, Łukasz Niemier escreveu:
The problem is that `import` does more, and you can detect that `import` is unused and it can be replaced by `require`, but compiler cannot reason that `require` is unneeded as for example imagine that we have 2 modules (in separate files, as this will not work within single file):

defmodule A do
  def foo, do: 10
end

And in second file

defmodule AllFoos do
  require A

  @foos for module <- :code.all_loaded(), function_exported?(module, :foo, 0), do: module

  def foos, do: @foos
end

And without that `require` this code will depend on compilation order (which isn’t guaranteed by Elixir compiler) to work properly. So as you can see the compiler has no knowledge whether it can alter compilation order restricted by user.

Of course this is highly unlike scenario for `require`, but is perfectly valid code right now, with very well defined behaviour.

Wiadomość napisana przez Mário Guimarães <mario.lui...@gmail.com> w dniu 08.04.2019, o godz. 11:22:

To unsubscribe from this group and all its topics, send an email to elixir-l...@googlegroups.com.

Louis Pilfold

unread,
Apr 8, 2019, 7:10:50 AM4/8/19
to elixir-lang-core
Hey

It's not necessary to call require in order to call functions from another module at compile time, so we can remove or warn if only functions are used.

What type of metaprogramming needs require but does not use macros? I thought that if no macros were used then a require can be safely removed.

Cheers,
Louis

Mário Guimarães

unread,
Apr 8, 2019, 7:32:36 AM4/8/19
to elixir-lang-core
Louis: you are right, as require should only be used to bring macros into context


segunda-feira, 8 de Abril de 2019 às 12:10:50 UTC+1, Louis Pilfold escreveu:
Hey

It's not necessary to call require in order to call functions from another module at compile time, so we can remove or warn if only functions are used.

What type of metaprogramming needs require but does not use macros? I thought that if no macros were used then a require can be safely removed.

Cheers,
Louis

On Mon, 8 Apr 2019, 09:45 Łukasz Niemier, <luk...@niemier.pl> wrote:
You do not need to use macro to require compilation. You can use function or even just depending on fact that this module is already compiled in some highly hacky code with metaprogramming. I cannot give you any reasonable example right now. Also remember that you can require something just to call functions during compile time, it do not need to be macro.
Wiadomość napisana przez Louis Pilfold <lo...@lpil.uk> w dniu 08.04.2019, o godz. 10:39:

Hey

Wouldn't it be possible to track if any macros have been used by the requiring module? I'm not familiar with the compiler here but it seems like it is always possible as all information is available at compile time.

Cheers,
Louis

On Mon, 8 Apr 2019, 09:19 Łukasz Niemier, <luk...@niemier.pl> wrote:
Not possible as `require`s are always used - by the compiler, as this marks that required module need to be compiled before compilation of module with require.

W dniu piątek, 5 kwietnia 2019 17:48:56 UTC+2 użytkownik Mário Guimarães napisał:
Hi,

I suggest for Elixir to warn on unused requires, like it does for unused aliases.

Thanks 

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-l...@googlegroups.com.

--
You received this message because you are subscribed to a topic in the Google Groups "elixir-lang-core" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elixir-lang-core/d9ZjViQaOY8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elixir-l...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-l...@googlegroups.com.

José Valim

unread,
Apr 12, 2019, 5:27:36 AM4/12/19
to elixir-l...@googlegroups.com
Hi Mario,

Thank you for the proposal!

So “require” was generally described as Łukasz mentioned it: it is about making sure a module is compiled, which is a requirement for macros. However, given macros were the only use case for a while, we decided to streamline and simplify the docs, without changing the implementation.

I can see arguments for both sides here. I agree that the warning would be excellent for the current interpretation of "require" but I believe we need to do further investigation to make sure that macros are indeed the only use case for the next years. So I think it is a good idea, let's keep it in mind for a while.

To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/0b5053f9-17a7-4b1c-ab62-4879923fcddc%40googlegroups.com.

Xavier Noria

unread,
Apr 12, 2019, 5:35:20 AM4/12/19
to elixir-l...@googlegroups.com
It also happened that in some cases the compiler warned that the module was compiled, but not required, and thus the macro the compiler _knew_ existed was not available because you didn’t opt-in.

So, if the purpose was to ensure it was compiled... well, it was, and it was not enough.

In the end, you need to opt-in _regardless_ of whether the module is compiled at that point.

That was the motivation for changing the emphasis in the docs.
--
Sent from Gmail Mobile

Xavier Noria

unread,
Apr 12, 2019, 7:08:50 AM4/12/19
to elixir-l...@googlegroups.com
I have recovered the original example. Let's consider

    Integer.digits(1) # function
    defmodule M do
      Integer.is_odd(1) # macro
    end

Elixir says (my emphasis)

** (CompileError) foo.ex:4: you must require Integer before invoking the macro Integer.is_odd/1
    (elixir) src/elixir_dispatch.erl:97: :elixir_dispatch.dispatch_require/6

So, according to the message, inside M the compiler has Integer compiled and knows that Integer.is_odd/1 is a macro, the message says so!

If the true purpose of require was to ensure the module is compiled to know its macros, that code should run, shouldn't it? Integer is compiled, I made sure in a different way, the macros are known, so it should run. But it doesn't run, so there's something more :).

From a user's perspective, require is really saying "I want to use the macros of this module", and Elixir may need to compile the module in order to be aware of the macros the user has said they want to use if not already compiled, but that is internal.

As a side comment, the docs also tell you that macro expansion happens at compile time.


OvermindDL1

unread,
Apr 16, 2019, 1:06:35 PM4/16/19
to elixir-lang-core
For note, I use `require` to compile another module that then generates 'other' things that are then used by the module that is calling require (calls another language build system), so it has non-macro uses.

Xavier Noria

unread,
Apr 16, 2019, 7:34:54 PM4/16/19
to elixir-l...@googlegroups.com
On Wed, 17 Apr 2019 at 02:06, OvermindDL1 <overm...@gmail.com> wrote:

For note, I use `require` to compile another module that then generates 'other' things that are then used by the module that is calling require (calls another language build system), so it has non-macro uses.

This is the PR that reworded that

José Valim

unread,
Apr 16, 2019, 7:38:45 PM4/16/19
to elixir-l...@googlegroups.com
I would keep the PR as it is the most clear explanation, especially for newcomers.

If we do add the proposed warning in the future, users like OvermindDL1 can use Code.ensure_compiled(module) to guarantee a certain module is compiled and available.


José Valim
Skype: jv.ptec
Founder and Director of R&D


--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
Message has been deleted

thia.md...@gmail.com

unread,
Sep 5, 2025, 7:49:31 AM (2 days ago) Sep 5
to elixir-lang-core

Hello all,

I’d like to revisit this topic after some years. Back in 2019 there was agreement that a warning for unused require could make sense, but more investigation was needed because of its dual role (ensuring compilation + enabling macros).

Has the stance on this changed since then?
Would adding a warning when no macros are used from a required module be considered today?

Thanks!

Jean Klingler

unread,
Sep 6, 2025, 7:45:32 AM (18 hours ago) Sep 6
to elixir-l...@googlegroups.com
I think it would make sense, given that macros are the only documented reason to use require, and that Code.ensure_loaded (or Code.ensure_compiled!) should otherwise be used?

We'd probably need to introduce a warn: false option like we have for import, for meta-programming use cases like __using__.

José Valim

unread,
Sep 6, 2025, 10:37:43 AM (15 hours ago) Sep 6
to elixir-l...@googlegroups.com

A warn: false option would solve it. But I believe last time libraries like Plug used require to make sure a module is available. It has been quite a while though.


Jean Klingler

unread,
Sep 6, 2025, 7:23:01 PM (6 hours ago) Sep 6
to elixir-l...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages