congruent-lambda-p: be more permissive with the congruency test
Lambda list congruency is described here: - 7.6.4 Congruent Lambda-lists for all Methods of a Generic Function - 7.6.5 Keyword Arguments in Generic Functions and Methods Previously we have tested conformingly for the fourth point: 4. If the generic function lambda list mentions &key, each method must accept all of the keyword names mentioned after &key, either by accepting them explicitly, by specifying &allow-other-keys, or by specifying &rest but not &key. Each method can accept additional keyword arguments of its own. The checking of the validity of keyword names is done in the generic function, not in each method. A method is invoked as if the keyword argument pair whose name is :allow-other-keys and whose value is true were supplied, though no such argument pair will be passed. The fifth point mentions that if either the generic function or any applicable method has &allow-other-keys, then function may be called with extra keyword arguments: 5. The use of &allow-other-keys need not be consistent across lambda lists. If &allow-other-keys is mentioned in the lambda list of any applicable method or of the generic function, any keyword arguments may be mentioned in the call to the generic function. This change makes the fourth point more consistent with the fifth, however it is *not* conformant when it is read literally. Reasons for this change: - this behavior is exhibited at least by SBCL and CCL, so we'll be more compatible with a non-conformant code tested on them - the change won't impact results of a correct program unless it depends on the defmethod signaling an error condition
This commit is contained in:
parent
8fc3b4a56e
commit
896e7c5895
1 changed files with 18 additions and 13 deletions
|
|
@ -120,21 +120,26 @@
|
|||
(defun congruent-lambda-p (l1 l2)
|
||||
(multiple-value-bind (r1 opts1 rest1 key-flag1 keywords1 a-o-k1)
|
||||
(si::process-lambda-list l1 'FUNCTION)
|
||||
(declare (ignore a-o-k1))
|
||||
(multiple-value-bind (r2 opts2 rest2 key-flag2 keywords2 a-o-k2)
|
||||
(si::process-lambda-list l2 'FUNCTION)
|
||||
(and (= (length r2) (length r1))
|
||||
(= (length opts1) (length opts2))
|
||||
(eq (and (null rest1) (null key-flag1))
|
||||
(and (null rest2) (null key-flag2)))
|
||||
;; All keywords mentioned in the genericf function
|
||||
;; must be accepted by the method.
|
||||
(or (null key-flag1)
|
||||
(null key-flag2)
|
||||
a-o-k2
|
||||
(null (set-difference (all-keywords keywords1)
|
||||
(all-keywords keywords2))))
|
||||
t))))
|
||||
(and (= (length r2) (length r1))
|
||||
(= (length opts1) (length opts2))
|
||||
(eq (and (null rest1) (null key-flag1))
|
||||
(and (null rest2) (null key-flag2)))
|
||||
;; All keywords mentioned in the generic function must be
|
||||
;; accepted by the method.
|
||||
(or (null key-flag1)
|
||||
(null key-flag2)
|
||||
;; Testing for a-o-k1 here may not be conformant when
|
||||
;; the fourth point of 7.6.4 is read literally, but it
|
||||
;; is more consistent with the generic function calling
|
||||
;; specification. Also it is compatible with popular
|
||||
;; implementations like SBCL and CCL. -- jd 2020-04-07
|
||||
a-o-k1
|
||||
a-o-k2
|
||||
(null (set-difference (all-keywords keywords1)
|
||||
(all-keywords keywords2))))
|
||||
t))))
|
||||
|
||||
(defun add-method (gf method)
|
||||
;; during boot it's a structure accessor
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue