commit 2c6e5006ed3adb02f3bc7b364b2bbc688271d9f7 (tree)
parent 998b714708bd7f750a3a076e5afd47c80786e72c
Author: David <enfipy@gmail.com>
Date: Tue, 7 Apr 2026 00:47:21 +0500
Sema: fix comptime @ptrCast to optional slices
Diffstat:
2 files changed, 24 insertions(+), 3 deletions(-)
diff --git 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
@@ -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;