cargo build --release flags a clashing extern declaration for _setjmp:
warning: `setjmp` redeclares `_setjmp` with a different signature
--> crates/perry-runtime/src/promise.rs:956:9
|
956 | #[link_name = "_setjmp"]
| ^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
|
::: crates/perry-runtime/src/gc.rs:1860:13
|
1860 | #[link_name = "_setjmp"]
| ------------------------ `_setjmp` previously declared here
|
= note: expected `unsafe extern "C" fn(*mut u64) -> i32`
found `unsafe extern "C" fn(*mut i32) -> i32`
= note: `#[warn(clashing_extern_declarations)]` on by default
Why this matters
Both sites link to the same C symbol (_setjmp) with different parameter types (*mut u64 vs *mut i32). If they happen to be called with buffers sized for one but the runtime layout matches the other, this is undefined behavior — buffer corruption is silent and platform-dependent. The fact that it currently appears to work is luck of the macOS / aarch64 ABI, not safety.
Investigation needed
- What does
_setjmp actually take on macOS / Linux?
- On darwin,
jmp_buf is int[_JBLEN] — i.e. effectively *mut c_int.
- On glibc Linux, the layout is also
int[] though _JBLEN differs.
- What does each call site actually use the buffer for?
gc.rs uses it as a register-snapshot blob (u64[]).
promise.rs uses it for an unwind context (i32[]).
- Are either of them allocating the wrong-sized buffer?
Proposed fix shape
Introduce a single extern "C" block (e.g. runtime::ffi::setjmp or as a small shared module) with the correct libc-matching signature. Have both gc.rs and promise.rs import that one declaration. Remove the duplicated #[link_name] declarations.
If the two sites genuinely need to view the same buffer through different lenses, cast the pointer at the call site rather than redeclaring the extern.
Context
Spotted by the warning-cleanup PR (chore: reduce compile warnings 325 → 125). Kept out of that PR because it requires investigation of libc layouts and the runtime's stack-unwinding contract.
cargo build --releaseflags a clashing extern declaration for_setjmp:Why this matters
Both sites link to the same C symbol (
_setjmp) with different parameter types (*mut u64vs*mut i32). If they happen to be called with buffers sized for one but the runtime layout matches the other, this is undefined behavior — buffer corruption is silent and platform-dependent. The fact that it currently appears to work is luck of the macOS / aarch64 ABI, not safety.Investigation needed
_setjmpactually take on macOS / Linux?jmp_bufisint[_JBLEN]— i.e. effectively*mut c_int.int[]though_JBLENdiffers.gc.rsuses it as a register-snapshot blob (u64[]).promise.rsuses it for an unwind context (i32[]).Proposed fix shape
Introduce a single
extern "C"block (e.g.runtime::ffi::setjmpor as a small shared module) with the correct libc-matching signature. Have bothgc.rsandpromise.rsimport that one declaration. Remove the duplicated#[link_name]declarations.If the two sites genuinely need to view the same buffer through different lenses, cast the pointer at the call site rather than redeclaring the extern.
Context
Spotted by the warning-cleanup PR (
chore: reduce compile warnings 325 → 125). Kept out of that PR because it requires investigation of libc layouts and the runtime's stack-unwinding contract.