Thread overview
[Issue 15318] Templates not emitted for two "partial cycles"
Nov 12, 2015
Martin Nowak
Nov 12, 2015
David Nadlinger
Nov 12, 2015
Walter Bright
Nov 13, 2015
Kenji Hara
Nov 18, 2015
David Nadlinger
Nov 18, 2015
Kenji Hara
May 22, 2017
Johan Engelen
May 23, 2017
Vladimir Panteleev
May 23, 2017
David Nadlinger
November 12, 2015
https://issues.dlang.org/show_bug.cgi?id=15318

Martin Nowak <code@dawg.eu> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |code@dawg.eu

--- Comment #1 from Martin Nowak <code@dawg.eu> ---
This seems to be a case where the second rule of this issue 14431 fix doesn't
work.
http://forum.dlang.org/post/mailman.697.1440962414.13986.digitalmars-d-bugs@puremagic.com

> If a template is instantiated in non-root module, compiler usually does not have to put it in object file. But if a template is instantiated in both of root and non-root modules which mutually import each other, it needs to placed in objfile.

===

In both of the compilations there is a root and a non-root module instantiating
bar!5. Now unfortunately the compiler decides both times that the non-root
module should do it.
This problem would be solved by my proposal to define a global order for who is
responsible to instantiate a template, by choosing the module with the
lexicographically smaller module name.
https://github.com/D-Programming-Language/dmd/pull/4384#discussion_r29910422
https://issues.dlang.org/show_bug.cgi?id=14431#c12

This would establish a stable order between B and C, and no matter how you compile them, B gets to instantiate the template.

===

An intermediate workaround for your problem is to use the -allinst switch, even though it slows down compilation a lot. You can also compile each module separately in which case both B and C get the instance (in general this is even slower than -allinst).

--
November 12, 2015
https://issues.dlang.org/show_bug.cgi?id=15318

--- Comment #2 from David Nadlinger <code@klickverbot.at> ---
(In reply to Martin Nowak from comment #1)
> In both of the compilations there is a root and a non-root module instantiating bar!5. Now unfortunately the compiler decides both times that the non-root module should do it.

That is correct.

> This problem would be solved by my proposal to define a global order for who is responsible to instantiate a template, by choosing the module with the lexicographically smaller module name. https://github.com/D-Programming-Language/dmd/pull/4384#discussion_r29910422 https://issues.dlang.org/show_bug.cgi?id=14431#c12
> 
> This would establish a stable order between B and C, and no matter how you compile them, B gets to instantiate the template.

At first glance, it seems as if this should work. However, I would need to think about it in more detail to be sure that the approach doesn't implicitly introduce any new edges in the module dependency graph that would break incremental compilation.

> An intermediate workaround for your problem is to use the -allinst switch […]

I'd say a much better workaround would be to just remove the clearly faulty "optimization" from DMD until we have a solid strategy to replace it with. In fact, Weka is currently using a lightweight fork of upstream LDC with the code mentioned in the original report patched out, and it has resolved all the related issues.

--
November 12, 2015
https://issues.dlang.org/show_bug.cgi?id=15318

Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bugzilla@digitalmars.com

--- Comment #3 from Walter Bright <bugzilla@digitalmars.com> ---
It can also be resolved by noting that C is not imported (directly or indirectly) by B, and so C's instantiation will not count as an imported instantiation when instantianting templates in B.

--
November 13, 2015
https://issues.dlang.org/show_bug.cgi?id=15318

--- Comment #4 from Kenji Hara <k.hara.pg@gmail.com> ---
I don't think that the issue case is a bug in the current instantiation strategy.

The codegen omission for non-root instances is designed for the compiling
applications which is using big template style libraries.
On the other hand, in the issue case, the non-root instance bar!5 is a part of
the build target, so no libraries can supply the missing symbol.

I think it could be resolved at compiler tool side.
If a module is imported, all of template instances in it could be handled
either:
  A. as non-root instances, because the module is a part of library.
  B. as speculative instances, because the module is a part of build target.
But currently, all of import directories are in a ordered flat list.
So, compiler cannot distinguish the two cases - today all of cases are treated
as case A.


My proposal is, adding a boundary between "build target" and "library". By that, we can have a new behavior for the modules for the build target.

How to define the boundary? There's some ways I can think.

- Use the 'package' difference. For example:
  If none of root modules belong to 'std' package, then all of modules belongs
'std' can be handled as library modules.
- Use the found import directory. For example:
  The default import directly '.' can be handled as for the build-target
always.
- Use a new switch for the importing build-target modules. For example:
    dmd -buildTarget_I=...
  If compiler finds a module from that directory, the module will be handled as
build target module.

The approach would also fit to modern package system.

--
November 18, 2015
https://issues.dlang.org/show_bug.cgi?id=15318

--- Comment #5 from David Nadlinger <code@klickverbot.at> ---
I very much prefer (In reply to Walter Bright from comment #3)
> It can also be resolved by noting that C is not imported (directly or indirectly) by B, and so C's instantiation will not count as an imported instantiation when instantianting templates in B.

Yep, this is indeed an option here. We'd still end up emitting the template twice in this example, though, which is what I alluded to regarding not being able to elide the instance.

(In reply to Kenji Hara from comment #4)
> I don't think that the issue case is a bug in the current instantiation strategy.

I can't really see how you can come to this conclusion. If it's not a regression, then where is the documentation that states that DMD is not to be invoked in this fashion?

Like Martin and Andrei, I'd suggest taking a step back and thinking about what the template instantiation strategy is really meant to achieve first. I don't think piling up more and more special cases is going to be helpful, especially because it just pushes this complexity to the user.

--
November 18, 2015
https://issues.dlang.org/show_bug.cgi?id=15318

--- Comment #6 from Kenji Hara <k.hara.pg@gmail.com> ---
> (In reply to Kenji Hara from comment #4)
> > I don't think that the issue case is a bug in the current instantiation strategy.
> 
> I can't really see how you can come to this conclusion. If it's not a regression, then where is the documentation that states that DMD is not to be invoked in this fashion?

OK, I recognized true issue you reported. I had misunderstood.

--
May 22, 2017
https://issues.dlang.org/show_bug.cgi?id=15318

Johan Engelen <jbc.engelen@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jbc.engelen@gmail.com

--- Comment #7 from Johan Engelen <jbc.engelen@gmail.com> ---
It appears this was fixed for the OP testcase in DMD 2.072.

Measurement points:
2.069.2  BROKEN
2.070.2  BROKEN
2.071.2  BROKEN
2.072.2  WORKS!
2.073.2  WORKS!

--
May 23, 2017
https://issues.dlang.org/show_bug.cgi?id=15318

Vladimir Panteleev <thecybershadow@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
                 CC|                            |thecybershadow@gmail.com
         Resolution|---                         |DUPLICATE

--- Comment #8 from Vladimir Panteleev <thecybershadow@gmail.com> ---
(In reply to Johan Engelen from comment #7)
> It appears this was fixed for the OP testcase in DMD 2.072.

Fixed in https://github.com/dlang/dmd/pull/5690

*** This issue has been marked as a duplicate of issue 13242 ***

--
May 23, 2017
https://issues.dlang.org/show_bug.cgi?id=15318

--- Comment #9 from David Nadlinger <code@klickverbot.at> ---
(In reply to Johan Engelen from comment #7)
> It appears this was fixed for the OP testcase in DMD 2.072.

Let's hope it is actually fixed, rather than just not occurring anymore in the test case. ;)

--