On Thu, Oct 9, 2025 at 11:24 AM Nikolaos Chatzikonstantinou
<[email protected]> wrote:
>
> On Thu, Oct 9, 2025 at 7:26 AM Nikolaos Chatzikonstantinou
> <[email protected]> wrote:
> >
> > On Sun, Sep 21, 2025 at 12:47 AM Nikolaos Chatzikonstantinou
> > <[email protected]> wrote:
> > >
> > > Hello bug-guile,
> > >
> > > I have a structure (srfi srfi-9 gnu) that keeps parts of strings in a
> > > binary tree (it's a rope). The intention was to have it immutable, so
> > > I used substring/shared. I kept getting errors on my unit tests when I
> > > referenced individual characters; I could not replicate these errors
> > > on the REPL. Eventually I realized that substring/shared caused them.
> >
> > I want to offer a small (<100 LoC) reproducible example now. I'm using
> > 3.0.10. Try to run the test suite with autocompilation disabled
> > (--no-auto-compile), and you should get failure (if success, try
> > running again, rarely it succeeds.) If you compile the test.scm file,
> > then it should work fine.
> >
> > I am not sure that I can figure this one out myself further, but
> > somehow it is related to my projects tests being left uncompiled. Does
> > anyone have an insight to the problem here?
>
> Here is an even smaller reproducible example (see attached). It's one
> module with the function
>
>   (define-public (string-ref-0 s) (string-ref s 0))
>
> which fails this test:
>
>   (test-eqv "ref with zero index."
>     (string-ref "hello" 0)
>     (string-ref-0 (substring/shared "hello" 0 1)))
>
> Instructions to reproduce the bug are in README.md. I checked that it
> is still a bug in HEAD.

I also figured out that -O0 -Ocps -Oresolve-primitives is the level of
optimization causing it. Anything less is OK. Here is the disassembly:

## Buggy: -Ocps -Oresolve-primitives

```
Disassembly of #<procedure string-ref-0 (s)> at #x7f5ad3a8924c:

   0    (instrument-entry 16419)                              at bug.scm:2:0
   2    (assert-nargs-ee/locals 2 3)    ;; 5 slots (1 arg)
   3    (make-immediate 4 2)            ;; 0                  at bug.scm:2:46
   4    (immediate-tag=? 3 7 0)         ;; heap-object?       at bug.scm:2:32
   6    (jne 30)                        ;; -> L4
   7    (heap-tag=? 3 127 21)           ;; string?
   9    (jne 27)                        ;; -> L4
  10    (word-ref/immediate 2 3 3)
  11    (call-u64<-scm 1 4 18)          ;; scm->u64
  13    (u64<? 1 2)
  14    (jnl 20)                        ;; -> L3
  15    (word-ref/immediate 4 3 2)
  16    (uadd 4 4 1)
  17    (scm-ref/immediate 3 3 1)
  18    (tail-pointer-ref/immediate 2 3 2)
  19    (word-ref/immediate 1 3 0)
  20    (load-u64 0 0 1024)
  23    (ulogand 1 1 0)
  24    (s64-imm=? 1 0)
  25    (je 4)                          ;; -> L1
  26    (ulsh/immediate 4 4 2)
  27    (u32-ref 4 2 4)
  28    (j 2)                           ;; -> L2
L1:
  29    (u8-ref 4 2 4)
L2:
  30    (tag-char 4 4)
  31    (reset-frame 1)                 ;; 1 slot
  32    (handle-interrupts)
  33    (return-values)
L3:
  34    (throw/value+data 4 16351)      ;; #(out-of-range "string-ref"
"Argument 2 out of range: ~S")
L4:
  36    (throw/value+data 3 16375)      ;; #(wrong-type-arg
"string-ref" "Wrong type argument in position 1 (expecting…")
```

## OK: -Ocps

```
Disassembly of #<procedure string-ref-0 (s)> at #x7ff512c8d24c:

   0    (instrument-entry 16371)                              at bug.scm:2:0
   2    (assert-nargs-ee/locals 2 1)    ;; 3 slots (1 arg)
   3    (static-ref 2 16356)            ;; #f                 at bug.scm:2:33
   5    (immediate-tag=? 2 7 0)         ;; heap-object?
   7    (je 9)                          ;; -> L1
   8    (static-ref 2 16279)            ;; #<directory (bug) 7ff513e46820>
  10    (static-ref 0 16359)            ;; string-ref
  12    (call-scm<-scm-scm 2 2 0 111)   ;; lookup-bound
  14    (static-set! 2 16345)           ;; #f
L1:
  16    (scm-ref/immediate 2 2 1)
  17    (make-immediate 0 2)            ;; 0                  at bug.scm:2:46
  18    (handle-interrupts)                                   at bug.scm:2:32
  19    (tail-call)
```

## OK: -Oresolve-primitives

```
Disassembly of #<procedure string-ref-0 (s)> at #x7f6170d83230:

   0    (instrument-entry 16372)                              at bug.scm:2:0
   2    (assert-nargs-ee/locals 2 9)    ;; 11 slots (1 arg)
   3    (static-ref 0 16359)            ;; #f                 at bug.scm:2:32
   5    (immediate-tag=? 0 7 0)         ;; heap-object?
   7    (je 7)                          ;; -> L1
   8    (call-scm<-scmn-scmn 0 16248 16356 112);; lookup-bound-public
  12    (static-set! 0 16350)           ;; #f
L1:
  14    (scm-ref/immediate 8 0 1)
  15    (mov 7 9)                                             at bug.scm:2:44
  16    (make-immediate 6 2)            ;; 0                  at bug.scm:2:46
  17    (mov 10 8)                                            at bug.scm:2:32
  18    (mov 9 7)
  19    (mov 8 6)
  20    (reset-frame 3)                 ;; 3 slots
  21    (handle-interrupts)
  22    (tail-call)
```

Regards,
Nikolaos Chatzikonstantinou



Reply via email to