oing down into X: extend INFO's variable list
     ;; accordingly.
     (let ((refs (binding-info-refs info))
           (vars (binding-info-vars info))
           (src  (tree-il-srcv x)))
       (define (extend inner-vars inner-names)
         (fold (lambda (var name vars)
                 (vhash-consq var (list name src) vars))
               vars
               inner-vars
               inner-names))

       (match x
         (($ <lexical-ref> src name gensym)
          (make-binding-info vars (vhash-consq gensym #t refs)))
         (($ <lexical-set> src name gensym)
          (make-binding-info vars (vhash-consq gensym #t refs)))
         (($ <lambda-case> src req opt rest kw inits gensyms body alt)
          (let ((names `(,@req
                         ,@(or opt '())
                         ,@(if rest (list rest) '())
                         ,@(if kw (map cadr (cdr kw)) '()))))
            (make-binding-info (extend gensyms names) refs)))
         (($ <let> src names gensyms)
          (make-binding-info (extend gensyms names) refs))
         (($ <letrec> src in-order? names gensyms)
          (make-binding-info (extend gensyms names) refs))
         (($ <fix> src names gensyms)
          (make-binding-info (extend gensyms names) refs))
         (_ info))))

   (lambda (x info env locs)
     ;; Leaving X's scope: shrink INFO's variable list
     ;; accordingly and reported unused nested variables.
     (let ((refs (binding-info-refs info))
           (vars (binding-info-vars info)))
       (define (shrink inner-vars refs)
         (vlist-for-each
          (lambda (var)
            (let ((gensym (car var)))
              ;; Don't report lambda parameters as unused.
              (if (and (memq gensym inner-vars)
                       (not (vhash-assq gensym refs))
                       (not (lambda-case? x)))
                  (let ((name (cadr var))
                        ;; We can get approximate source location by going up
                        ;; the LOCS location stack.
                        (loc  (or (caddr var)
                                  (find pair? locs))))
                    (if (and (not (gensym? name))
                             (not (eq? name '_)))
                        (warning 'unused-variable loc name))))))
          vars)
         (vlist-drop vars (length inner-vars)))

       ;; For simplicity, we leave REFS untouched, i.e., with
       ;; names of variables that are now going out of scope.
       ;; It doesn't hurt as these are unique names, it just
       ;; makes REFS unnecessarily fat.
       (match x
         (($ <lambda-case> src req opt rest kw inits gensyms)
          (make-binding-info (shrink gensyms refs) refs))
         (($ <let> src names gensyms)
          (make-binding-info (shrink gensyms refs) refs))
         (($ <letrec> src in-order? names gensyms)
          (make-binding-info (shrink gensyms refs) refs))
         (($ <fix> src names gensyms)
          (make-binding-info (shrink gensyms refs) refs))
         (_ info))))

   (lambda (result env) #t)
   (make-binding-info vlist-null vlist-null)))

