From f75923af00c0b0f06c387c3d9477aa550df887e8 Mon Sep 17 00:00:00 2001 From: agra Date: Tue, 26 May 2026 07:51:12 +0300 Subject: [PATCH] uikit: type UIKitPlatform fields properly + handle optional in Obj-C encoding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The UIKitPlatform struct had a string of '*void = null; // UIWindow*' fields — the type lived in a comment, every callsite had to 'xx'-cast back to the real type. Migrated to the real foreign-class pointer types now that M3 declared all the relevant '#objc_class' aliases: window: ?*UIWindow root_vc: ?*UIViewController gl_view: ?*UIView (SxGLView OR SxMetalView — both extend UIView) gl_layer: ?*CALayer (CAEAGLLayer OR CAMetalLayer) gl_ctx: ?*EAGLContext display_link: ?*CADisplayLink Each field is wrapped in '?' since the platform may not have set it yet (gl_ctx is null in metal mode, display_link is null before the first frame, etc.). SxSceneDelegate's window getter/setter now take/return '?*UIWindow' instead of '*void' so calling code doesn't need an xx-cast. Required fix in objcTypeEncodingFromSignature: '?T' (optional) was bailing with 'type kind not yet supported'. Apple's runtime treats nullability as 'pointer may be null' — the wire encoding is the same as T. Recursive unwrap handles ?*UIView → '@', ?*CADisplayLink → '@', etc. Chess on iOS-sim: board renders, full pipeline intact. 183 tests + zig build test green. --- library/modules/platform/uikit.sx | 21 ++++++++++++--------- src/ir/lower.zig | 8 ++++++++ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/library/modules/platform/uikit.sx b/library/modules/platform/uikit.sx index 22180b7..c712a1f 100644 --- a/library/modules/platform/uikit.sx +++ b/library/modules/platform/uikit.sx @@ -217,12 +217,12 @@ SxSceneDelegate :: #objc_class("SxSceneDelegate") { uikit_scene_will_connect(xx self, xx 0, scene, session, options); } - window :: (self: *Self) -> *void { - if g_uikit_plat == null { return xx 0; } + window :: (self: *Self) -> ?*UIWindow { + if g_uikit_plat == null { return null; } return g_uikit_plat.window; } - setWindow :: (self: *Self, w: *void) { + setWindow :: (self: *Self, w: ?*UIWindow) { if g_uikit_plat == null { return; } g_uikit_plat.window = w; } @@ -247,12 +247,15 @@ GpuMode :: enum { } UIKitPlatform :: struct { - window: *void = null; // UIWindow* - root_vc: *void = null; // UIViewController* - gl_view: *void = null; // SxGLView* OR SxMetalView* (depending on gpu_mode) - gl_layer: *void = null; // CAEAGLLayer* OR CAMetalLayer* (= gl_view.layer) - gl_ctx: *void = null; // EAGLContext* (null in metal mode) - display_link: *void = null; + window: ?*UIWindow = null; + root_vc: ?*UIViewController = null; + // SxGLView (gles mode) or SxMetalView (metal mode) — both extend + // UIView, so the common method surface is reachable as *UIView. + gl_view: ?*UIView = null; + // CAEAGLLayer (gles) or CAMetalLayer (metal) — both extend CALayer. + gl_layer: ?*CALayer = null; + gl_ctx: ?*EAGLContext = null; + display_link: ?*CADisplayLink = null; color_renderbuffer: u32 = 0; framebuffer: u32 = 0; gl_initialized: bool = false; diff --git a/src/ir/lower.zig b/src/ir/lower.zig index 7ce9072..d0a2a22 100644 --- a/src/ir/lower.zig +++ b/src/ir/lower.zig @@ -4713,6 +4713,14 @@ pub const Lowering = struct { try out.appendSlice(self.alloc, "^v"); } }, + .optional => |o| { + // sx's `?T` is a nullable T. At the Obj-C ABI boundary + // nullability is just "this pointer may be null" — the + // wire-level encoding is the same as T. Unwrap and + // recurse. (Same goes for `?*UIView` etc. — the + // underlying pointer kind drives the encoding char.) + return self.appendObjcEncoding(out, o.child, span); + }, else => return self.bailObjcEncoding(span, "type kind not yet supported by Obj-C encoding", @intFromEnum(std.meta.activeTag(info))), } }