circularity detection of FORMAT NIL behaves oddly in PRINT-OBJECT methods

Bug #1644948 reported by 3b
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
SBCL
New
Undecided
Unassigned

Bug Description

(defclass foo () ())
(defmethod print-object ((o foo) s)
  (let ((x "foo"))
    (flet ((twice (a s y)
             (format s "~a ~a ~a" a y y)))
      (format s "s ~a ~a~%" x x)
      (twice "twice " s x)
      (format s "~&nil ~s~%" (format nil "~a ~a" x x))
      (twice "twice " s x)
      (format s "~&nil ~s~%" (format nil "~a ~a" x x))
      (format s "nil/twice ~s~%" (twice "" nil x))
      (format s "nil ~s~%" (format nil "~a ~a ~a" "" x x))
      (format s "~&wots ~s~%"
              (with-output-to-string (ss)
                (format ss "~a ~a ~a" "" x x)))
      (format s "nil ~s~%" (format nil "~a ~a ~a" "" x x))
      (format s "wots/twice ~s~%"
              (with-output-to-string (ss)
                (twice " " ss x)))
      (format s "nil ~s~%" (format nil "~a ~a" x x))
      (format s "nil/twice ~s~%" (twice "" nil x))
      (format s "nil ~s~%" (format nil "~a ~a" x x)))))

(let ((*print-circle* t))
  (princ (make-instance 'foo))
  (values))

s #1=foo #1#
#2=twice #1# #1#
nil "foo foo"
#2# #1# #1#
nil "foo foo"
nil/twice "#3= #1# #1#"
nil " foo foo"
wots "#3# #1# #1#"
nil "#3# #1# #1#"
wots/twice " #1# #1#"
nil "#1# #1#"
nil/twice "#3# #1# #1#"
nil "#1# #1#"

not completely sure what the correct output is, but (format nil "~a ~a" x x) should probably return either "#1=foo #1#" or "#1# #1#" (or "#1=foo #1#" once then "#1# #1#") depending on whether you consider "creates and returns a string containing the output from control-string" from http://www.lispworks.com/documentation/HyperSpec/Body/22_c.htm to mean it is printing to a new stream or not, and if so if it is a new one per call. http://www.lispworks.com/documentation/HyperSpec/Body/v_pr_cir.htm specifies that circularity detection starts over when printing to a stream other than the one passed to the PRINT-OBJECT method.

Either way, returning "#1# #1#" when the NIL isn't a constant, then returning "foo foo" a few times when NIL is passed directly, then "#1# #1#" when NIL is passed directly after calling with-output-to-string seems wrong.

"#1# #1#" shoring up in with-output-to-string also looks wrong, probably https://bugs.launchpad.net/sbcl/+bug/309090

see also https://bugs.launchpad.net/sbcl/+bug/308948

Tags: printer
Revision history for this message
3b (00003b) wrote :

reported by _death on #lisp in context of condition reports (which use print-object) in http://paste.lisp.org/display/330728

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.