Subject: Frame bindings referring to non-existent locals
From: Andrew Whatson <[email-masked]>
To: [email-masked]
Date: Tue, 20 Sep 2022 07:16:14 +0000
List-Id: <debbugs-submit.debbugs.gnu.org>

Hello Guilers!

I have some buggy code which fails to compile.  While printing the backtrace of
this compilation error, another error occurs and Guile reports "Exception thrown
while printing backtrace".

To reproduce the error:

  $ git clone https://gitlab.com/flatwhatson/guile-prescheme.git
  $ cd guile-prescheme
  $ git checkout d793730895aaeb4ee203f062ab3864af8fd1d5fd
  $ guild compile -L . ps-compiler/prescheme/flatten.scm

  <...snip...>
  In ice-9/eval.scm:
     626:19  7 (_ #<directory (ps-compiler prescheme linking) 7ff7692f…>)
     293:34  6 (_ #(#(#<directory (prescheme bcomp package) 7ff766…>) …))
     293:34  5 (_ #(#(#<directory (prescheme bcomp package) 7ff766…>) …))
     214:21  4 (_ #(#(#<directory (prescheme bcomp package) 7ff766…>) …))
     217:50  3 (lp (#<procedure 7ff7654c3f80 at ice-9/eval.scm:123:…> …))
     217:33  2 (lp (#<procedure 7ff7654c3f60 at ice-9/eval.scm:182:…> …))
  Exception thrown while printing backtrace:
  In procedure frame-local-ref: Argument 2 out of range: 1

  ice-9/boot-9.scm:1685:16: In procedure raise-exception:
  Wrong type to apply: #<srfi-69:hash-table real-table: #<hash-table 7faf5e6...
  <...snip...>

To investigate further, I've run the compile script from the repl and dug around
for the responsible frame:

  > ,use (scripts compile)
  > (compile "-L" "." "ps-compiler/prescheme/flatten.scm")
  ;; fails, enters debugger
  [1]> ,bt
  ;; fails to print backtrace
  [1]> ,m (system vm frame)
  [1]> ,use (system repl common) (system repl debug) (srfi srfi-43)
  [1]> (debug-frames (repl-debug (car (fluid-ref *repl-stack*))))
  ;; $1 is a vector of frame objects
  [1]> (define (dump-frame i f) (format #t "~a: ~a\n" i f) (frame-arguments f))
  [1]> (vector-for-each dump-frame $1)
  ;; fails on frame index 2
  [2]> (define (dump-binding b) (format #t "~a\n" b))
  [2]> (frame-num-locals (vector-ref $1 2))
  ;; problem frame has 1 local slot
  [2]> (for-each dump-binding (frame-bindings (vector-ref $1 2)))
  #<<binding> frame: #<frame 7fee83f4c440 lp> idx: 0 name: closure slot: 0 ...
  #<<binding> frame: #<frame 7fee83f4c440 lp> idx: 1 name: args slot: 1 ...
  [2]> (frame-num-locals (vector-ref $1 3))
  ;; parent frame has 2 local slots
  [2]> (for-each dump-binding (frame-bindings (vector-ref $1 3)))
  #<<binding> frame: #<frame 7fee83f4c430 lp> idx: 0 name: closure slot: 0 ...
  #<<binding> frame: #<frame 7fee83f4c430 lp> idx: 1 name: args slot: 1 ...

From this, it looks like there's a broken frame which has 2 bindings, but only 1
local slot, leading to the "out of range" error while printing the backtrace.
Curiously, its parent frame has the same 2 bindings, and 2 local slots as
expected.

Any ideas what is happening here?

Cheers,
Andrew