;;; any point. If there is more than one, the specified tiebreaker
;;; rule is used to choose among them.
-(defmethod compute-class-precedence-list ((root slot-class))
+(defmethod compute-class-precedence-list ((root class))
(compute-std-cpl root (class-direct-superclasses root)))
(defstruct (class-precedence-description
(cpd-count 0))
(defun compute-std-cpl (class supers)
- (cond ((null supers) ;First two branches of COND
- (list class)) ;are implementing the single
- ((null (cdr supers)) ;inheritance optimization.
- (cons class
- (compute-std-cpl (car supers)
- (class-direct-superclasses (car supers)))))
- (t
- (multiple-value-bind (all-cpds nclasses)
- (compute-std-cpl-phase-1 class supers)
- (compute-std-cpl-phase-2 all-cpds)
- (compute-std-cpl-phase-3 class all-cpds nclasses)))))
+ (cond
+ ;; the first two branches of this COND are implementing an
+ ;; optimization for single inheritance.
+ ((and (null supers)
+ (not (forward-referenced-class-p class)))
+ (list class))
+ ((and (null (cdr supers))
+ (not (forward-referenced-class-p (car supers))))
+ (cons class
+ (compute-std-cpl (car supers)
+ (class-direct-superclasses (car supers)))))
+ (t
+ (multiple-value-bind (all-cpds nclasses)
+ (compute-std-cpl-phase-1 class supers)
+ (compute-std-cpl-phase-2 all-cpds)
+ (compute-std-cpl-phase-3 class all-cpds nclasses)))))
(defvar *compute-std-cpl-class->entry-table-size* 60)
(if (class-name class)
(format nil "named ~S" (class-name class))
class)))
- (let ((names (mapcar #'class-or-name
- (cdr (find-superclass-chain class forward-class)))))
- (cpl-error class
- "The class ~A is a forward referenced class.~@
- The class ~A is ~A."
- (class-or-name forward-class)
- (class-or-name forward-class)
- (if (null (cdr names))
- (format nil
- "a direct superclass of the class ~A"
- (class-or-name class))
- (format nil
- "reached from the class ~A by following~@
+ (if (eq class forward-class)
+ (cpl-error class
+ "The class ~A is a forward referenced class."
+ (class-or-name class))
+ (let ((names (mapcar #'class-or-name
+ (cdr (find-superclass-chain class forward-class)))))
+ (cpl-error class
+ "The class ~A is a forward referenced class.~@
+ The class ~A is ~A."
+ (class-or-name forward-class)
+ (class-or-name forward-class)
+ (if (null (cdr names))
+ (format nil
+ "a direct superclass of the class ~A"
+ (class-or-name class))
+ (format nil
+ "reached from the class ~A by following~@
the direct superclass chain through: ~A~
~% ending at the class ~A"
- (class-or-name class)
- (format nil
- "~{~% the class ~A,~}"
- (butlast names))
- (car (last names))))))))
+ (class-or-name class)
+ (format nil
+ "~{~% the class ~A,~}"
+ (butlast names))
+ (car (last names)))))))))
(defun find-superclass-chain (bottom top)
(labels ((walk (c chain)
\f
(defmethod finalize-inheritance ((class std-class))
(update-class class t))
+
+(defmethod finalize-inheritance ((class forward-referenced-class))
+ ;; FIXME: should we not be thinking a bit about what kinds of error
+ ;; we're throwing? Maybe we need a clos-error type to mix in? Or
+ ;; possibly a forward-referenced-class-error, though that's
+ ;; difficult given e.g. class precedence list calculations...
+ (error
+ "~@<FINALIZE-INHERITANCE was called on a forward referenced class:~
+ ~2I~_~S~:>"
+ class))
+
\f
(defun class-has-a-forward-referenced-superclass-p (class)
(or (forward-referenced-class-p class)
(assert (equal (incompatible-ll-test-2 t 1 2) '(1 2)))
(assert (eq (incompatible-ll-test-2 1 :bar 'yes) 'yes))
\f
+;;; Attempting to instantiate classes with forward references in their
+;;; CPL should signal errors (FIXME: of what type?)
+(defclass never-finished-class (this-one-unfinished-too) ())
+(multiple-value-bind (result error)
+ (ignore-errors (make-instance 'never-finished-class))
+ (assert (null result))
+ (assert (typep error 'error)))
+(multiple-value-bind (result error)
+ (ignore-errors (make-instance 'this-one-unfinished-too))
+ (assert (null result))
+ (assert (typep error 'error)))
+\f
;;;; success
(sb-ext:quit :unix-status 104)