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.
|
// this predicate is single-hop only.
|
||||||
.impl_transitive => @panic("isVisible: transitive visibility is owned by findVisibleImpls"),
|
.impl_transitive => @panic("isVisible: transitive visibility is owned by findVisibleImpls"),
|
||||||
.c_import_bare => {
|
.c_import_bare => {
|
||||||
// Foreign-C gate: only C-import fn_decls without a library_ref
|
// Foreign-C gate: only a lib-less C-import fn_decl is policed; a
|
||||||
// are policed; a non-foreign body or a library-bound foreign
|
// library-bound decl (resolves via the named library, not a
|
||||||
// decl is unconditionally visible.
|
// 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;
|
const fd = self.program_index.fn_ast_map.get(name) orelse return true;
|
||||||
if (fd.body.data != .foreign_expr) return true;
|
switch (fd.body.data) {
|
||||||
if (fd.body.data.foreign_expr.library_ref != null) return true;
|
.foreign_expr => |fe| {
|
||||||
return self.visibleOverEdges(name);
|
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),
|
.user_bare_flat => return self.visibleOverEdges(name),
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user