get-setf-expansion of CxxR functions is nonconformant
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
SBCL |
Fix Released
|
Undecided
|
Douglas Katzman |
Bug Description
Citing http://
"This place ... Is equivalent to this place ...
(caar x) (car (car x))
(cadr x) (car (cdr x))
..." and so on.
A simple counterexample to the stipulated "equivalence" of places:
* (defun g (x) (rplaca x (cons 111 222)) 100)
* (defun h (x) (rplaca x nil) 10)
* (defun bar (selector)
(let* ((inner (cons 5 6))
(cell (list inner)))
(format t "Cell=~S~%" cell)
(ecase selector
(:car-car (incf (car (car cell)) (g cell)))
(:caar (incf (caar cell) (g cell)))
(:cdr-car (incf (cdr (car cell)) (h cell)))
(:cdar (incf (cdar cell) (h cell))))
(format t "Cell=~S, inner=~S~%" cell inner)
(values)))
* (bar :car-car)
Cell=((5 . 6))
Cell=((111 . 222)), inner=(105 . 6)
* (bar :caar)
Cell=((5 . 6))
Cell=((211 . 222)), inner=(5 . 6)
* (bar :cdr-car)
Cell=((5 . 6))
Cell=(NIL), inner=(5 . 16)
* (bar :cdar)
Cell=((5 . 6))
debugger invoked on a SIMPLE-TYPE-ERROR in thread
#<THREAD "main thread" RUNNING {1002D5ECB3}>:
Argument X is not a NUMBER: NIL
The problem is that the setf "getter" for CAAR returns CAAR itself instead of CAR of a temp as required by equivalence to the exploded form of CAR/CDR compositions.
* (macroexpand-1 '(incf (caar x)))
(LET* ((#:G536 X) (#:G537 (+ (CAAR #:G536) 1)))
(SB-KERNEL:
Same is true of FIRST,SECOND,etc and of all R/M/W macros that use get-setf-expansion.
Also I suspect that while our expansion of (PUSHNEW X (NTH I L)) is not non-conformant, it would be a lot nicer if if expanded to something like:
(let ((cell (nthcdr index list))) (pushnew item (car cell))))
instead of something like:
(%setnth ... (adjoin ... (nth )))
Changed in sbcl: | |
assignee: | nobody → Douglas Katzman (dougk) |
status: | New → In Progress |
Changed in sbcl: | |
status: | In Progress → Fix Committed |
Changed in sbcl: | |
status: | Fix Committed → Fix Released |