;; We still need to deal with the class case too, but at
;; least #.(find-class 'integer) and integer as equivalent
;; specializers with this.
- (let* ((specializer (if (and (typep specializer 'class)
- (let ((name (class-name specializer)))
- (and name (symbolp name)
- (eq specializer (find-class name nil)))))
- (class-name specializer)
- specializer))
- (kind (info :type :kind specializer)))
-
- (flet ((specializer-class ()
- (if (typep specializer 'class)
- specializer
- (find-class specializer nil))))
+ (let* ((specializer-nameoid
+ (if (and (typep specializer 'class)
+ (let ((name (class-name specializer)))
+ (and name (symbolp name)
+ (eq specializer (find-class name nil)))))
+ (class-name specializer)
+ specializer))
+ (kind (info :type :kind specializer-nameoid)))
+
+ (flet ((specializer-nameoid-class ()
+ (typecase specializer-nameoid
+ (symbol (find-class specializer-nameoid nil))
+ (class specializer-nameoid)
+ (class-eq-specializer
+ (specializer-class specializer-nameoid))
+ (t nil))))
(ecase kind
- ((:primitive) `(type ,specializer ,parameter))
+ ((:primitive) `(type ,specializer-nameoid ,parameter))
((:defined)
- (let ((class (specializer-class)))
- ;; CLASS can be null here if the user has erroneously
- ;; tried to use a defined type as a specializer; it
- ;; can be a non-BUILT-IN-CLASS if the user defines a
- ;; type and calls (SETF FIND-CLASS) in a consistent
- ;; way.
+ (let ((class (specializer-nameoid-class)))
+ ;; CLASS can be null here if the user has
+ ;; erroneously tried to use a defined type as a
+ ;; specializer; it can be a non-BUILT-IN-CLASS if
+ ;; the user defines a type and calls (SETF
+ ;; FIND-CLASS) in a consistent way.
(when (and class (typep class 'built-in-class))
- `(type ,specializer ,parameter))))
+ `(type ,specializer-nameoid ,parameter))))
((:instance nil)
- (let ((class (specializer-class)))
+ (let ((class (specializer-nameoid-class)))
(cond
(class
(if (typep class '(or built-in-class structure-class))
;; ...)). Best to let the user know we haven't
;; been able to extract enough information:
(style-warn
- "~@<can't find type for presumed class ~S in ~S.~@:>"
- specializer
+ "~@<can't find type for specializer ~S in ~S.~@:>"
+ specializer-nameoid
'parameter-specializer-declaration-in-defmethod)
'(ignorable)))))
((:forthcoming-defclass-type)
--- /dev/null
+;;;; miscellaneous side-effectful tests of the MOP
+
+;;;; This software is part of the SBCL system. See the README file for
+;;;; more information.
+;;;;
+;;;; While most of SBCL is derived from the CMU CL system, the test
+;;;; files (like this one) were written from scratch after the fork
+;;;; from CMU CL.
+;;;;
+;;;; This software is in the public domain and is provided with
+;;;; absolutely no warranty. See the COPYING and CREDITS files for
+;;;; more information.
+
+;;; This isn't really a test of the MOP per se. PCL historically has
+;;; a CLASS-EQ specializer, which it uses internally to achieve
+;;; certain effects. There's no particular reason that it should be
+;;; exposed to the user, except that some people have asked for it at
+;;; some point; however, there is also no particular reason that code
+;;; using it should be gratuitously broken, as it was for a while by
+;;; the SB-PCL::PARAMETER-SPECIALIZER-DECLARATION-IN-DEFMETHOD
+;;; function. So it's fine if this test starts failing, as long as
+;;; it's deliberate.
+
+(in-package "CL-USER")
+
+(defclass super () ())
+(defclass sub (super) ())
+
+(defgeneric test (x))
+
+(defmethod test ((x t)) nil)
+(let ((spec (sb-pcl::class-eq-specializer (find-class 'super))))
+ (eval `(defmethod test ((x ,spec)) t)))
+
+(assert (test (make-instance 'super)))
+(assert (null (test (make-instance 'sub))))