Possible bug with sbcl 2.5.11 and FN package (and NAMED-READTABLES)

Peter Keller via Sbcl-help <[email protected]> Tue, 2 Dec 2025 20:38:42 -0600
Newsgroups gmane.lisp.steel-bank.general
Message-ID <[email protected]>
Hello,

I have run into an unexpected problem when using sbcl 2.5.11 on x86_64.

When using a newly built sbcl with documented methods (and adding --fancy
and --dynamic-space-size=24Gb), and when loading the FN package from
the most recent quicklisp of 2025-06-22, I get this signaled condition:

CL-USER> (ql:quickload :fn)

;; piles of normal compilation output, then:

debugger invoked on a SIMPLE-ERROR in thread
#<THREAD tid=4031189 "main thread" RUNNING {1200030003}>:
   Bug in readtable iterators or concurrent access?

Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
   0: [CONTINUE                     ] Retry assertion.
   1: [TRY-RECOMPILING              ] Recompile fn and try loading it again
   2: [RETRY                        ] Retry
                                      loading FASL for #<CL-SOURCE-FILE "fn" "fn">.
   3: [ACCEPT                       ] Continue, treating
                                      loading FASL for #<CL-SOURCE-FILE "fn" "fn">
                                      as having been successful.
   4:                                 Retry ASDF operation.
   5: [CLEAR-CONFIGURATION-AND-RETRY] Retry ASDF operation after resetting the
                                      configuration.
   6:                                 Retry ASDF operation.
   7:                                 Retry ASDF operation after resetting the
                                      configuration.
   8: [ABORT                        ] Give up on "fn"
   9: [REGISTER-LOCAL-PROJECTS      ] Register local projects and try again.
  10:                                 Exit debugger, returning to top level.

(EDITOR-HINTS.NAMED-READTABLES::CHECK-READER-MACRO-CONFLICT #<NAMED-READTABLE 
:COMMON-LISP {12000421A3}> #<NAMED-READTABLE FN-READER {1220C19033}> #\Nul NIL)
    source: (ASSERT FROM-FN NIL
                    "Bug in readtable iterators or concurrent access?")
0]


Here is the backtrace. After the backtrace is more commentary:

0] backtrace

