PCL walker doesn't parse SPECIAL correctly
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
SBCL |
New
|
Undecided
|
Unassigned |
Bug Description
Visual inspection of the call to NOTE-DECLARATION within WALK-DECLARATIONS shows that it misbehaves if more than one symbol is given in (DECLARE (SPECIAL ...)), or when zero symbols are given, the latter being amusing only in that it causes walker-environment declarations to have (SPECIAL NIL), making later inquiry of (var-special-p nil) => T, which is inconsistent with global constants being constant, not special.
Trivial example:
(in-package sb-walker)
(walk-form
'(let ((a 3) (b 4)) (declare (special a b)) :showme (otherstuff))
nil
#'(lambda (subform context env)
(let ((*print-lines* 1)) (format t "~&~S ~S" context subform))
(if (eq subform :showme)
(format t " specialp a=>~A b=>~A" (var-special-p 'a env) (var-special-p 'b env))
subform)))
:EVAL (LET ((A 3) (B 4)) ..)
:EVAL 3
:EVAL 4
:EVAL :SHOWME specialp a=>T b=>NIL
...
In turn, there is unexpected behavior elsewhere, e.g. SB-PCL:
;; Begin 'example.lisp'
(eval-when (:compile-toplevel :load-toplevel)
(defclass dog (animal) ()))
(defmethod run ((pet dog))
(declare (special chia pet))
(format t "Run ~A run~%" (slot-value pet 'name)))
;; End
gets this:
; (SB-PCL:
; ((DECLARE (SPECIAL CHIA PET))
; (FORMAT T "Run ~A run~%"
; (SLOT-VALUE PET 'NAME))))
;
; note: Cannot optimize slot access, inheritance of #<STANDARD-CLASS DOG> is not yet
; finaliable due to forward-referenced superclasses:
whereas the code fragment producing that message is not supposed to execute due to (when (and ... (not (var-special-p ...
Of course the warning is just a symptom - it's actually trying (unsuccessfully) to do an optimization that it shouldn't try.
Incidentally the word "finalizable" is misspelled.
Using separate DECLARE forms or separate Decl-Specs in one declare form works. e.g.
(walk-form
'(let ((a 3) (b 4)) (declare (special a)(special b)) :showme (otherstuff)) nil [same walk-fn as before])
->
:EVAL (LET ((A 3) (B 4)) ..)
:EVAL 3
:EVAL 4
:EVAL :SHOWME specialp a=>T b=>T