perf(cli): hash set for recursive-target dir-cycle dedup

ober

eb6cec77e911a5144346bdf0749be65aa16e7473

diff --git a/lib/semgrep/cli.sls b/lib/semgrep/cli.sls
index 355aba4..edba2ce 100644
--- a/lib/semgrep/cli.sls
+++ b/lib/semgrep/cli.sls
@@ -262,10 +262,7 @@
        (or language-opt (guess-language-from-path path)))
   (def (identity-key info)
        (cons (secure-entry-device info) (secure-entry-inode info)))
-  (def (identity-seen? key seen)
-       (let loop ([xs seen])
-         (and (not (null? xs))
-              (or (equal? key (car xs)) (loop (cdr xs))))))
+  (def (identity-seen? key seen) (hash-key? seen key))
   (def (expand-open-directory-target
          language-opt
          dir
@@ -277,7 +274,7 @@
              [entry-count 0]
              [path-char-count 0]
              [ignored-paths '()]
-             [seen '()])
+             [seen (make-hash-table)])
          (let ([expanded (let walk ([relative-dir ""]
                                     [depth 0]
                                     [acc '()])
@@ -299,7 +296,7 @@
                                (error 'semgrep-cli
                                  "recursive target contains a directory cycle"
                                  relative-dir))
-                             (set! seen (cons key seen))
+                             (hash-put! seen key #t)
                              (let loop ([entries (secure-directory-list
                                                    (cli-root-handle root)
                                                    relative-dir
diff --git a/src/semgrep/cli.ss b/src/semgrep/cli.ss
index 1d6eace..3ab0f90 100644
--- a/src/semgrep/cli.ss
+++ b/src/semgrep/cli.ss
@@ -303,17 +303,14 @@
   (cons (secure-entry-device info) (secure-entry-inode info)))
 
 (def (identity-seen? key seen)
-  (let loop ([xs seen])
-    (and (not (null? xs))
-         (or (equal? key (car xs))
-             (loop (cdr xs))))))
+  (hash-key? seen key))
 
 (def (expand-open-directory-target language-opt dir root use-ignore?)
   (let ([ignore-patterns (if use-ignore? (read-semgrepignore dir) '())]
         [entry-count 0]
         [path-char-count 0]
         [ignored-paths '()]
-        [seen '()])
+        [seen (make-hash-table)])
     (let ([expanded
            (let walk ([relative-dir ""] [depth 0] [acc '()])
              (when (> depth max-recursive-depth)
@@ -327,7 +324,7 @@
                (when (identity-seen? key seen)
                  (error 'semgrep-cli "recursive target contains a directory cycle"
                         relative-dir))
-               (set! seen (cons key seen))
+                (hash-put! seen key #t)
                (let loop ([entries (secure-directory-list
                                      (cli-root-handle root)
                                      relative-dir