No Erlang compile time errors for missing functions

Why are there no compilation errors or warnings when calling a function in another module that does not exist or has the wrong arity?

The compiler has all the export information in the module to make this possible. Is this not yet realized or is there a technical reason why this is not possible, which I do not see?

+4
source share
6 answers

I don’t know why this is missing (perhaps because the modules are completely separate, and compiling one does not depend on the other really, but this is just speculation). But I believe that you can find issues like static dialyzer analysis. Take a look at http://www.erlang.org/doc/man/dialyzer.html

This is part of the system itself, so try including it in your workflow.

+5
source

This, as others have said. Modules are compiled separately, and there is absolutely no guarantee that the environment that exists at compile time is the same as the one that will exit at run time. This means that performing checks at compile time about the existence of a module or function in it is basically meaningless. At run time, the module may or may not be loaded, the function you are calling may or may not be defined in the module, or it may do something completely different from what you expected.

All this is due to the very dynamic nature of Erlang systems. There is no real way as such to determine what is in the system at runtime. Hot code loading is part of this and works properly due to the dynamic nature of the system. This means that it can override the system at run time, you can load into new versions of existing modules with a different interface, and you can load into completely new modules and delete existing modules.

To do this, you must perform all checks about the existence of a module or function at run time.

Tools like dialyzer can help with this, but they assume that you are not doing anything β€œfunny” at run time, and the system you are checking is the same as your system. This, of course, is all good, but very static. And against the nature of Erlang, which should be dynamic, in everything.

Unfortunately, in this case you cannot both drink and eat it.

+4
source

This is due to the loading of hot code. Each module can be loaded at any particular time. Therefore, when you have code in module A that calls the function B:F , you cannot say that this is not true at compile time, when your source code for module B does not have function B:F Imagine: you are compiling module A with a call to B:F You load module B into memory without function B:F Then you load module A , which contains a call to B:F , but do not call it. Then compile the new version of module B with B:F Then download this new module, and then you can call B:F , and everything is completely correct. Imagine that your module A makes module B turned on and loads it. At some particular moment, you cannot say that it is not so that module A contains a call to the nonexistent function B:F

+1
source

In my opinion, most, if not all, the compiler does not check if a function exists during compilation. What is required in the general case is the declaration of a function prototype: the type of the return value, the list, and the type of all arguments. This is done in C / C ++ by including some_file.h in each module definition (not .c or .cpp).

Erlang checks this type dynamically and the program runs, so there is no need to include these definitions. This is even completely useless, because Erlang allows you to update the application while it is running, so the type of function may change, or the function may disappear, intentionally or by mistake, during the life of the application; therefore, the Erlang designer decided to conduct this check at runtime rather than at build time.

The error you are talking about usually occurs during the link phase of code generation, when the "compiler" tries to collect all the separate parts of the object code to create an executable file or library, at this point the linker solves all external addresses (for a shared variable, a static call ...). This phase does not exist in Erlang, the module is completely autonomous; it does not participate with the rest of the application, nor with the parameter, nor with the address of the function.

Of course, you need to use some tools and perform some tests before updating the current production program, but I believe that these checks have the same level of importance as the correctness of the algorithm itself.

+1
source

When compiling, for example. module alpha , which has a call to beta:some_function(...) , the compiler cannot assume that a specific version of beta will be used at runtime. Perhaps you will compile a new version of beta after compiling alpha , and this will result in the correct export of some_function . Perhaps you download alpha for use on another host that has all the other modules.

Therefore, the compiler simply compiles the remote call, and any errors (non-existent module or function) are resolved at runtime when some version of beta is loaded.

+1
source

You can use the xref application to check for obsolete, undefined, and unused functions (and more!).

Compile the module using debug_info :

 Eshell V6.2 (abort with ^G) 1> c(test, debug_info). {ok,test} 

Check the module with xref:m/1 :

 2> xref:m(test). [{deprecated,[]}, {undefined,[{{test,start,0},{erlang,foo,0}}]}, {unused,[]}] 

You can learn more about xref here:

Erlang - Xref - Cross Reference Tool (Tools User Guide)

Erlang - xref (Tool Reference)

+1
source

Source: https://habr.com/ru/post/1469096/


All Articles