From 2c6e5006ed3adb02f3bc7b364b2bbc688271d9f7 Mon Sep 17 00:00:00 2001 From: David Date: Tue, 7 Apr 2026 00:47:21 +0500 Subject: [PATCH] Sema: fix comptime @ptrCast to optional slices --- src/Sema.zig | 13 ++++++++++--- test/behavior/cast.zig | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 29d65047c68812b825d8c37952a700884714e0aa..0fafcc99b1c520b97d2677ba259f15240c7abf0b 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -21689,10 +21689,17 @@ fn ptrCastFull( .equal_runtime_src_slice => unreachable, .change_runtime_src_slice => unreachable, }; - return Air.internedToRef(try pt.intern(.{ .slice = .{ - .ty = dest_ty.toIntern(), - .ptr = (try pt.getCoerced(ptr_val, dest_ty.slicePtrFieldType(zcu))).toIntern(), + const dest_is_optional = dest_ty.zigTypeTag(zcu) == .optional; + const slice_ty = if (dest_is_optional) dest_ty.optionalChild(zcu) else dest_ty; + const slice_val = try pt.intern(.{ .slice = .{ + .ty = slice_ty.toIntern(), + .ptr = (try pt.getCoerced(ptr_val, slice_ty.slicePtrFieldType(zcu))).toIntern(), .len = len.toIntern(), + } }); + if (!dest_is_optional) return Air.internedToRef(slice_val); + return Air.internedToRef(try pt.intern(.{ .opt = .{ + .ty = dest_ty.toIntern(), + .val = slice_val, } })); } else { // Any to non-slice diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index d3f6ea5f48e09231888dbf285642cdb545b741fb..bb99b36863867f283da9478db9ee027aa2d8a5df 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -1544,6 +1544,20 @@ test "*const [N]null u8 to ?[]const u8" { try comptime S.doTheTest(); } +test "comptime @ptrCast to optional slice" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; + + const result: ?[]const u8 = comptime blk: { + const slice: []const u8 = "123"; + break :blk @ptrCast(slice); + }; + + comptime assert(mem.eql(u8, result.?, "123")); + try expectEqualSlices(u8, "123", result.?); +} + test "cast between [*c]T and ?[*:0]T on fn parameter" { const S = struct { const Handler = ?fn ([*c]const u8) callconv(.c) void; -- 2.54.0