src/: Check that methods are compatible during class finalization.
authorMark Wooding <mdw@distorted.org.uk>
Mon, 9 Jul 2018 11:53:52 +0000 (12:53 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Mon, 9 Jul 2018 12:09:58 +0000 (13:09 +0100)
This is the payoff from the previous refactoring.  Check, specifically,
that the keyword argument types among the applicable methods are
compatible.  Otherwise we only find out about this during effective-
method computation, which happens during output, and it's too late to
stop the presses.

doc/SYMBOLS
doc/layout.tex
src/class-finalize-impl.lisp
src/method-impl.lisp
src/method-proto.lisp

index 95604ae..63e0abc 100644 (file)
@@ -546,6 +546,7 @@ method-proto.lisp
   simple-method-body                            generic
   sod-message-applicable-methods                generic
   sod-message-argument-tail                     generic
+  sod-message-check-methods                     generic
   sod-message-effective-method-class            generic
   sod-message-keyword-argument-lists            generic
   sod-method-description                        generic
@@ -1517,6 +1518,8 @@ sod-message-applicable-methods
   sod-message sod-class
 sod-message-argument-tail
   basic-message
+sod-message-check-methods
+  sod-message sod-class t
 sod-message-class
   sod-message
 sod-message-combination
index ca31a9c..95753b1 100644 (file)
 \end{describe}
 
 \begin{describe}{gf}
+    {sod-message-check-methods @<message> @<class> @<direct-methods>}
+\end{describe}
+
+\begin{describe}{gf}
     {sod-message-effective-method-class @<message> @> @<class>}
 \end{describe}
 
index 10d2b2f..2978bd4 100644 (file)
                                 has metaclass `~A'"
                                super supermeta))))))
 
+  ;; Check that all of the messages we can be sent have coherent collections
+  ;; of applicable methods.  This can go wrong, for example, if we inherit
+  ;; methods with differently typed keyword arguments.
+  (finalization-error (:mismatched-applicable-methods)
+    (dolist (super (sod-class-precedence-list class))
+      (dolist (message (sod-class-messages super))
+       (let ((methods (sod-message-applicable-methods message class)))
+         (sod-message-check-methods message class methods)))))
+
   ;; Check that an initializer is available for every slot in the class's
   ;; metaclass.  Skip this and trust the caller if the metaclass isn't
   ;; finalized yet: in that case, we must be bootstrapping, and we must hope
index 91c22bb..6c751a4 100644 (file)
                             (c-function-keywords (sod-method-type method))))
                     direct-methods))))
 
+(defmethod sod-message-check-methods
+    ((message sod-message) (class sod-class) direct-methods)
+  (compute-effective-method-keyword-arguments message class direct-methods))
 
 (defmethod shared-initialize :after
     ((method effective-method) slot-names &key direct-methods)
index 1298431..5687802 100644 (file)
                                                             direct-methods
                                                             state))))
 
+(export 'sod-message-check-methods)
+(defgeneric sod-message-check-methods (message class direct-methods)
+  (:documentation
+   "Check that the applicable methods for a MESSAGE are compatible.
+
+   Specifically, given the DIRECT-METHODS applicable for the message when
+   received by an instance of CLASS, signal errors if the methods don't
+   match the MESSAGE or each other."))
+
 (export 'sod-message-effective-method-class)
 (defgeneric sod-message-effective-method-class (message)
   (:documentation