-
-
Notifications
You must be signed in to change notification settings - Fork 609
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[REG2.067] Issue 14508 - compiling with -unittest instantiates templates in non-root modules #4626
Conversation
|
@WalterBright This is also an answer for the instantiation strategy workaround that you implemented in #2661, to fix issue 11239. |
|
Not sure that this or #2661 are good ideas. You can't generally expect that linking code compiled with different debug/version settings works. struct Foo
{
debug size_t cnt;
}
void bar(Foo* foo) { debug ++foo.cnt; } |
|
@MartinNowak Yes, it generally doesn't work. But for the instantiated code we can relax the restriction. |
|
Auto-tester now shows all green. The previous Phobos failure in Win64 was another link-failure issue 14541. |
|
Shouldn't the codegen be like this instead? Nd = version(unittest) and debug template instances in non-root modules |
|
Pushed additional fix commit. I'll squash it after the review finished. |
By using |
|
Sit, Making instantiation strategy more strict will directly hit the root of issue 12661. We need to fix it radically, at first. |
71bacba to
d93f17b
Compare
|
OK, I added one more feature "force instantiation mechanism". More feature for root of issue 12661 - Add forceInst mechanism
|
|
I'm not in favor of reordering code as in f0080e8 because it makes it very difficult to compare code that crosses such a diff. Can you please back that out? |
|
I'm a bit worried, that doing it transitively will generate an awful amount of code.
How can you know that function contains such conditions before instantiating it? |
|
I also have a suggestion to fix part of the instantiation bloat. |
|
Does this resolve the compilation slowdown caused by #4384 ? |
|
I suspect the rule we should be using is that all templates in non-root modules should be instantiated lazily, meaning only if a particular instantiation is actually needed. No eager instantiations. Thus certainly would resolve the particular case in https://issues.dlang.org/show_bug.cgi?id=14508 I did this for enum members a while back, and the results have been very satisfactory. It also resolves order-of-evaluation issues. |
An alternate suggestion would be to change the behavior of -unittest and -debug switches. For example: But, it would prohibit to define a module just for unit-testing/debug utilities. I think it would need a design decision to the D module system.
It would be horrible idea. How many combinations would be necessary for the user code conditional compilations? |
No. It makes more slow down compilation speed to make linking more stable. |
There's no general way, so a condition can depend on the semantic result. See the following example code: // this function template may or may not depend on -unittest
void foo(string code)() {
mixin(code);
}
foo!"version(unittest) unsafeCheckFunc();"(); |
|
I removed commits for code cleanup in order to concentrate on bug fix. |
See my comment here, #4384 (comment). |
Sounds good, but is that feasible for the next release? It wouldn't solve linkage issues when the template is used though.
That would actually solve the problem we had with MonoTimeImpl and vibe.d.
How is that? You mean for separate compilation? |
There's got to be a better answer than a 30% slowdown. What about the idea of lazy instantiation? |
…orward reference in Tuple.opAssign The "error reproduction instantiation" might succeed to finish semantic analysis by the forward reference resolution. When it happens, the cached error instance needs to be overridden by the succeeded instance.
…non-root modules
All template instances outside of `version(unittest){}` or `debug(num){}` need to use the normal instantiation strategy.
When `-unittest` or `-debug(=num)` switches specified, the instantiation strategy will be tweaked - a conditionally instantiated template code by `version(unittest){}` or `debug(num){}` will be generated conservatively, even if it's done in non root module.
It can be formalized as follows:
R = templates instantiated in root module
N = templates instantiated in non root module
S = templates instantiated speculatively
Default instantiation strategy:
codegen = R - (R ∩ N)
The new instantiation strategy for -unittest or -debug=num:
codegen = Rd - (Rd ∩ N)
Rd = R ∪ Nd
Nd = version(unittest) and debug template instances in non-root modules
and debug(num){} blocks.
The old instantiation strategy for -allInst:
codegen = R ∪ N
- If an instantiated function contains debug{} or version(unittest){}, the instance code will be forcibly generated.
- If an instantiated function calls other forcibly instantiated function and its attribute is influenced by inference, that code is also generated forcibly.
|
Superseded by: #4784 |
https://issues.dlang.org/show_bug.cgi?id=14508
All template instances outside of
version(unittest){}ordebug(num){}need to use the normal instantiation strategy.When
-unittestor-debug(=num)switches specified, the instantiation strategy will be tweaked - a conditionally instantiated template code byversion(unittest){}ordebug(num){}will be generated conservatively, even if it's done in non root module.It can be formalized as follows:
R = templates instantiated in root module
N = templates instantiated in non root module
S = templates instantiated speculatively
codegen = R - (R ∩ N)
codegen = Rd - (Rd ∩ N)
Rd = R ∪ Nd
Nd = version(unittest) and debug template instances in non-root modules
codegen = R ∪ N