Comment 2 for bug 695286

Revision history for this message
Roman Marynchak (roman-marynchak) wrote :

I have found the corresponding CLHS section - 6.1.1.7. It says: "Destructuring allows binding of a set of variables to a corresponding set of values anywhere that a value can normally be bound to a single variable. During loop expansion, each variable in the variable list is matched with the values in the values list. If there are more variables in the variable list than there are values in the values list, the remaining variables are given a value of nil. If there are more values than variables listed, the extra values are discarded".

Our LOOP expansion uses DESTRUCTURING-BIND directly through LOOP-DESTRUCTURING-BIND, so the problem occurs (because DESTRUCTURING-BIND does not allow the pattern mismatch). Consider this macroexpansion:

* (macroexpand '(loop with (a b) = (list)))

(BLOCK NIL
  (LET ((#:LOOP-DESTRUCTURE-608 (LIST)))
    (SB-LOOP::LOOP-DESTRUCTURING-BIND (A B) #:LOOP-DESTRUCTURE-608
                                      (SB-LOOP::LOOP-BODY NIL NIL NIL NIL
                                                          NIL))))

SB-LOOP::LOOP-DESTRUCTURING-BIND code is below:

(sb!int:defmacro-mundanely loop-destructuring-bind
    (lambda-list arg-list &rest body)
  (let ((*ignores* nil))
    (declare (special *ignores*))
    (let ((d-var-lambda-list (subst-gensyms-for-nil lambda-list)))
      `(destructuring-bind ,d-var-lambda-list
           ,arg-list
         (declare (ignore ,@*ignores*))
         ,@body))))

IMHO, LOOP-DESTRUCTURING-BIND macro is a place where the fix should be implemented.

Also, note that CCL has this bug too (and CLISP does not).