authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-10-05 15:06:14+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-10-06 20:09:45+03:00
log94039d66ed4fecb7defc5deeeedd7afa3b773f0c
tree59e0c2a2033972bdf2ba22a76db7b1236a82dcc5
parentcc89908e826882065eeaa23bb8827fb7d7cd6219

Sema: disallow fieldParentPtr and offsetOf on comptime fields

Comptime fields are tied to the type and behave more like declarations so these operations cannot return anything useful for them.

3 files changed, 46 insertions(+), 0 deletions(-)

src/Sema.zig+8
...@@ -18749,6 +18749,10 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6...@@ -18749,6 +18749,10 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
18749 break :blk try sema.tupleFieldIndex(block, ty, field_name, rhs_src);18749 break :blk try sema.tupleFieldIndex(block, ty, field_name, rhs_src);
18750 } else try sema.structFieldIndex(block, ty, field_name, rhs_src);18750 } else try sema.structFieldIndex(block, ty, field_name, rhs_src);
1875118751
18752 if (ty.structFieldIsComptime(field_index)) {
18753 return sema.fail(block, src, "no offset available for comptime field", .{});
18754 }
18755
18752 switch (ty.containerLayout()) {18756 switch (ty.containerLayout()) {
18753 .Packed => {18757 .Packed => {
18754 var bit_sum: u64 = 0;18758 var bit_sum: u64 = 0;
...@@ -20132,6 +20136,10 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -20132,6 +20136,10 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
20132 break :blk try sema.tupleFieldIndex(block, struct_ty, field_name, name_src);20136 break :blk try sema.tupleFieldIndex(block, struct_ty, field_name, name_src);
20133 } else try sema.structFieldIndex(block, struct_ty, field_name, name_src);20137 } else try sema.structFieldIndex(block, struct_ty, field_name, name_src);
2013420138
20139 if (struct_ty.structFieldIsComptime(field_index)) {
20140 return sema.fail(block, src, "cannot get @fieldParentPtr of a comptime field", .{});
20141 }
20142
20135 try sema.checkPtrOperand(block, ptr_src, field_ptr_ty);20143 try sema.checkPtrOperand(block, ptr_src, field_ptr_ty);
20136 const field_ptr_ty_info = field_ptr_ty.ptrInfo().data;20144 const field_ptr_ty_info = field_ptr_ty.ptrInfo().data;
2013720145
src/type.zig+22
...@@ -5664,6 +5664,28 @@ pub const Type = extern union {...@@ -5664,6 +5664,28 @@ pub const Type = extern union {
5664 }5664 }
5665 }5665 }
56665666
5667 pub fn structFieldIsComptime(ty: Type, index: usize) bool {
5668 switch (ty.tag()) {
5669 .@"struct" => {
5670 const struct_obj = ty.castTag(.@"struct").?.data;
5671 if (struct_obj.layout == .Packed) return false;
5672 const field = struct_obj.fields.values()[index];
5673 return field.is_comptime;
5674 },
5675 .tuple => {
5676 const tuple = ty.castTag(.tuple).?.data;
5677 const val = tuple.values[index];
5678 return val.tag() != .unreachable_value;
5679 },
5680 .anon_struct => {
5681 const anon_struct = ty.castTag(.anon_struct).?.data;
5682 const val = anon_struct.values[index];
5683 return val.tag() != .unreachable_value;
5684 },
5685 else => unreachable,
5686 }
5687 }
5688
5667 pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, target: Target) u32 {5689 pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, target: Target) u32 {
5668 const struct_obj = ty.castTag(.@"struct").?.data;5690 const struct_obj = ty.castTag(.@"struct").?.data;
5669 assert(struct_obj.layout == .Packed);5691 assert(struct_obj.layout == .Packed);
test/cases/compile_errors/fieldParentPtr_on_comptime_field.zig created+16
...@@ -0,0 +1,16 @@
1const T = struct {
2 comptime a: u32 = 2,
3};
4pub export fn entry1() void {
5 @offsetOf(T, "a");
6}
7pub export fn entry2() void {
8 @fieldParentPtr(T, "a", undefined);
9}
10
11// error
12// backend=stage2
13// target=native
14//
15// :5:5: error: no offset available for comptime field
16// :8:5: error: cannot get @fieldParentPtr of a comptime field