[Issue 14612] New: typeid(interface) returns TypeInfo_Class object
via Digitalmars-d-bugs
digitalmars-d-bugs at puremagic.com
Wed May 20 06:49:42 PDT 2015
https://issues.dlang.org/show_bug.cgi?id=14612
Issue ID: 14612
Summary: typeid(interface) returns TypeInfo_Class object
Product: D
Version: D2
Hardware: All
OS: All
Status: NEW
Severity: normal
Priority: P1
Component: DMD
Assignee: nobody at puremagic.com
Reporter: k.hara.pg at gmail.com
In the following test code, typeid(i) does not return typeid(J) typed
TypeInfo_Interface, rather it returns typeid(J).info that is TypeInfo_Class.
import std.stdio;
interface I {}
interface J : I {}
class C : J {}
class D : C {}
void main()
{
D d = new D();
Object o = cast(Object)d;
I i = cast(I)d;
writeln(typeid(d) is typeid(D)); // true
writeln(typeid(o) is typeid(D)); // true
writeln(typeid(i) is typeid(I)); // false ?
writeln(typeid(i) is typeid(J)); // false ?
writeln(typeid(i) is typeid(D)); // false ?
writeln(typeid(i)); // prints 'test.J' !?
// old exp.classinfo property is same with typeid(exp)
writeln(d.classinfo is typeid(D)); // true
writeln(o.classinfo is typeid(D)); // true
writeln(i.classinfo is typeid(J)); // false, same with typeid()
writeln(i.classinfo is typeid(I)); // false, same with typeid()
writeln(i.classinfo is typeid(D)); // false, same with typeid()
writeln( typeid(i) is typeid(J).info); // true
writeln(i.classinfo is typeid(J).info); // true
}
----
This nonintuitive behavior comes historically from D1.
In D1, ClassInfo, TypeInfo_Class, and TypeInfo_Interface are different classes.
In there, ClassInfo
had had the information of class *and* interface definition in runtime, and two
TypeInfo-s were purely
identity objects that associated with the class/interface types.
In D2, ClassInfo and TypeInfo_Class were merged into one (by issue 3380 ?).
Now ClassInfo is an alias name of TypeInfo_Class.
But, the separation between ClassInfo and TypeInfo_Interface is still there.
And currently, typeid(i) is completely same with i.classinfo, therefore it
still returns ClassInfo == TypeInfo_Class.
-----
I think there's two ways to fix the behavior.
1. To make TypeInfo_Interface accessible from runtime interface references. To
do that,
change object.Interface struct as follows:
struct Interface
{
version(none) // old
{
TypeInfo_Class classinfo;
}
else // new
{
TypeInfo_Interface tinfo;
@property TypeInfo_Class classinfo() { return tinfo.info; }
}
void*[] vtbl;
size_t offset;
}
and then the interface vtb[0] will be the runtime TypeInfo_Interface that we
needing.
Pros: We need very little compiler and druntime changes.
Cons: It would add a small runtime cost in the dynamic cast.
See: druntime/src/rt/cast_.d
2. Separate ClassInfo from TypeInfo_Class again and define TypeInfo hierarchy
as follows:
abstract class ClassInfo : TypeInfo { ... }
class TypeInfo_Class : ClassInfo { ... }
class TypeInfo_Interface : ClassInfo { ... }
Pros: By handling ClassInfo, the runtime cost in dynamic cast operation can be
kept same with today's.
Cons: If an user still using the name 'ClassInfo', the code behavior will be
changed.
--
More information about the Digitalmars-d-bugs
mailing list