Templating Classinfo and Typeinfo
Version | 1 |
Created | 2009-11-02 |
Status | Draft |
Last modified | 2009-11-02 |
Author | David Simcha |
Abstract
Currently, the layout of D’s runtime type info, or RTTI, is defined in object.d. The details of how the fields of each instantiation of these classes are populated are buried deep inside the compiler. If ClassInfo and TypeInfo were instead template classes inheriting from some non-templated abstract base class that defined the interface and field layout, any compile-time introspection feature could trivially be added to RTTI and made available at runtime.
Description
D’s ability to perform introspection at compile time has improved by leaps and bounds, while runtime introspection has remained stagnant. ClassInfo and TypeInfo provide very limited capabilities in this regard and a reasonable argument can be made that they should remain limited to avoid code bloat. However, they should be extensible within the D language, without modification of the compiler.
Currently, the layout of ClassInfo and TypeInfo is defined in object.d in druntime. ClassInfo and TypeInfo receive their information partly by hard-coding of information for various builtin types and partly through magic internal to the compiler. They cannot be modified to add features by simply modifying object.d without modifying the compiler. Furthermore, since the compile-time type is not available in the implementations of ClassInfo and TypeInfo (they are not templates), it is difficult to use compile-time introspection to add features to runtime type info.
I therefore propose that ClassInfo and TypeInfo be turned into template subclasses of an abstract base class:
abstract class ClassInfo : Object {
// Define the basic layout of ClassInfo and virtual functions
// that all implementations must have.
}
class ClassInfoImpl(T) : ClassInfo {
// Populate the fields inherited from ClassInfo using
// compile-time introspection.
this() {
this.name = T.stringof;
this.vtbl = T.__vtbl;
this.destructor = cast(void*) &(T.__dtor);
static if(hasPointers!(T.tupleof)) {
this.flags |= 1; // The GC should scan.
}
// etc.
}
}
// Similar stuff for TypeInfo. Builtin types could be handled
// by template specialization.
This also provides an elegant solution to the code bloat problem. Various goodies could be included in RTTI inside version statements and enabled or disabled with a simple version switch at compile time. Those who want the extra features could easily enable them and those who care more about generating small executables could leave them disabled. For example, D’s compile time introspection capabilities are probably powerful enough to add full runtime reflection to ClassInfo, but this feature would have more overhead in terms of executable size than some would consider acceptable. If its implementation were simply placed inside a version statement, the user could easily choose whether to enable it, without increasing the complexity of the compiler implementation.
Open Issues
Obviously, when the compiler instantiates ClassInfo and TypeInfo for a new type, this will lead to infinite recursion if done naively. (You could have a situation where TypeInfo!(Foo) causes TypeInfo!( TypeInfo!(Foo)) to be created, then TypeInfo!( TypeInfo!( TypeInfo!(Foo))), and so on.) How hard would it be to simply add a special case rule to the compiler to prevent TypeInfo from being instantiated with TypeInfo, etc.?
Copyright
This document has been placed in the Public Domain.