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
