:generic-function generic-function
:method method)
(update-dfun generic-function))
+ (setf (gf-info-needs-update generic-function) t)
(map-dependents generic-function
(lambda (dep)
(update-dependent generic-function
:generic-function generic-function
:method method)
(update-dfun generic-function)
+ (setf (gf-info-needs-update generic-function) t)
(map-dependents generic-function
(lambda (dep)
(update-dependent generic-function
dep 'remove-method method)))))))
generic-function)
+
+
+;; Tell INFO about the generic function's methods' keys so that the
+;; compiler doesn't complain that the keys defined for some method are
+;; unrecognized.
+(sb-ext:without-package-locks
+ (defun sb-c::maybe-update-info-for-gf (name)
+ (let ((gf (if (fboundp name) (fdefinition name))))
+ (when (and gf (generic-function-p gf) (not (early-gf-p gf))
+ (not (eq :declared (info :function :where-from name)))
+ (gf-info-needs-update gf))
+ (let* ((methods (generic-function-methods gf))
+ (gf-lambda-list (generic-function-lambda-list gf))
+ (tfun (constantly t))
+ keysp)
+ (multiple-value-bind (gf.required gf.optional gf.restp gf.rest
+ gf.keyp gf.keys gf.allowp)
+ (parse-lambda-list gf-lambda-list)
+ (declare (ignore gf.rest))
+ ;; 7.6.4 point 5 probably entails that if any method says
+ ;; &allow-other-keys then the gf should be construed to
+ ;; accept any key.
+ (let ((allowp (or gf.allowp
+ (find '&allow-other-keys methods
+ :test #'find
+ :key #'method-lambda-list))))
+ (setf (info :function :type name)
+ (specifier-type
+ `(function
+ (,@(mapcar tfun gf.required)
+ ,@(if gf.optional
+ `(&optional ,@(mapcar tfun gf.optional)))
+ ,@(if gf.restp
+ `(&rest t))
+ ,@(when gf.keyp
+ (let ((all-keys
+ (mapcar
+ (lambda (x)
+ (list x t))
+ (remove-duplicates
+ (nconc
+ (mapcan #'function-keywords methods)
+ (mapcar #'keywordicate gf.keys))))))
+ (when all-keys
+ (setq keysp t)
+ `(&key ,@all-keys))))
+ ,@(when (and (not keysp) allowp)
+ `(&key))
+ ,@(when allowp
+ `(&allow-other-keys)))
+ *))
+ (info :function :where-from name) :defined-method
+ (gf-info-needs-update gf) nil))))))
+ (values)))
\f
(defun compute-applicable-methods-function (generic-function arguments)
(values (compute-applicable-methods-using-types
(make-initial-dfun gf))))
(function dfun-state)
(cons (car dfun-state))))))
-
-(defmethod update-gf-dfun ((class std-class) gf)
- (let ((*new-class* class)
- (arg-info (gf-arg-info gf)))
- (cond
- ((special-case-for-compute-discriminating-function-p gf))
- ((gf-precompute-dfun-and-emf-p arg-info)
- (multiple-value-bind (dfun cache info)
- (make-final-dfun-internal gf)
- (update-dfun gf dfun cache info))))))
\f
(defmethod (setf class-name) (new-value class)
(let ((classoid (wrapper-classoid (class-wrapper class))))
(reinitialize-instance generic-function :name new-value)
new-value)
\f
+(defmethod function-keywords ((method standard-method))
+ (multiple-value-bind (nreq nopt keysp restp allow-other-keys-p
+ keywords)
+ (analyze-lambda-list (if (consp method)
+ (early-method-lambda-list method)
+ (method-lambda-list method)))
+ (declare (ignore nreq nopt keysp restp))
+ (values keywords allow-other-keys-p)))
+
(defmethod function-keyword-parameters ((method standard-method))
(multiple-value-bind (nreq nopt keysp restp allow-other-keys-p
keywords keyword-parameters)