refactor(ffi-linkage): Phase 9.3-src — purge 'foreign' from src/ comments + a user-facing diagnostic

Reword every 'foreign' comment to the extern/runtime-class vocabulary matching the
renamed identifiers (foreign call→extern call, foreign class→runtime class, foreign
path→runtime path, the #foreign-literal comment mentions → extern, etc.). Also fixes
two USER-FACING issues: the 'expected … #foreign … after type annotation' parse error
no longer advertises the removed keyword, and the Android 'no #jni_main' help
diagnostic now shows '#jni_class(…) extern' instead of the rejected '#foreign
#jni_class'. Removed the now-dead prefix-#foreign-vs-postfix conflict branch in
parseRuntimeClassDecl (the caller rejects #foreign before it runs).

src/ now contains 'foreign' ONLY in the hash_foreign token machinery + its 4
rejection messages — the deprecation mechanism (kept per the 9.0 recommendation; the
message MUST name #foreign to guide migration). Snapshot-neutral; suite green
(646 corpus / 444 unit, 0 failed).
This commit is contained in:
agra
2026-06-15 09:35:00 +03:00
parent e99383fcb4
commit dc51c4b5bf
35 changed files with 172 additions and 180 deletions

View File

@@ -33,7 +33,7 @@ const TypeResolver = type_resolver.TypeResolver;
/// imported / library modules are trusted, matching `checkErrorFlow`.
///
/// Queries the canonical facts rather than maintaining a parallel authoritative
/// list: declared top-level names come from `ProgramIndex` (foreign classes,
/// list: declared top-level names come from `ProgramIndex` (runtime classes,
/// generic templates, protocols, aliases) plus the AST decl/scope walk (for
/// LOCAL type decls, which `ProgramIndex` doesn't track); primitives come from
/// `TypeResolver.resolvePrimitive`; registered concrete types from the
@@ -138,7 +138,7 @@ pub const UnknownTypeChecker = struct {
// A function NAME is a binding site too: a bare reserved-name
// `i2 :: (…) {…}` (free fn or struct/impl method) is rejected,
// exactly like `i2 := …`. Backtick (`` `i2 :: … ``) and
// `#import c` foreign fns set `is_raw` and are exempt (0089).
// `#import c` extern fns set `is_raw` and are exempt (0089).
self.checkBindingName(fd.name, fd.name_span, fd.is_raw);
self.checkParamNames(fd.params);
self.checkBindingNames(fd.body);
@@ -194,7 +194,7 @@ pub const UnknownTypeChecker = struct {
if (os.binding) |b| self.checkBindingName(b, os.binding_span, os.binding_is_raw);
self.checkBindingNames(os.body);
},
// impl / protocol-default / foreign-class method bodies: each
// impl / protocol-default / runtime-class method bodies: each
// method introduces its own params + locals. A `#jni_main` /
// `#objc_class` bodied method is lowered (M1.2), so its reserved
// param/local names mis-lower the same as any other.
@@ -365,7 +365,7 @@ pub const UnknownTypeChecker = struct {
/// (a lambda default), so recurse into it.
fn checkParamNames(self: UnknownTypeChecker, params: []const ast.Param) void {
for (params) |p| {
// A backtick raw param (`` (`i2: T) ``) or a `#import c` foreign
// A backtick raw param (`` (`i2: T) ``) or a `#import c` extern
// param is exempt from the reserved-type-name rule —
// the exemption is honored inside `checkBindingName` via `p.is_raw`.
self.checkBindingName(p.name, p.name_span, p.is_raw);
@@ -375,7 +375,7 @@ pub const UnknownTypeChecker = struct {
/// Collect every top-level name that can legitimately appear in a type
/// position: const-decl names (covers `T :: struct/enum/union/error/alias`
/// and value consts), plus the scan-populated foreign-class / generic-
/// and value consts), plus the scan-populated runtime-class / generic-
/// template / protocol / alias maps from `ProgramIndex`. Built across ALL
/// files so a main-file reference to an imported type isn't flagged.
fn collectDeclaredTypeNames(self: UnknownTypeChecker, decls: []const *const Node, out: *std.StringHashMap(void)) void {
@@ -860,7 +860,7 @@ pub const UnknownTypeChecker = struct {
/// correct without any lowering special-case.
/// `is_raw` is a REQUIRED argument, not a call-site guard: the exemption
/// lives INSIDE the check so no caller can validate a name without also
/// honoring the backtick / `#import c` foreign exemption. This is what keeps
/// honoring the backtick / `#import c` extern exemption. This is what keeps
/// the check and the exemption from desyncing — the recurring failure of the
/// earlier attempts, where each site threaded an `if (!is_raw)` guard
/// separately and one was forgotten.
@@ -872,12 +872,12 @@ pub const UnknownTypeChecker = struct {
/// Reserved-name check for a `::` declaration whose own name binds an
/// identifier but carries no dedicated `name_span` field — struct / enum /
/// union / error-set / protocol / foreign-class type decls, ufcs aliases,
/// union / error-set / protocol / runtime-class type decls, ufcs aliases,
/// and namespaced imports. Each such node begins at its name
/// token (`createNode(name_start, …)`), so the name's length isolates the
/// caret onto the name — a single source for the span, no separate stored
/// field to drift from `node.span`. `is_raw` is REQUIRED, exactly as in
/// `checkBindingName`: a backtick raw / `#import c` foreign name is exempt
/// `checkBindingName`: a backtick raw / `#import c` extern name is exempt
/// by construction.
fn checkDeclName(self: UnknownTypeChecker, node: *const Node, name: []const u8, is_raw: bool) void {
const span = ast.Span{ .start = node.span.start, .end = node.span.start + @as(u32, @intCast(name.len)) };