authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-03-16 03:13:19+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-04-28 01:14:22+01:00
logd4c539664661a93fe193a9559688e7c6c3955e0d
tree1743dcd498afcb2f5d95cf90df601b99b8e32892
parent5ed8bd5c85e34d200a504418ebd2fc3d902460ac
signaturelock-open Commit is signed but in an unrecognized format.

Sema: fix pointers to comptime fields of comptime-known aggregate pointers

Resolves: #23190

2 files changed, 31 insertions(+), 5 deletions(-)

src/Sema.zig+12-5
...@@ -28013,12 +28013,17 @@ fn structFieldPtrByIndex(...@@ -28013,12 +28013,17 @@ fn structFieldPtrByIndex(
28013 const zcu = pt.zcu;28013 const zcu = pt.zcu;
28014 const ip = &zcu.intern_pool;28014 const ip = &zcu.intern_pool;
2801528015
28016 if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| {28016 const struct_type = zcu.typeToStruct(struct_ty).?;
28017 const val = try struct_ptr_val.ptrField(field_index, pt);28017 const field_is_comptime = struct_type.fieldIsComptime(ip, field_index);
28018 return Air.internedToRef(val.toIntern());28018
28019 // Comptime fields are handled later
28020 if (!field_is_comptime) {
28021 if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| {
28022 const val = try struct_ptr_val.ptrField(field_index, pt);
28023 return Air.internedToRef(val.toIntern());
28024 }
28019 }28025 }
2802028026
28021 const struct_type = zcu.typeToStruct(struct_ty).?;
28022 const field_ty = struct_type.field_types.get(ip)[field_index];28027 const field_ty = struct_type.field_types.get(ip)[field_index];
28023 const struct_ptr_ty = sema.typeOf(struct_ptr);28028 const struct_ptr_ty = sema.typeOf(struct_ptr);
28024 const struct_ptr_ty_info = struct_ptr_ty.ptrInfo(zcu);28029 const struct_ptr_ty_info = struct_ptr_ty.ptrInfo(zcu);
...@@ -28038,6 +28043,7 @@ fn structFieldPtrByIndex(...@@ -28038,6 +28043,7 @@ fn structFieldPtrByIndex(
28038 try Type.fromInterned(struct_ptr_ty_info.child).abiAlignmentSema(pt);28043 try Type.fromInterned(struct_ptr_ty_info.child).abiAlignmentSema(pt);
2803928044
28040 if (struct_type.layout == .@"packed") {28045 if (struct_type.layout == .@"packed") {
28046 assert(!field_is_comptime);
28041 switch (struct_ty.packedStructFieldPtrInfo(struct_ptr_ty, field_index, pt)) {28047 switch (struct_ty.packedStructFieldPtrInfo(struct_ptr_ty, field_index, pt)) {
28042 .bit_ptr => |packed_offset| {28048 .bit_ptr => |packed_offset| {
28043 ptr_ty_data.flags.alignment = parent_align;28049 ptr_ty_data.flags.alignment = parent_align;
...@@ -28048,6 +28054,7 @@ fn structFieldPtrByIndex(...@@ -28048,6 +28054,7 @@ fn structFieldPtrByIndex(
28048 },28054 },
28049 }28055 }
28050 } else if (struct_type.layout == .@"extern") {28056 } else if (struct_type.layout == .@"extern") {
28057 assert(!field_is_comptime);
28051 // For extern structs, field alignment might be bigger than type's28058 // For extern structs, field alignment might be bigger than type's
28052 // natural alignment. Eg, in `extern struct { x: u32, y: u16 }` the28059 // natural alignment. Eg, in `extern struct { x: u32, y: u16 }` the
28053 // second field is aligned as u32.28060 // second field is aligned as u32.
...@@ -28071,7 +28078,7 @@ fn structFieldPtrByIndex(...@@ -28071,7 +28078,7 @@ fn structFieldPtrByIndex(
2807128078
28072 const ptr_field_ty = try pt.ptrTypeSema(ptr_ty_data);28079 const ptr_field_ty = try pt.ptrTypeSema(ptr_ty_data);
2807328080
28074 if (struct_type.fieldIsComptime(ip, field_index)) {28081 if (field_is_comptime) {
28075 try struct_ty.resolveStructFieldInits(pt);28082 try struct_ty.resolveStructFieldInits(pt);
28076 const val = try pt.intern(.{ .ptr = .{28083 const val = try pt.intern(.{ .ptr = .{
28077 .ty = ptr_field_ty.toIntern(),28084 .ty = ptr_field_ty.toIntern(),
test/cases/compile_errors/runtime_store_to_comptime_field.zig created+19
...@@ -0,0 +1,19 @@
1const init: u32 = 1;
2fn rt() u32 {
3 return 3;
4}
5
6var tuple_val = .{init};
7export fn tuple_field() void {
8 tuple_val[0] = rt();
9}
10
11var struct_val = .{ .x = init };
12export fn struct_field() void {
13 struct_val.x = rt();
14}
15
16// error
17//
18// :8:14: error: cannot store runtime value in compile time variable
19// :13:15: error: cannot store runtime value in compile time variable