mem: document the xx-sx-fn-to-*void hole in the call-conv check

Audit of library + game found every C-side callback already follows
the callconv(.c) rule. The static check at the bare-fn-ref site catches
typed fn-pointer mismatches; the one remaining hole is `xx <sx_fn> : *void`
(used by e.g. `class_addMethod(_, _, xx my_imp, _)`). Tried to close
it by requiring callconv(.c) on any sx fn cast to *void, but
examples/50-smoke.sx legitimately stores a default-conv sx fn into a
*void slot when manually constructing a Closure value — that path
goes through the sx-side closure trampoline ABI, not C. The compiler
can't distinguish C-side vs sx-side from the cast alone.

Leaving the hole open and documenting why. The existing libraries
follow the convention manually; the typed-fn-ptr check covers
pthread_create / SDL callbacks / GL loader-style sites which is where
the real-world bugs landed.
This commit is contained in:
agra
2026-05-25 10:11:07 +03:00
parent f886d5f1be
commit 619aff85f6

View File

@@ -1992,6 +1992,16 @@ pub const Lowering = struct {
break :blk self.emitPlaceholder(eff_fn_name);
}
}
// NOTE: `xx <sx_fn> : *void` (e.g.
// `class_addMethod(_, _, xx my_imp, _)`)
// is intentionally NOT diagnosed here.
// Manually-constructed Closure values
// legitimately store default-conv sx fns
// into a `*void` slot for sx-side dispatch
// through the closure trampoline ABI. The
// compiler can't distinguish C-side vs
// sx-side use from the cast alone.
// examples/50-smoke.sx has both shapes.
}
}
break :blk self.builder.emit(.{ .func_ref = fid }, .s64);