From 51af043f73c683c0609d4285a1bfee7d07e08b7a Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Mon, 9 Jul 2018 12:53:52 +0100 Subject: [PATCH] src/: Check that methods are compatible during class finalization. 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 | 3 +++ doc/layout.tex | 4 ++++ src/class-finalize-impl.lisp | 9 +++++++++ src/method-impl.lisp | 3 +++ src/method-proto.lisp | 9 +++++++++ 5 files changed, 28 insertions(+) diff --git a/doc/SYMBOLS b/doc/SYMBOLS index 95604ae..63e0abc 100644 --- a/doc/SYMBOLS +++ b/doc/SYMBOLS @@ -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 diff --git a/doc/layout.tex b/doc/layout.tex index ca31a9c..95753b1 100644 --- a/doc/layout.tex +++ b/doc/layout.tex @@ -247,6 +247,10 @@ \end{describe} \begin{describe}{gf} + {sod-message-check-methods @ @ @} +\end{describe} + +\begin{describe}{gf} {sod-message-effective-method-class @ @> @} \end{describe} diff --git a/src/class-finalize-impl.lisp b/src/class-finalize-impl.lisp index 10d2b2f..2978bd4 100644 --- a/src/class-finalize-impl.lisp +++ b/src/class-finalize-impl.lisp @@ -516,6 +516,15 @@ 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 diff --git a/src/method-impl.lisp b/src/method-impl.lisp index 91c22bb..6c751a4 100644 --- a/src/method-impl.lisp +++ b/src/method-impl.lisp @@ -272,6 +272,9 @@ (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) diff --git a/src/method-proto.lisp b/src/method-proto.lisp index 1298431..5687802 100644 --- a/src/method-proto.lisp +++ b/src/method-proto.lisp @@ -95,6 +95,15 @@ 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 -- 2.11.0