Backtrace for: #<SB-THREAD:THREAD tid=4031189 "main thread" RUNNING {1200030003}>
0: (EDITOR-HINTS.NAMED-READTABLES::CHECK-READER-MACRO-CONFLICT 
#<NAMED-READTABLE :COMMON-LISP {12000421A3}> #<NAMED-READTABLE FN-READER 
{1220C19033}> #\Nul NIL)
1: (EDITOR-HINTS.NAMED-READTABLES:MERGE-READTABLES-INTO #<NAMED-READTABLE 
FN-READER {1220C19033}> :STANDARD)
2: ("top level form") [toplevel]
3: (SB-FASL::LOAD-FASL-GROUP #S(SB-FASL::FASL-INPUT :STREAM #<SB-SYS:FD-STREAM 
for "file 
/home/psilord/.cache/common-lisp/sbcl-2.5.11-linux-x64/home/psilord/quicklisp/dists/quicklisp/software/fn-20241012-git/fn.fasl" 
{1220C12A93}> :TABLE #(308 
#1="/home/psilord/quicklisp/dists/quicklisp/software/fn-20241012-git/fn.lisp" 
:MACRO #<PACKAGE "FN"> FN* DEFMACRO #2=(:MACRO FN* . DEFMACRO) FORM (#2# FORM) 
MACRO-FUNCTION (MACRO-FUNCTION FN*) #(8 79 4 36 8 36 28 10 0 1 103 40 ...) ...) 
:STACK #(0 #<FUNCTION "top level form" {B800C2F8EB}> *PACKAGE* 
*STOP-ON-SYMBOLS* #S(SB-C:DEFINITION-SOURCE-LOCATION :NAMESTRING #1# :INDICES 
65537) (QUOTE LAMBDA) FN* #S(SB-C:DEFINITION-SOURCE-LOCATION :NAMESTRING #1# 
:INDICES 98305) FN*-INTERNALS NORMALIZED-ARG-COUNT VALID-_-NAME FILTER-TREE 
...) :NAME-BUFFER #("" "FIND-UNDELETED-PACKAGE-OR-LOSEE") :PRINT NIL 
:PARTIAL-SOURCE-INFO #S(SB-C::DEBUG-SOURCE :NAMESTRING #1# :CREATED 3972516143 
:START-POSITIONS NIL :PLIST NIL)))
4: ((LAMBDA NIL :IN SB-FASL::LOAD-AS-FASL))
5: (SB-IMPL::CALL-WITH-LOADER-PACKAGE-NAMES #<FUNCTION (LAMBDA NIL :IN 
SB-FASL::LOAD-AS-FASL) {1220C1622B}>)
6: (SB-FASL::LOAD-AS-FASL #<SB-SYS:FD-STREAM for "file 
/home/psilord/.cache/common-lisp/sbcl-2.5.11-linux-x64/home/psilord/quicklisp/dists/quicklisp/software/fn-20241012-git/fn.fasl" 
{1220C12A93}> NIL NIL)
7: ((LABELS SB-FASL::LOAD-STREAM-1 :IN LOAD) #<SB-SYS:FD-STREAM for "file 
/home/psilord/.cache/common-lisp/sbcl-2.5.11-linux-x64/home/psilord/quicklisp/dists/quicklisp/software/fn-20241012-git/fn.fasl" 
{1220C12A93}> T)
8: (SB-FASL::CALL-WITH-LOAD-BINDINGS #<FUNCTION (LABELS SB-FASL::LOAD-STREAM-1 
:IN LOAD) {7CDE5D7AE2CB}> #<SB-SYS:FD-STREAM for "file 
/home/psilord/.cache/common-lisp/sbcl-2.5.11-linux-x64/home/psilord/quicklisp/dists/quicklisp/software/fn-20241012-git/fn.fasl" 
{1220C12A93}> T #<SB-SYS:FD-STREAM for "file 
/home/psilord/.cache/common-lisp/sbcl-2.5.11-linux-x64/home/psilord/quicklisp/dists/quicklisp/software/fn-20241012-git/fn.fasl" 
{1220C12A93}>)
9: (LOAD 
#P"/home/psilord/.cache/common-lisp/sbcl-2.5.11-linux-x64/home/psilord/quicklisp/dists/quicklisp/software/fn-20241012-git/fn.fasl" 
:VERBOSE NIL :PRINT NIL :IF-DOES-NOT-EXIST :ERROR :EXTERNAL-FORMAT :DEFAULT)
10: (UIOP/UTILITY:CALL-WITH-MUFFLED-CONDITIONS #<FUNCTION (LAMBDA NIL :IN 
UIOP/LISP-BUILD:LOAD*) {1220C124BB}> ("Overwriting already existing readtable 
~S." #(#:FINALIZERS-OFF-WARNING :ASDF-FINALIZERS)))
11: ((SB-PCL::EMF ASDF/ACTION:PERFORM) #<unused argument> #<unused argument> 
#<ASDF/LISP-ACTION:LOAD-OP > #<ASDF/LISP-ACTION:CL-SOURCE-FILE "fn" "fn">)
12: ((LAMBDA NIL :IN ASDF/ACTION:CALL-WHILE-VISITING-ACTION))
13: ((:METHOD ASDF/ACTION:PERFORM :AROUND (ASDF/LISP-ACTION:LOAD-OP 
ASDF/LISP-ACTION:CL-SOURCE-FILE)) #<ASDF/LISP-ACTION:LOAD-OP > 
#<ASDF/LISP-ACTION:CL-SOURCE-FILE "fn" "fn">) [fast-method]
14: ((:METHOD ASDF/ACTION:PERFORM-WITH-RESTARTS (ASDF/LISP-ACTION:LOAD-OP 
ASDF/LISP-ACTION:CL-SOURCE-FILE)) #<ASDF/LISP-ACTION:LOAD-OP > 
#<ASDF/LISP-ACTION:CL-SOURCE-FILE "fn" "fn">) [fast-method]
15: ((:METHOD ASDF/ACTION:PERFORM-WITH-RESTARTS :AROUND (T T)) 
#<ASDF/LISP-ACTION:LOAD-OP > #<ASDF/LISP-ACTION:CL-SOURCE-FILE "fn" "fn">) 
[fast-method]
16: ((:METHOD ASDF/PLAN:PERFORM-PLAN (T)) #<ASDF/PLAN:SEQUENTIAL-PLAN 
{121A088F33}>) [fast-method]
17: ((FLET SB-C::WITH-IT :IN SB-C::%WITH-COMPILATION-UNIT))
18: ((:METHOD ASDF/PLAN:PERFORM-PLAN :AROUND (T)) #<ASDF/PLAN:SEQUENTIAL-PLAN 
{121A088F33}>) [fast-method]
19: ((:METHOD ASDF/OPERATE:OPERATE (ASDF/OPERATION:OPERATION 
ASDF/COMPONENT:COMPONENT)) #<ASDF/LISP-ACTION:LOAD-OP > #<ASDF/SYSTEM:SYSTEM 
"fn"> :PLAN-CLASS NIL :PLAN-OPTIONS NIL) [fast-method]
20: ((SB-PCL::EMF ASDF/OPERATE:OPERATE) #<unused argument> #<unused argument> 
#<ASDF/LISP-ACTION:LOAD-OP > #<ASDF/SYSTEM:SYSTEM "fn"> :VERBOSE NIL)
21: ((LAMBDA NIL :IN ASDF/OPERATE:OPERATE))
22: ((:METHOD ASDF/OPERATE:OPERATE :AROUND (T T)) #<ASDF/LISP-ACTION:LOAD-OP > 
#<ASDF/SYSTEM:SYSTEM "fn"> :VERBOSE NIL) [fast-method]
23: ((SB-PCL::EMF ASDF/OPERATE:OPERATE) #<unused argument> #<unused argument> 
ASDF/LISP-ACTION:LOAD-OP "fn" :VERBOSE NIL)
24: ((LAMBDA NIL :IN ASDF/OPERATE:OPERATE))
25: ((:METHOD ASDF/OPERATE:OPERATE :AROUND (T T)) ASDF/LISP-ACTION:LOAD-OP "fn" 
:VERBOSE NIL) [fast-method]
26: (ASDF/SESSION:CALL-WITH-ASDF-SESSION #<FUNCTION (LAMBDA NIL :IN 
ASDF/OPERATE:OPERATE) {121A0813CB}> :OVERRIDE T :KEY NIL :OVERRIDE-CACHE T 
:OVERRIDE-FORCING NIL)
27: ((LAMBDA NIL :IN ASDF/OPERATE:OPERATE))
28: (ASDF/SESSION:CALL-WITH-ASDF-SESSION #<FUNCTION (LAMBDA NIL :IN 
ASDF/OPERATE:OPERATE) {121A07A73B}> :OVERRIDE NIL :KEY NIL :OVERRIDE-CACHE NIL 
:OVERRIDE-FORCING NIL)
29: ((:METHOD ASDF/OPERATE:OPERATE :AROUND (T T)) ASDF/LISP-ACTION:LOAD-OP "fn" 
:VERBOSE NIL) [fast-method]
30: (ASDF/OPERATE:LOAD-SYSTEM "fn" :VERBOSE NIL)
31: (QUICKLISP-CLIENT::CALL-WITH-MACROEXPAND-PROGRESS #<FUNCTION (LAMBDA NIL 
:IN QUICKLISP-CLIENT::APPLY-LOAD-STRATEGY) {121A07648B}>)
32: (QUICKLISP-CLIENT::AUTOLOAD-SYSTEM-AND-DEPENDENCIES "fn" :PROMPT NIL)
33: ((:METHOD QUICKLISP-CLIENT:QUICKLOAD (T)) :FN :PROMPT NIL :SILENT NIL 
:VERBOSE NIL) [fast-method]
34: (QL-DIST::CALL-WITH-CONSISTENT-DISTS #<FUNCTION (LAMBDA NIL :IN 
QUICKLISP-CLIENT:QUICKLOAD) {1219D65A4B}>)
35: (SB-INT:SIMPLE-EVAL-IN-LEXENV (QUICKLISP-CLIENT:QUICKLOAD :FN) #<NULL-LEXENV>)
36: (EVAL (QUICKLISP-CLIENT:QUICKLOAD :FN))
37: (SB-EXT:INTERACTIVE-EVAL (QUICKLISP-CLIENT:QUICKLOAD :FN) :EVAL NIL)
38: (SB-IMPL::REPL-FUN NIL)
39: ((LAMBDA NIL :IN SB-IMPL::TOPLEVEL-REPL))
40: (SB-IMPL::%WITH-REBOUND-IO-SYNTAX #<FUNCTION (LAMBDA NIL :IN 
SB-IMPL::TOPLEVEL-REPL) {7CDE5D7AFC1B}>)
41: (SB-IMPL::TOPLEVEL-REPL NIL)
42: (SB-IMPL::TOPLEVEL-INIT)
43: ((FLET SB-UNIX::BODY :IN SB-IMPL::START-LISP))
44: ((FLET "WITHOUT-INTERRUPTS-BODY-3" :IN SB-IMPL::START-LISP))
45: (SB-IMPL::%START-LISP)

Here is the code in question which signaled the condition:

(defun check-reader-macro-conflict (from to char &optional subchar)
   (flet ((conflictp (from-fn to-fn)
            (assert from-fn ()
                    "Bug in readtable iterators or concurrent access?")
            (and to-fn (not (function= to-fn from-fn)))))
     (when (if subchar
               (conflictp (%get-dispatch-macro-character char subchar from)
                          (%get-dispatch-macro-character char subchar to))
               (conflictp (%get-macro-character char from)
                          (%get-macro-character char to)))
       (cerror (format nil "Overwrite ~@C in ~A." char to)
               'reader-macro-conflict
               :from-readtable from
               :to-readtable to
               :macro-char char
               :sub-char subchar))))

It resides in:

~/quicklisp/dists/quicklisp/software/named-readtables-20250622-git/src/named-readtables.lisp

So it looks like the 2025-06-22 release of named-readtables is signaling the
condition. I did not debug more about why this is happening, but this works on
SBCL 2.5.6. I can poke it to debug more if needed.

Thank you!

-pete