better encapsulation support in generic functions
[sbcl.git] / src / code / fdefinition.lisp
index 0dd857c..f004d2d 100644 (file)
         (setf (info :function :definition name) (make-fdefn name))
         fdefn)))
 
+(defun maybe-clobber-ftype (name)
+  (unless (eq :declared (info :function :where-from name))
+    (clear-info :function :type name)))
+
 ;;; Return the fdefinition of NAME, including any encapsulations.
 ;;; The compiler emits calls to this when someone tries to FUNCALL
 ;;; something. SETFable.
@@ -69,6 +73,7 @@
     (or (and fdefn (fdefn-fun fdefn))
         (error 'undefined-function :name name))))
 (defun (setf %coerce-name-to-fun) (function name)
+  (maybe-clobber-ftype name)
   (let ((fdefn (fdefinition-object name t)))
     (setf (fdefn-fun fdefn) function)))
 
   (let ((fdefn (fdefinition-object name nil)))
     (unless (and fdefn (fdefn-fun fdefn))
       (error 'undefined-function :name name))
+    (when (typep (fdefn-fun fdefn) 'generic-function)
+      (return-from encapsulate
+        (encapsulate-generic-function (fdefn-fun fdefn) type body)))
     ;; We must bind and close over INFO. Consider the case where we
     ;; encapsulate (the second) an encapsulated (the first)
     ;; definition, and later someone unencapsulates the encapsulated
   (let* ((fdefn (fdefinition-object name nil))
          (encap-info (encapsulation-info (fdefn-fun fdefn))))
     (declare (type (or encapsulation-info null) encap-info))
+    (when (and fdefn (typep (fdefn-fun fdefn) 'generic-function))
+      (return-from unencapsulate
+        (unencapsulate-generic-function (fdefn-fun fdefn) type)))
     (cond ((not encap-info)
            ;; It disappeared on us, so don't worry about it.
            )
 ;;; Does NAME have an encapsulation of the given TYPE?
 (defun encapsulated-p (name type)
   (let ((fdefn (fdefinition-object name nil)))
+    (when (and fdefn (typep (fdefn-fun fdefn) 'generic-function))
+      (return-from encapsulated-p
+        (encapsulated-generic-function-p (fdefn-fun fdefn) type)))
     (do ((encap-info (encapsulation-info (fdefn-fun fdefn))
                      (encapsulation-info
                       (encapsulation-info-definition encap-info))))
   "Set NAME's global function definition."
   (declare (type function new-value) (optimize (safety 1)))
   (with-single-package-locked-error (:symbol name "setting fdefinition of ~A")
+    (maybe-clobber-ftype name)
 
     ;; Check for hash-table stuff. Woe onto him that mixes encapsulation
     ;; with this.