redefining structure accessors using DEFUN
Bug #540063 reported by
Nikodemus Siivola
This bug affects 1 person
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
SBCL |
Fix Released
|
Medium
|
Douglas Katzman |
Bug Description
...doesn't work, doesn't warn that this is not going to work.
CL-USER> (defstruct x y)
X
CL-USER> (defun x-y (z) (list :x-y z))
STYLE-WARNING: redefining X-Y in DEFUN
X-Y
CL-USER> (lambda (z) (x-y z))
#<FUNCTION (LAMBDA (Z)) {1003DE8709}>
CL-USER> (funcall * (make-x :y t))
T
CL-USER> (lambda (z) (declare (notinline x-y)) (x-y z))
#<FUNCTION (LAMBDA (Z)) {100387D049}>
CL-USER> (funcall * (make-x :y t))
Control stack guard page temporarily disabled: proceed with caution
Changed in sbcl: | |
assignee: | nobody → Douglas Katzman (dougk) |
status: | Confirmed → Fix Committed |
Changed in sbcl: | |
status: | Fix Committed → Fix Released |
To post a comment you must log in.
This report is a bit muddled. There are at least three different flavors of "possible broken-ness" going on, but 1 of them isn't technically a bug, one of them is kind of a bug but very fixable, and one is a bug.
I would assume that description of "won't work" refers only to the "actual" bug here. But the evidence presented above illustrates the other bits of broken-ness, not what I would say is the bug.
Taking those in order:
- if *print-circle* were on, stack exhaustion would not have happened. This is certainly the least bug-like of the issues, in as much as attempting to print '#1=(foo . #1#) without *print-circle* on should also "not work"
- the printer is confused. It could easily be made to use '%instance-ref' on the slot index, instead of funcalling the dsd-accessor. This would at least make the printer immune to redefinitions like above, which is arguably an improvement, despite that the user has arranged not to be able to actually access a slot (because of obscuring its accessor with some other random function).
- DEFUN never erases a source-transform, so that you have this weird state in which compiling a call to a thing is not the same as funcalling through the name. At some point I tried to see what happens if we always make (setf fdefinition), and hence DEFUN, remove any source-transform, and then have the *last* action performed by DEFSTRUCT be the installation of transforms. This wasn't as simple as it sounds.