[armedbear-devel] Forward referenced classes woes

Stas Boukarev stassats at gmail.com
Sat Aug 11 14:20:35 UTC 2012

Consider the following code:

(defclass whitespace-normalizer (sax-proxy))

(defclass sax-proxy (broadcast-handler)

(defclass broadcast-handler ()
  ((handlers :initform nil
	     :initarg :handlers
	     :accessor broadcast-handler-handlers)))

Doing the followoing results in errors:

(setf (broadcast-handler-handlers (make-instance 'whitespace-normalizer)) 10)

There is no applicable method for the generic function
{6621477C}> when called with arguments (10 #<WHITESPACE-NORMALIZER

(setf (broadcast-handler-handlers (make-instance 'sax-proxy)) 10) 

The slot HANDLERS is missing from the class #<STANDARD-CLASS SAX-PROXY

The problem is that whitespace-normalizer and sax-proxy are
finalized too early.

Finalization happens in std-after-initialization-for-classes

by calling maybe-finalize-class-subtree, which in its turn finalizes the
class and its subclasses in case the class has all its superclasses

When (defclass whitespace-normalizer (sax-proxy)) is executed it creates
a forward-referenced-class for sax-proxy, and when sax-proxy is defined
it calls a method for ensure-class-using-class
for forward-referenced-classes. Before calling reinitialize-instance it
does (change-class class metaclass) to change from forward-referenced to
normal class. change-class in its turn calls shared-initialize method,
which calls the aforementioned std-after-initialization-for-classes, but
it doesn't supply any direct-superclass arguments. So, when
maybe-finalize-class-subtree is called it thinks that sax-proxy's sole
superclass is standard-object, so it goes ahead finalizing sax-proxy and
whitespace-normalizer at the wrong time with wrong information. And
ensure-class-using-class later call with the right direct-superclass
information doesn't matter anymore, since the classes were already badly

With best regards, Stas.

More information about the armedbear-devel mailing list