fix(ffi-linkage): Phase 5.0 prereq — exclude extern imports from plain-free-fn classification
isPlainFreeFn / isPlainFreeFnDecl excluded a #foreign body but classified an empty-block extern fn as a plain free function, so existing extern fns were wrongly counted in the bare-call ambiguity verdict (and eligible for the out-of-line-slot / shadow-author pass). Both predicates now also exclude extern_export == .extern_ (an external C symbol with no sx-lowerable body, name-keyed first-wins dispatch like #foreign); export keeps a real body and stays plain-free. Greens example 1230 — same-name extern authors compile like their #foreign twins (0729). 646 corpus / 444 unit, 0 failed.
This commit is contained in:
@@ -808,12 +808,16 @@ pub fn hasComptimeParams(fd: *const ast.FnDecl) bool {
|
||||
}
|
||||
|
||||
/// A plain free function: no type params (not generic) and an ordinary sx
|
||||
/// body (not `#foreign` / `#builtin` / `#compiler`). Only these get an
|
||||
/// out-of-line identity-addressable slot — the bare-call disambiguation
|
||||
/// body (not `#foreign` / `#builtin` / `#compiler` / `extern`). Only these get
|
||||
/// an out-of-line identity-addressable slot — the bare-call disambiguation
|
||||
/// and the shadow-author lowering pass leave every other shape
|
||||
/// to the existing name-keyed dispatch.
|
||||
pub fn isPlainFreeFn(fd: *const ast.FnDecl) bool {
|
||||
if (fd.type_params.len > 0) return false;
|
||||
// An `extern` import is an external C symbol with no sx-lowerable body —
|
||||
// name-keyed first-wins dispatch like a `#foreign` body, never a plain free
|
||||
// fn. `export` DEFINES a real body, so it stays plain-free.
|
||||
if (fd.extern_export == .extern_) return false;
|
||||
return switch (fd.body.data) {
|
||||
.foreign_expr, .builtin_expr, .compiler_expr => false,
|
||||
else => true,
|
||||
|
||||
@@ -173,10 +173,16 @@ pub fn fnDeclOf(raw: RawDeclRef) ?*const ast.FnDecl {
|
||||
}
|
||||
|
||||
/// A PLAIN free function — no type params, an ordinary (non-`#foreign`/
|
||||
/// `#builtin`/`#compiler`) body — the only callable kind the bare-call verdict
|
||||
/// counts.
|
||||
/// `#builtin`/`#compiler`/`extern`) body — the only callable kind the bare-call
|
||||
/// verdict counts.
|
||||
pub fn isPlainFreeFnDecl(fd: *const ast.FnDecl) bool {
|
||||
if (fd.type_params.len > 0) return false;
|
||||
// An `extern` import is an external C symbol with no sx-lowerable body —
|
||||
// dispatched name-keyed first-wins, exactly like a `#foreign` body, so it
|
||||
// is NOT a plain free fn (excluded from the bare-call ambiguity verdict and
|
||||
// the out-of-line-slot / shadow-author pass). `export` DEFINES a real sx
|
||||
// body, so it stays plain-free.
|
||||
if (fd.extern_export == .extern_) return false;
|
||||
return switch (fd.body.data) {
|
||||
.foreign_expr, .builtin_expr, .compiler_expr => false,
|
||||
else => true,
|
||||
|
||||
Reference in New Issue
Block a user