authorgravatar for 51252236+xdBronch@users.noreply.github.comxdBronch <51252236+xdBronch@users.noreply.github.com> 2025-10-13 17:25:00-04:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-10-16 19:36:11+01:00
logf785e4745d85f7056ab670989c5739b62b0df265
treee1f50a9768f3856e0175ca2e234da9aff0f1ed91
parent173f497e29daf377a6b843e6ed8cdddc12ceb712

detect invalid `@bitCast` with arrays


3 files changed, 56 insertions(+), 5 deletions(-)

src/Sema.zig+24-2
...@@ -9952,8 +9952,19 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -9952,8 +9952,19 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
9952 dest_ty.fmt(pt), container,9952 dest_ty.fmt(pt), container,
9953 });9953 });
9954 },9954 },
9955 .array => {
9956 const elem_ty = dest_ty.childType(zcu);
9957 if (!elem_ty.hasWellDefinedLayout(zcu)) {
9958 const msg = msg: {
9959 const msg = try sema.errMsg(src, "cannot @bitCast to '{f}'", .{dest_ty.fmt(pt)});
9960 errdefer msg.destroy(sema.gpa);
9961 try sema.errNote(src, msg, "array element type '{f}' does not have a guaranteed in-memory layout", .{elem_ty.fmt(pt)});
9962 break :msg msg;
9963 };
9964 return sema.failWithOwnedErrorMsg(block, msg);
9965 }
9966 },
99559967
9956 .array,
9957 .bool,9968 .bool,
9958 .float,9969 .float,
9959 .int,9970 .int,
...@@ -10015,8 +10026,19 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -10015,8 +10026,19 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
10015 operand_ty.fmt(pt), container,10026 operand_ty.fmt(pt), container,
10016 });10027 });
10017 },10028 },
10029 .array => {
10030 const elem_ty = operand_ty.childType(zcu);
10031 if (!elem_ty.hasWellDefinedLayout(zcu)) {
10032 const msg = msg: {
10033 const msg = try sema.errMsg(src, "cannot @bitCast from '{f}'", .{operand_ty.fmt(pt)});
10034 errdefer msg.destroy(sema.gpa);
10035 try sema.errNote(src, msg, "array element type '{f}' does not have a guaranteed in-memory layout", .{elem_ty.fmt(pt)});
10036 break :msg msg;
10037 };
10038 return sema.failWithOwnedErrorMsg(block, msg);
10039 }
10040 },
1001810041
10019 .array,
10020 .bool,10042 .bool,
10021 .float,10043 .float,
10022 .int,10044 .int,
src/Type.zig+6-3
...@@ -1924,9 +1924,12 @@ pub fn isPtrLikeOptional(ty: Type, zcu: *const Zcu) bool {...@@ -1924,9 +1924,12 @@ pub fn isPtrLikeOptional(ty: Type, zcu: *const Zcu) bool {
1924 };1924 };
1925}1925}
19261926
1927/// For *[N]T, returns [N]T.1927/// For *[N]T, returns [N]T.
1928/// For *T, returns T.1928/// For *T, returns T.
1929/// For [*]T, returns T.1929/// For [*]T, returns T.
1930/// For @Vector(N, T), returns T.
1931/// For [N]T, returns T.
1932/// For ?T, returns T.
1930pub fn childType(ty: Type, zcu: *const Zcu) Type {1933pub fn childType(ty: Type, zcu: *const Zcu) Type {
1931 return childTypeIp(ty, &zcu.intern_pool);1934 return childTypeIp(ty, &zcu.intern_pool);
1932}1935}
test/cases/compile_errors/bitCast_with_invalid_array_element_type.zig created+26
...@@ -0,0 +1,26 @@
1export fn foo() void {
2 const S = struct {
3 f: u8,
4 };
5 _ = @as([@sizeOf(S)]u8, @bitCast([1]S{undefined}));
6}
7
8export fn bar() void {
9 const S = struct {
10 f: u8,
11 };
12 _ = @as([1]S, @bitCast(@as([@sizeOf(S)]u8, undefined)));
13}
14
15export fn baz() void {
16 _ = @as([1]u32, @bitCast([1]comptime_int{0}));
17}
18
19// error
20//
21// :5:29: error: cannot @bitCast from '[1]tmp.foo.S'
22// :5:29: note: array element type 'tmp.foo.S' does not have a guaranteed in-memory layout
23// :12:19: error: cannot @bitCast to '[1]tmp.bar.S'
24// :12:19: note: array element type 'tmp.bar.S' does not have a guaranteed in-memory layout
25// :16:21: error: cannot @bitCast from '[1]comptime_int'
26// :16:21: note: array element type 'comptime_int' does not have a guaranteed in-memory layout