Skip to content

Instantly share code, notes, and snippets.

@alexandrumc
Last active February 4, 2020 12:49
Show Gist options
  • Save alexandrumc/6010b5da9def5957633c17a6675e4924 to your computer and use it in GitHub Desktop.
Save alexandrumc/6010b5da9def5957633c17a6675e4924 to your computer and use it in GitHub Desktop.
TWO ways: 1) dmd importer.d
2) dmd -unittest importer.d
import importme; // *importme.d* is opened and semantic analysis on *importme.d* begins;
// now you should follow the comments from *importme.d*
//imports are solved now; semantic analysis continues
void main()
{
foo(); // instantiate foo() which contains S!int x, so S!int will also be instantiated here.
}
// semantic analysis is finished
/** codegen phase begins:
for templates, there's a function inside dtemplate.d that is called `bool needsCodegen()`
this function returns true if we should generate code for a template instantiation;
inside this function, there's an `if (compiledWithUnittest) {} else {}` block.
The else{} branch says:
"Prefer instantiations from non-root module, to minimize object code size.
If a TemplateInstance is ever instantiated by non-root modules,
we do not have to generate code for it,
because it will be generated when the non-root module is compiled."
for ref: https://github.com/dlang/dmd/blob/master/src/dmd/dtemplate.d#L6179-L6183
This is exactly the case when we run `dmd importer.d`: S!int is instantiated once in importme.d and once in
importer.d, as I mentioned above. Since an instance of S!int is found inside importme.d (which is not a root module)
there will be no code generation for S!int instantiated in importer.d so the linker failure -- `method` cannot be found.
Now let's take the if(compiledWithUnittest) {} branch, which says:
"Prefer instantiations from root modules, to maximize link-ability."
So if we run `dmd -unittest importer.d` there will be a codegen phase for S!int and there won't be a linker error.
*/
// semantic analysis begins
module importme;
struct S(T)
{
T t;
void method() {}
}
void baz(S!int) {} // S!int is instantiated here when semantic analysis gets to the parameter of *buz* .
// the semantic analysis continues...
void foo()()
{
S!int x;
x.method();
}
// semantic analysis done; go back to *importer.d*
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment