PCL walker doesn't parse SPECIAL correctly

Bug #1055543 reported by Douglas Katzman
6
This bug affects 1 person
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::CAN-OPTIMIZE-ACCESS should *not* print a compiler note about being unable to optimize slot-value if you COMPILE-FILE a file containing these two forms (without ANIMAL being defined yet)-

;; 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::%DEFMETHOD-EXPANDER RUN NIL ((PET DOG))
; ((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

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.