formatter functions should be lazy in arg count checking

Bug #1410628 reported by Douglas Katzman
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
SBCL
New
Undecided
Unassigned

Bug Description

Given:
* (defstruct foo a)
* (defmethod print-object ((self foo) stream) (when (eql (foo-a self) 42) (throw 'dog 'bone)))

Other implementations are able to process :
* (catch 'dog (format t "Hi there ~S ~S~%" (make-foo :a 42)))

But the compiler turns that format into a lambda which never executes its body because it insists on receiving 2 args.
(macroexpand-1 '(formatter "Hi there ~S ~S~%"))
#'(LAMBDA
      (STREAM
       &OPTIONAL
       (#:FORMAT-ARG669
        (ERROR 'SB-FORMAT:FORMAT-ERROR :COMPLAINT "required argument missing" :CONTROL-STRING
               "Hi there ~S ~S~%" :OFFSET 10))
       (#:FORMAT-ARG670
        (ERROR 'SB-FORMAT:FORMAT-ERROR :COMPLAINT "required argument missing" :CONTROL-STRING
               "Hi there ~S ~S~%" :OFFSET 13))
       &REST SB-FORMAT::ARGS)
    (DECLARE (IGNORABLE STREAM))
    (BLOCK NIL
      (WRITE-STRING "Hi there " STREAM)
      (PRIN1 #:FORMAT-ARG669 STREAM)
      (WRITE-STRING " " STREAM)
      (PRIN1 #:FORMAT-ARG670 STREAM)
      (TERPRI STREAM))
    SB-FORMAT::ARGS)

Probably we should have the lambda accept a dx &rest arg and use guarded expressions of the form
  (output-something (if (> (length args) K) (NTH ...) (error ...)))
which should compile not too much worse if either &rest is converted to &more or is really stack-allocated.

Revision history for this message
Douglas Katzman (dougk) wrote :

actually, since you have to return args anyway, there's no additional overhead imposed by
  (output-something (if args (pop args) (error ...))

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.