Abstract. Much recent work on proof-carrying code aims to build certifying compilers for single-inheritance object-oriented languages, such as Java or C#. Some advanced object-oriented languages support compiling a derived class without complete information about its base class. This strategy-though necessary for supporting features such as mixins, traits, and first-class classes-is not wellsupported by existing typed intermediate languages. We present a low-level IL with a type system based on the Calculus of Inductive Constructions. It is an appropriate target for efficient, type-preserving compilation of various forms of inheritance, even when the base class is unknown at compile time. Languages (such as Java) that do not require such flexibility are not penalized for it at run time.
MotivationIn most object-oriented languages, programmers factor their solutions over a hierarchy of classes. Since the classes in a hierarchy may appear in different compilation units, one question that the language designer (or implementer) must address is: how much information about a base class is needed to compile its derived class?With its emphasis on efficient object layout and method dispatch, C++ [32] requires complete information about the base class: the number, locations, and types of all its fields and methods. Indeed, it is because C++ depends on this information that a seemingly minor change to a base class triggers recompilation of all its descendents. Java [23] is somewhat more flexible. To support binary compatibility, its class files are not committed to a particular object layout. A derived class depends only on the names and types of the base class fields and methods that it uses. Nevertheless, most Java implementations ultimately compile classes to lower-level code using the same layouts and techniques as C++.A few modern object-oriented languages allow classes as module parameters (Moby [15], OCaml [28]) or as first-class values (Loom [5]). Other languages support more flexible forms of inheritance, such as mixins [24,3] and traits [29]. If a base class is not available for inspection when a derived class is compiled, we say the base class is not manifest. Implementations of these languages use a dictionary data structure to map method and field names to their locations in the object layout. The dictionary may be applied at link time or at run time, as required by the language.Here is a simple example in OCaml (although it could be expressed just as easily in Moby). We declare a signature for modules containing a circle class that implements Below, CircleBBox declares a class bbox that inherits from a (non-manifest) base class circle, overrides the area method (using a super call), and defines a new method bounds.module CircleBBox = functor (C : CIRCLE) -> struct class bbox arg = object (self) inherit C.circle arg as super method area = super#area * 4.0 / pi (* area of bbox *) method bounds = let (x,y) = self#center in let r = self#radius in ((x-r,y-r), (x+r,y+r)) end endTo compile this functor, we must mak...