~ chicken-core (master) 5e0bbf5560c744b35fd5b43d12e6d963b2778f99


commit 5e0bbf5560c744b35fd5b43d12e6d963b2778f99
Author:     felix <felix@call-with-current-continuation.org>
AuthorDate: Wed Jul 22 10:43:59 2026 +0200
Commit:     Peter Bex <peter@more-magic.net>
CommitDate: Wed Jul 22 11:41:16 2026 +0200

    Modify global assignment debug-instrumentation at debug-level 3 to avoid shadowing of external callback
    
    The instrumentation of code produced by debug level 3 ("-d3") resulted in the
    name the compiler inferred for an external callback (via "define-external") to
    be shadowed. This caused a mismatch when checking whether the Scheme entry
    point of the callback name is in the compilers list of callbacks.
    The result was that the entry point was not deemed to be special, with
    the compiler then assuming it can optimize the procedure, including its argument
    signature, arbitrarily, as no visible caller can be found when the callback is
    defined inside a module.
    
    The instrumentation code has now been restructured to avoid a temporary
    wrapping of the "foreign-callback-wrapper" form.
    
    Signed-off-by: Peter Bex <peter@more-magic.net>

diff --git a/core.scm b/core.scm
index 9ef88f84..07875f98 100644
--- a/core.scm
+++ b/core.scm
@@ -1174,9 +1174,8 @@
 				     (mark-variable var '##compiler#always-bound))
 				   (when emit-debug-info
 				     (set! val
-				       `(##core#let ((,var ,val))
-					  (##core#debug-event C_DEBUG_GLOBAL_ASSIGN (##core#quote ,var))
-					  ,var)))
+				       `(##core#let ((,(gensym) (##core#debug-event C_DEBUG_GLOBAL_ASSIGN (##core#quote ,var))))
+					  ,val)))
 				   ;; We use `var0` instead of `var` because the {macro,current}-environment
 				   ;; are keyed by the raw and unqualified name
 				   (cond ((##sys#macro? var0 (##sys#current-environment))
diff --git a/distribution/manifest b/distribution/manifest
index 76d53a6b..047deef1 100644
--- a/distribution/manifest
+++ b/distribution/manifest
@@ -269,6 +269,7 @@ tests/life.scm
 tests/include.scm
 tests/include-ci.scm
 tests/ffi-tests.scm
+tests/ffi-tests-2.scm
 tweaks.scm
 Makefile
 Makefile.android
diff --git a/tests/ffi-tests-2.scm b/tests/ffi-tests-2.scm
new file mode 100644
index 00000000..d896a532
--- /dev/null
+++ b/tests/ffi-tests-2.scm
@@ -0,0 +1,15 @@
+;; -d3 caused shadowing of variable assigned to callback wrapper, which in 
+;; turn resulted in an invalid optimization of the callback, assuming the
+;; Scheme-level procedure was not externally visible.
+
+(module testcase () ;; NOTE: It does *not* fail outside a module!
+  (import scheme (chicken base) (chicken foreign))
+
+  (define-external (some_callback ((c-pointer void) blabla)) scheme-object
+    #t)
+
+  (define (test-callback)
+    ((foreign-safe-lambda* void ()
+       "C_return(some_callback(NULL));")))
+
+  (test-callback))
diff --git a/tests/runtests.sh b/tests/runtests.sh
index 8b4b93ea..fc9589f1 100755
--- a/tests/runtests.sh
+++ b/tests/runtests.sh
@@ -90,6 +90,8 @@ $compile compiler-tests.scm
 echo "======================================== FFI tests ..."
 $compile ffi-tests.scm
 ./a.out
+$compile -d3 ffi-tests-2.scm
+./a.out
 
 echo "======================================== csc tests ..."
 $interpret -s csc-tests.scm
Trap