Skip to content

Fix: %mem-set OFFSET has no default, unlike %mem-ref - #1813

Open
dg1sbg wants to merge 1 commit into
clasp-developers:mainfrom
dg1sbg:pr/mem-set-offset-default
Open

Fix: %mem-set OFFSET has no default, unlike %mem-ref#1813
dg1sbg wants to merge 1 commit into
clasp-developers:mainfrom
dg1sbg:pr/mem-set-offset-default

Conversation

@dg1sbg

@dg1sbg dg1sbg commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

What is broken

The methods generated for %mem-set in fli.lisp take &optional offset with no default, while the matching %mem-ref methods take &optional (offset 0). Calling %mem-set with the documented three arguments therefore passes NIL through to %offset-address-as-integer and fails:

(defparameter *p* (clasp-ffi:%allocate-foreign-object :float))

(clasp-ffi:%mem-ref *p* :float)         ; => 0.0     ok
(clasp-ffi:%mem-set *p* :float 2.5)     ; => error:  NIL is not of type INTEGER.
(clasp-ffi:%mem-set *p* :float 2.5 0)   ; => ok

So an offset must be supplied explicitly to %mem-set but not to %mem-ref. Both generic functions declare &optional offset, so the two accessors were plainly meant to be symmetric — only the generated methods disagree.

Fix

One token in the generate-methods macrolet: &optional offset becomes &optional (offset 0), matching the %mem-ref method generated three lines above it.

Compatibility

Strictly additive. The only arity whose behaviour changes is the 3-argument call, which previously errored unconditionally:

  • 3 args — was an error, now works as offset 0.
  • 4 args with an offset — unchanged.
  • 4 args with an explicit NIL — unchanged, still errors, because an explicitly supplied argument means the default form never runs.

No call that worked before behaves differently.

Tests

Adds mem-set-default-offset to the FFI suite in defcallback-native.lisp. The pre-existing cffi-defcallback test exercises %mem-set with explicit offsets, so the 4-argument path is covered by an existing test rather than only by argument.

Full regression suite on boehm: 1975 successes, zero unexpected failures (1974 baseline + the new test). Passed MEM-SET-DEFAULT-OFFSET, Passed CFFI-DEFCALLBACK.

Found while investigating #1811, but entirely independent of it — this is a plain lambda-list oversight, not related to dispatch.

The methods generated for %mem-set took `&optional offset` with no
default, while the matching %mem-ref methods took `&optional (offset 0)`.
Calling %mem-set with the documented three arguments therefore passed NIL
through to %offset-address-as-integer and failed with

  NIL is not of type INTEGER.

so an offset had to be supplied explicitly, unlike %mem-ref:

  (clasp-ffi:%mem-ref p :float)        ; => 0.0
  (clasp-ffi:%mem-set p :float 2.5)    ; => error
  (clasp-ffi:%mem-set p :float 2.5 0)  ; => ok

Both generic functions declare `&optional offset`, so the two accessors
were meant to be symmetric; only the generated methods disagreed.

Strictly additive: behaviour changes only for the arity-3 call that
previously errored. Callers passing an explicit offset are unaffected --
an explicitly supplied NIL means the default form never runs, so that
case still errors exactly as before.

Adds a regression test to the FFI suite.
@dg1sbg
dg1sbg force-pushed the pr/mem-set-offset-default branch from afb1ac3 to 2dc8f19 Compare August 13, 2026 16:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant