Compilation order,and legal circular references

If I have module A with submodule A_sub, and module B with submodule B_sub, I think it is legal for A_sub to access procedures in B_sub by use association, and for B_sub to access procedures in A_sub by use association, but how can this be compiled, especially if I am just compiling manually? Are there flags in IFX for “ignore dependencies”? Apologies if this has already been solved/answered elsewhere.

My unsolicited piece of advice is: if you can, try to break circular dependencies and be sure that your modules respect as best as possible a clear vertical hierarchy of dependencies. If you need, introduce intermediate modules. Otherwise you are bounding yourself or whomever will follow behind you to some nasty build-time bugs down the road. And when I say nasty, it is because they might or might not appear, difficult to reproduce, you build in parallel with 8 procs, there it is, with 6 or 10, not there… on one OS it might build, on the other not with the hellish error #10298, "problem during post processing of parallel object compilation"

I now learned to see circular dependencies in codes like fast-food, it might be tempting because it is easy to get there, they might be legal… but the harm is visible afterwards.

I would actually prefer for compilers to detect and warn about circular dependencies to help the developer avoid them.

I don’t think there is a need for any special flag here if you declares only the interfaces needed as public in both modules. Then, the submodules can just use the modules. Since both modules do not use each other, you can compile either one of them first. But both modules must be compiled before the submodules are compiled. And either one of the submodules can be compiled before the other one.

Hope this help

Thanks all, I was not advocating this as a programming practice, just trying to understand how it might be compiled.

The USE module-name syntax rule explicitly says that module-name must be the name of a module. A name of a submodule is not a name of a module, these are different program units.

TLDR: You cannot USE a submodule.

I believe all the interfaces have to be defined in the top level module right? So that one gets compiled first I would imagine, then the compiler can check interfaces when building the submodules.

Having spent today doing some experiments, I think @Chuckyvt is correct; provided all the interfaces are present and correct, all the module files can be compiled before any submodules have to be compiled. My next experiments will be to explore how in lining and other optimisation processes may work or be inhibited. Thanks all.

My experience has shown that Chuckyvt’s belief is correct.

I have a top.f08 whose 1st line is ‘MODULE top_mod’ and it currently has 407 submodule INTERFACEs in it. Each SUBROUTINE or FUNCTION that make up those 407 is a
SUBMODULE of MODULE top_mod, e.g. its 1st 3 lines are:

SUBMODULE (top_mod) A_proc

CONTAINS

MODULE SUBROUTINE A (…)

Until I made it that way I was plagued with circular dependencies like A has a ‘USE B’. B has a ‘USE C’. C has a ‘USE A’. That meant none of A, B, or C could be compiled because the information for the one it was dependent on did not exist. Compiling top.f08 before any other files meant those then existed.

Before doing the above, it was very tedious to unravel when it involved more that ‘A is missing B’ and ‘B is missing A’. THE FEATURE of SUBMODULEs A and B of top_mod is: “A is NOT able to see the code of B and vice versa”. A can call B and B can call A. It is still up to you that you have not coded an infinite loop.

My working with 407 such SUBMODULEs that have top_mod as their parent has completely cured circular dependency. I still have about another 300+ to add to top.f08. The 407 do create an executable that runs. Those basic 407 were chosen because each one would have its code exercised. Just that much has taken me 11 months of full time work to accomplish toward my goal of including those other 300+ and still have zero troubles with circularity.

I add that in a few of those 407 SUBMODULEs of MODULE top.f08 are “ordinary”, non-MODULE, servant FUNCTIONs called upon only by that file’s MODULE. I do have the SUBMODULE have an INTERFACE for each servant. With that assurance of only one caller there is no circular dependency.

One MODULE to rule all SUBMODULEs. Compilation order after doing top.f08 is irrelevant.

3 Likes

There is an old joke about recursive algorithms that goes

“To understand recursion you must first understand recursion”

I think the same might apply to circular module references. To understand circular references you must first understand circular references :grin:

As @gWyche suggested, the straightforward solution is to just merge modules A and B into a single module AB, and have interface blocks for the submodule procedures that must be “seen” by other submodules.