[DRuntime] TypeInfo bug when using associative array + shared library
On main binary:
//other.d
class Other
{
}
//main.d
void main()
{
import other;
int[TypeInfo] typeMap = [
typeid(Other]: 10
];
//use dynamicaly loaded getType
assert(getType() in typeMap);
}
On other binary:
TypeInfo getType()
{
import other;
return typeid(Other);
}
They have the same fully qualified name, same hash, but it still errors. Happens in both dmd and ldc2.
That may be due to
// lookup a key
inout(Bucket)* findSlotLookup(size_t hash, scope const void* pkey, scope const TypeInfo keyti) inout
{
for (size_t i = hash & mask, j = 1;; ++j)
{
if (buckets[i].hash == hash && keyti.equals(pkey, buckets[i].entry))
return &buckets[i];
else if (buckets[i].empty)
return null;
i = (i + j) & mask;
}
}
This is the function for finding the data.
And as you can see, the equals implementation of TypeInfo differs from opEquals:
bool opEquals(const TypeInfo ti) @safe nothrow const
{
/* TypeInfo instances are singletons, but duplicates can exist
* across DLL's. Therefore, comparing for a name match is
* sufficient.
*/
if (this is ti)
return true;
return ti && this.toString() == ti.toString();
}
bool equals(in void* p1, in void* p2) const { return p1 == p2; }
Since they are void, no opEquals is actually called. I'm confused on what is the expected behavior. Of course I can simply use a string from typeinfo, but that wasn't the intended way to use at first.
keyti here should be the TypeInfo of a TypeInfo, which is a TypeInfo_Class. And that .equals() casts the void* params to Object: https://github.com/dlang/dmd/blob/baee0d8080011ed357a0351ca1aebbb3c1abb41d/druntime/src/object.d#L1601-L1607
And that should then invoke TypeInfo.opEquals() that you linked above.
Humm yeah that makes sense, but now I wonder why it is still not working then
I suggest using LDC's -link-defaultlib-debug and stepping through it with a debugger.