Subject: bug#20087: gensym

From: [email-masked]
Date: Fri, 18 Mar 2016 17:03:27 +0000

Hello

I agree, this goes against the main assumption people have about gensym. 
I was able to reproduce the bug.

Here's a patch to libguile/symbol.c which fixes this behavior by 
incrementing the gensym counter in a loop until it creates a fresh 
symbol.
diff --git a/libguile/symbols.c b/libguile/symbols.c
index 71d9827..2df7433 100644
--- a/libguile/symbols.c
+++ b/libguile/symbols.c
@@ -394,19 +394,31 @@ SCM_DEFINE (scm_gensym, "gensym", 0, 1, 0,
   SCM suffix, name;
   int n, n_digits;
   char buf[SCM_INTBUFLEN];
-
+  SCM symbol;
+  
   if (SCM_UNBNDP (prefix))
     prefix = default_gensym_prefix;
 
-  /* mutex in case another thread looks and incs at the exact same moment */
-  scm_i_scm_pthread_mutex_lock (&scm_i_misc_mutex);
-  n = gensym_counter++;
-  scm_i_pthread_mutex_unlock (&scm_i_misc_mutex);
-
-  n_digits = scm_iint2str (n, 10, buf);
-  suffix = scm_from_latin1_stringn (buf, n_digits);
-  name = scm_string_append (scm_list_2 (prefix, suffix));
-  return scm_string_to_symbol (name);
+  while(1) {
+    /* mutex in case another thread looks and incs at the exact same moment */
+    scm_i_scm_pthread_mutex_lock (&scm_i_misc_mutex);
+    n = gensym_counter++;
+    scm_i_pthread_mutex_unlock (&scm_i_misc_mutex);
+    
+    n_digits = scm_iint2str (n, 10, buf);
+    suffix = scm_from_latin1_stringn (buf, n_digits);
+    name = scm_string_append (scm_list_2 (prefix, suffix));
+    
+    symbol = lookup_interned_symbol (name, scm_i_string_hash (name));
+    if (scm_is_true (symbol))
+      {
+        continue;
+      }
+    else
+      {
+        return scm_string_to_symbol (name);
+      }
+  }
 }
 #undef FUNC_NAME