When using templates defined in another module (via an alias), all the files must be compiled together or link errors ensue. For example:
Compile together
$ dmd main.d mymodule.d && echo "ok"
ok
Compile separately
$ dmd -c main.d && dmd -c mymodule.d && dmd main.o mymodule.o
main.o:(.data._D78TypeInfo_S8mymodule40__T15TypedIdentifierVAyaa6_4d7954797065Z15TypedIdentifier6__initZ+0x40): undefined reference to `_D8mymodule40__T15TypedIdentifierVAyaa6_4d7954797065Z15TypedIdentifier8__xopCmpFKxS8mymodule40__T15TypedIdentifierVAyaa6_4d7954797065Z15TypedIdentifierKxS8mymodule40__T15TypedIdentifierVAyaa6_4d7954797065Z15TypedIdentifierZi'
main.o:(.data._D78TypeInfo_S8mymodule40__T15TypedIdentifierVAyaa6_4d7954797065Z15TypedIdentifier6__initZ+0x48): undefined reference to `_D8mymodule40__T15TypedIdentifierVAyaa6_4d7954797065Z15TypedIdentifier8toStringMxFZAya'
collect2: error: ld returned 1 exit status
--- errorlevel 1
This screws up our build system (which builds each file separately)
Here is the code for reproducing this error:
=============================================
main.d
=============================================
import mymodule;
void main()
{
int dict[MyType];
auto x = dict[MyType(0)];
}
=============================================
mymodule.d
=============================================
module mymodule;
import std.string;
struct TypedIdentifier(string NAME) {
int value;
this(int val) {
value = val;
}
int opCmp(ref const int rhs) const {
return value > rhs ? 1 : (value < rhs ? -1 : 0);
}
string toString() const {
return format("%s(%s)", NAME, value);
}
}
alias MyType = TypedIdentifier!"MyType";
Comment #1 by tomer — 2014-04-16T12:39:22Z
Further examination shows that it's caused by the automatic addition of function attributes:
=================================
$ nm mymodule.o | grep TypedIdentifier | grep toString
_D8mymodule40__T15TypedIdentifierVAyaa6_4d7954797065Z15TypedIdentifier8toStringMxFNaNfZAya
$ nm main.o | grep TypedIdentifier | grep toString
_D8mymodule40__T15TypedIdentifierVAyaa6_4d7954797065Z15TypedIdentifier8toStringMxFZAya
=================================
NaNf = pure @safe (according to http://dlang.org/abi.html )
When the `alias` sits in mymodule.d, toString gets qualified with `pure @safe`, while when it's invoked in main.d, it only looks for `const`. If I move the alias into main.d, or just skip the alias and use the full type, everything's fine.
This seems like a bug in the alias mechanism of the core compiler.
Comment #2 by r.sagitario — 2014-10-30T07:50:54Z
I guess this is another instance of Issue 10442.
Comment #3 by robert.schadek — 2024-12-13T18:19:41Z