Comment 1 for bug 1070635

Douglas Katzman (dougk) wrote :

OK, this kind of makes sense. All the quantifiers are defined in terms of (MAP NIL #'fn ...). The transform of MAP for a known sequence type ends up not demanding a closure over the functional arg, but the full call to MAP passes the functional arg which is not known to be downward. (Frankly I think that's *also* a bug: MAP never "holds on" to its functional arg but the compiler doesn't know it)

However, the solution for _this_ bug is in the compiler macros for the quantifiers. Even with a dynamic-extent declaration on my function RECURSE, that does not make the inner lambda also dynamic-extent.
(Which, by the way, also seems to contradict the premise that dynamic-extent is contagious!)

So forcing a dynamic-extent declaration into the expansion of the compiler-macro seems to do the trick:

diff --git a/src/code/seq.lisp b/src/code/seq.lisp
index bc678fd..58f5438 100644
--- a/src/code/seq.lisp
+++ b/src/code/seq.lisp
@@ -1183,17 +1183,17 @@ many elements are copied."
                 ;; from the old seq.lisp into target-seq.lisp.
                 (define-compiler-macro ,name (pred first-seq &rest more-seqs)
                   (let ((elements (make-gensym-list (1+ (length more-seqs))))
- (blockname (gensym "BLOCK")))
+ (blockname (gensym "BLOCK"))
+ (wrapped-pred (gensym "PRED")))
                     (once-only ((pred pred))
                       `(block ,blockname
- (map nil
- (lambda (,@elements)
- (let ((pred-value (funcall ,pred ,@elements)))
- (,',found-test pred-value
- (return-from ,blockname
- ,',found-result))))
- ,first-seq
- ,@more-seqs)
+ (flet ((,wrapped-pred (,@elements)
+ (let ((pred-value (funcall ,pred ,@elements)))
+ (,',found-test pred-value
+ (return-from ,blockname
+ ,',found-result)))))
+ (declare (dynamic-extent #',wrapped-pred))
+ (map nil #',wrapped-pred ,first-seq ,@more-seqs))
                          ,',unfound-result)))))))

I haven't built this in full yet, but it does appear to have fixed my test case.