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

@@ -228,7 +228,7 @@ pub fn lowerJniCall(self: *Lowering, fic: *const ast.FfiIntrinsicCall) Ref {
} }, ret_ty);
}
/// Lower an `inst.method(args)` call where `inst`'s type is a foreign-class
/// Lower an `inst.method(args)` call where `inst`'s type is a runtime-class
/// alias declared by `#jni_class("...") { ... }` (or its parallel forms).
/// JNI runtimes lower directly to `jni_msg_send` with a descriptor derived
/// from the method's sx signature; Obj-C / Swift runtimes are deferred to
@@ -252,7 +252,7 @@ pub fn lowerRuntimeMethodCall(
// child receiver, not the parent.
const found = self.findRuntimeMethodInChain(fcd, method_name) orelse {
if (self.diagnostics) |d| {
d.addFmt(.err, span, "no method '{s}' on foreign class '{s}' (or any `#extends` ancestor)", .{ method_name, fcd.name });
d.addFmt(.err, span, "no method '{s}' on runtime class '{s}' (or any `#extends` ancestor)", .{ method_name, fcd.name });
}
return Ref.none;
};
@@ -263,7 +263,7 @@ pub fn lowerRuntimeMethodCall(
// receiver derives a selector from the sx method name (default
// mangling: split on `_`, each piece becomes a keyword with a
// trailing `:`; niladic stays verbatim) and lowers to
// `objc_msg_send`. Both foreign and sx-defined classes flow
// `objc_msg_send`. Both runtime and sx-defined classes flow
// through the same path — sx-defined classes have their IMPs
// registered at module-init (M1.2 A.4b.iii) so `objc_msgSend`
// finds them. The Swift runtimes still bail — Phase 4.
@@ -292,7 +292,7 @@ pub fn lowerRuntimeMethodCall(
const env_ref = self.jni_env_stack.items[self.jni_env_stack.items.len - 1];
// Build a ClassRegistry snapshot so descriptor derivation can
// resolve `*Foo` cross-class refs to their foreign paths.
// resolve `*Foo` cross-class refs to their runtime paths.
var registry = jni_descriptor.ClassRegistry.init(self.alloc);
defer registry.deinit();
var it = self.program_index.runtime_class_map.iterator();
@@ -353,8 +353,8 @@ pub fn lowerRuntimeMethodCall(
// `self.objc()`. Emission-heavy IMP builders live in lower/objc_class.zig;
// the `lowerObjc*Call` lowering paths are below.
/// Resolve a foreign-class member type, substituting `Self` (and `*Self`)
/// with the foreign class's own struct type. Without this substitution
/// Resolve a runtime-class member type, substituting `Self` (and `*Self`)
/// with the runtime class's own struct type. Without this substitution
/// chained calls like `Cls.alloc().init()` see the inner result as a
/// fictitious `Self` struct and the next dispatch lookup fails.
pub fn resolveRuntimeClassMemberType(
@@ -559,7 +559,7 @@ pub fn lowerObjcStaticCall(
} }, ret_ty);
}
/// Lower `Alias.new(args)` where `Alias` is a foreign-class identifier
/// Lower `Alias.new(args)` where `Alias` is a runtime-class identifier
/// with `static new :: (...) -> *Self;` — JNI constructor dispatch:
/// `FindClass + GetMethodID("<init>", "(args)V") + NewObject(env,
/// clazz, mid, args...)`. Returns the new jobject.
@@ -587,7 +587,7 @@ pub fn lowerRuntimeStaticCall(
return Ref.none;
}
if (!std.mem.eql(u8, method.name, "new")) {
if (self.diagnostics) |d| d.addFmt(.err, span, "static foreign-class call '{s}.{s}' not yet supported via `Alias.method()` syntax \u{2014} only `new` is wired today; use `#jni_static_call` directly for other static methods", .{ fcd.name, method.name });
if (self.diagnostics) |d| d.addFmt(.err, span, "static runtime-class call '{s}.{s}' not yet supported via `Alias.method()` syntax \u{2014} only `new` is wired today; use `#jni_static_call` directly for other static methods", .{ fcd.name, method.name });
return Ref.none;
}
@@ -628,7 +628,7 @@ pub fn lowerRuntimeStaticCall(
};
// sx-side return type is `*Self` — resolve to a pointer to the
// foreign-class struct type so method dispatch on the new
// runtime-class struct type so method dispatch on the new
// jobject works (`view := SurfaceView.new(ctx); view.getHolder()`).
// At LLVM level still ptr; the sx type table is what method
// resolution consults.
@@ -671,7 +671,7 @@ pub fn lowerRuntimeStaticCall(
/// method's name (the common case — `super.onCreate(b)` from inside
/// `onCreate :: (self, b)` override), the enclosing method's
/// signature is reused. Other method names require the parent class
/// to be declared via `#foreign #jni_class` so the signature can be
/// to be declared via `#jni_class(…) extern` so the signature can be
/// looked up.
pub fn lowerSuperCall(
self: *Lowering,
@@ -701,7 +701,7 @@ pub fn lowerSuperCall(
// Resolve method signature. Same-name fast path reuses the
// enclosing method's descriptor; cross-method super calls require
// the parent class to be declared via `#foreign #jni_class`.
// the parent class to be declared via `#jni_class(…) extern`.
var descriptor: []const u8 = "";
var resolved_method: ?ast.RuntimeMethodDecl = null;
if (self.current_runtime_method) |em| {
@@ -725,7 +725,7 @@ pub fn lowerSuperCall(
}
}
const method = resolved_method orelse {
if (self.diagnostics) |d| d.addFmt(.err, span, "no method '{s}' found for `super.{s}(...)` — declare the parent class via `#foreign #jni_class` to make cross-method super calls available", .{ method_name, method_name });
if (self.diagnostics) |d| d.addFmt(.err, span, "no method '{s}' found for `super.{s}(...)` — declare the parent class via `#jni_class(…) extern` to make cross-method super calls available", .{ method_name, method_name });
return Ref.none;
};
@@ -780,13 +780,13 @@ pub fn lowerSuperCall(
// ── Foreign-class registration ──────────────────────────────────
/// Register a foreign-class declaration. The alias goes into
/// Register a runtime-class declaration. The alias goes into
/// `runtime_class_map` for method-dispatch lookup. The underlying
/// type (e.g. `*Activity`) is resolved via the existing struct
/// fallback in `type_bridge.resolveTypeName` (which interns unknown
/// named types as 0-field structs).
///
/// sx-defined Obj-C classes (no `#foreign`, runtime == .objc_class)
/// sx-defined Obj-C classes (no `extern`, runtime == .objc_class)
/// also land in `module.objc_defined_class_cache` in declaration
/// order AND have their bodied methods registered into `fn_ast_map`
/// under qualified names `<ClassName>.<methodName>`. Lazy lowering
@@ -821,7 +821,7 @@ pub fn registerRuntimeClassDecl(self: *Lowering, fcd: *const ast.RuntimeClassDec
/// Resolve the `#extends ParentAlias` declaration on a sx-defined
/// `#objc_class` to the actual Obj-C runtime class name. Falls
/// back to "NSObject" when no `#extends` is declared.
/// Aliases that resolve to foreign Obj-C classes use the
/// Aliases that resolve to runtime Obj-C classes use the
/// runtime_path; aliases for OTHER sx-defined classes use the
/// alias name directly (which equals the Obj-C class name for
/// sx-defined classes).
@@ -1007,7 +1007,7 @@ pub fn getJniEnvTlFids(self: *Lowering) struct { get: FuncId, set: FuncId } {
return .{ .get = self.jni_env_tl_get_fid.?, .set = self.jni_env_tl_set_fid.? };
}
/// When a namespaced import (`Ns :: #import "..."`) contains foreign-class
/// When a namespaced import (`Ns :: #import "..."`) contains runtime-class
/// declarations, ALSO register them under their qualified name `Ns.Class`
/// so receiver types like `*Ns.Class` can find the fcd. The recursive
/// scan/lower already handles bare-name registration; this only adds the
@@ -1169,7 +1169,7 @@ pub fn synthesizeJniMainStub(self: *Lowering, fcd: *const ast.RuntimeClassDecl,
}
/// JNI param/return type resolution: user-declared types pass through
/// `resolveType` so the method body can dispatch on richer foreign-class
/// `resolveType` so the method body can dispatch on richer runtime-class
/// types (`holder.getSurface()` etc.). At LLVM level both `*SurfaceHolder`
/// and `*void` lower to the same `ptr`, so the C ABI shape Java sees is
/// unchanged — only sx-side method resolution benefits.