fix(ffi-linkage): Phase 5.0 prereq — police lib-less extern like #foreign in c_import_bare gate
The non-transitive C-import visibility gate (`isVisible(.c_import_bare)`) only recognised the legacy `#foreign` body shape; a bare `extern` fn (empty-block body + extern_export == .extern_) escaped via the `body != foreign_expr -> return true` arm and was caught only by the general isNameVisible gate, yielding the generic 'not visible' wording instead of the C-specific 'C function not visible; add #import' one. Now both lib-less spellings route to visibleOverEdges, and a library- bound `extern LIB` (like a library-bound `#foreign LIB`) stays unconditionally visible. This makes a future fn-decl `#foreign`->`extern` migration byte-identical at this gate. Greens example 1228. 644 corpus / 444 unit, 0 failed.
This commit is contained in:
@@ -2247,13 +2247,28 @@ pub fn isVisible(self: *Lowering, name: []const u8, vis: resolver_mod.Visibility
|
||||
// this predicate is single-hop only.
|
||||
.impl_transitive => @panic("isVisible: transitive visibility is owned by findVisibleImpls"),
|
||||
.c_import_bare => {
|
||||
// Foreign-C gate: only C-import fn_decls without a library_ref
|
||||
// are policed; a non-foreign body or a library-bound foreign
|
||||
// decl is unconditionally visible.
|
||||
// Foreign-C gate: only a lib-less C-import fn_decl is policed; a
|
||||
// library-bound decl (resolves via the named library, not a
|
||||
// module edge) or a non-C body is unconditionally visible. The
|
||||
// legacy `#foreign` form (a `foreign_expr` body) and the new
|
||||
// `extern` keyword (`extern_export == .extern_`, empty-block body)
|
||||
// are two spellings of the same lib-less C-symbol import, so BOTH
|
||||
// route to `visibleOverEdges` here — a migrated `extern` decl must
|
||||
// get the identical "C function not visible" diagnostic its
|
||||
// `#foreign` twin did, not the generic top-level-name wording
|
||||
// (FFI-linkage Part B; example 1228).
|
||||
const fd = self.program_index.fn_ast_map.get(name) orelse return true;
|
||||
if (fd.body.data != .foreign_expr) return true;
|
||||
if (fd.body.data.foreign_expr.library_ref != null) return true;
|
||||
return self.visibleOverEdges(name);
|
||||
switch (fd.body.data) {
|
||||
.foreign_expr => |fe| {
|
||||
if (fe.library_ref != null) return true;
|
||||
return self.visibleOverEdges(name);
|
||||
},
|
||||
else => {
|
||||
if (fd.extern_export != .extern_) return true;
|
||||
if (fd.extern_lib != null) return true;
|
||||
return self.visibleOverEdges(name);
|
||||
},
|
||||
}
|
||||
},
|
||||
.user_bare_flat => return self.visibleOverEdges(name),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user