[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

error checking of args to CALL-NEXT-METHOD



[common-lisp-object-system mailing list added]

    Date: Mon, 6 Aug 90 15:58:51 PDT
    From: Doug Cutting <cutting@parc.xerox.com>

    The CLOS spec states (page 2-13):

      When providing arguments to CALL-NEXT-METHOD, the following rule
      must be satisfied or an error is signaled:  The ordered set of
      methods applicable for a changed set of arguments for
      CALL-NEXT-METHOD must be the same as the ordered set of applicable
      methods for the original arguments to the generic function.

    The phrase "an error is signaled" seems overly restrictive.  PCL does
    not detect this situation and I can see no way of ensuring it does
    without severely impacting performance.  Why not amend this to read
    "an error should be signaled" or even "the results are undefined"?

The performance impact need not be severe since usually the specialized
arguments will not be changed, and that can be tested first.  If any
specialized arguments are not EQ, go to out-of-line code that checks
whether any specialized arguments have different classes, and if so
calls COMPUTE-APPLICABLE-METHODS to see if the restriction is violated.
Programs that switch to arguments of different classes would be slow,
unless that checking is cached somehow, but other programs would not
be significantly affected.  However, even though I don't believe the
performance impact is necessarily severe, I'm not sure that checking
for this particular error is all that important.

CLOS in Symbolics Genera 8.0.1 and Symbolics Cloe 3.0 does not signal an
error in this situation either.  I used the following test case:

  (defclass tst1 ()())
  (defclass tst2 (tst1) ())
  (defmethod tst1 ((x tst1) y) (format t "~&tst1 primary method: ~S ~S" x y))
  (defmethod tst1 ((x tst2) y) (format t "~&tst2 primary method: ~S ~S" x y))
  (defmethod tst1 :around ((x tst2) y) (format t "~&tst2 around method: ~S ~S" x y) (call-next-method y x))
  (setq tst1 (make-instance 'tst1) tst2 (make-instance 'tst2))
  (tst1 tst2 tst2)	;okay
  tst2 around method: #<TST2 1105461> #<TST2 1105461>
  tst2 primary method: #<TST2 1105461> #<TST2 1105461>
  (tst1 tst2 tst1)	;invalid
  tst2 around method: #<TST2 1105461> #<TST1 1077767>
  tst2 primary method: #<TST1 1077767> #<TST2 1105461>

"An error should be signaled" is problematical unless we can define the
exact point in the program where safety is to be evaluated to decide
whether an error must be signalled.

"The consequences are undefined" would permit the most implementation
freedom but provide the least safety to users.

"The consequences are unspecified" looks as difficult to implement as
"an error is signalled" in some implementations (this wording would
forbid having optimized SETF of SLOT-VALUE go to the wrong memory
location in a program that calls CALL-NEXT-METHOD with invalid
arguments).