diff options
| author | Veikka Tuominen <git@vexu.eu> | 2022-10-05 15:06:14 +0300 |
|---|---|---|
| committer | Veikka Tuominen <git@vexu.eu> | 2022-10-06 20:09:45 +0300 |
| commit | 94039d66ed4fecb7defc5deeeedd7afa3b773f0c (patch) | |
| tree | 59e0c2a2033972bdf2ba22a76db7b1236a82dcc5 | |
| parent | cc89908e826882065eeaa23bb8827fb7d7cd6219 (diff) | |
| download | zig-94039d66ed4fecb7defc5deeeedd7afa3b773f0c.tar.gz zig-94039d66ed4fecb7defc5deeeedd7afa3b773f0c.zip | |
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.
| -rw-r--r-- | src/Sema.zig | 8 | ||||
| -rw-r--r-- | src/type.zig | 22 | ||||
| -rw-r--r-- | test/cases/compile_errors/fieldParentPtr_on_comptime_field.zig | 16 |
3 files changed, 46 insertions, 0 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index 7b9f7da769..f2b3cee3e3 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -18749,6 +18749,10 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6 break :blk try sema.tupleFieldIndex(block, ty, field_name, rhs_src); } else try sema.structFieldIndex(block, ty, field_name, rhs_src); + if (ty.structFieldIsComptime(field_index)) { + return sema.fail(block, src, "no offset available for comptime field", .{}); + } + switch (ty.containerLayout()) { .Packed => { var bit_sum: u64 = 0; @@ -20132,6 +20136,10 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr break :blk try sema.tupleFieldIndex(block, struct_ty, field_name, name_src); } else try sema.structFieldIndex(block, struct_ty, field_name, name_src); + if (struct_ty.structFieldIsComptime(field_index)) { + return sema.fail(block, src, "cannot get @fieldParentPtr of a comptime field", .{}); + } + try sema.checkPtrOperand(block, ptr_src, field_ptr_ty); const field_ptr_ty_info = field_ptr_ty.ptrInfo().data; diff --git a/src/type.zig b/src/type.zig index 1fef525062..7c35eccbe6 100644 --- a/src/type.zig +++ b/src/type.zig @@ -5664,6 +5664,28 @@ pub const Type = extern union { } } + pub fn structFieldIsComptime(ty: Type, index: usize) bool { + switch (ty.tag()) { + .@"struct" => { + const struct_obj = ty.castTag(.@"struct").?.data; + if (struct_obj.layout == .Packed) return false; + const field = struct_obj.fields.values()[index]; + return field.is_comptime; + }, + .tuple => { + const tuple = ty.castTag(.tuple).?.data; + const val = tuple.values[index]; + return val.tag() != .unreachable_value; + }, + .anon_struct => { + const anon_struct = ty.castTag(.anon_struct).?.data; + const val = anon_struct.values[index]; + return val.tag() != .unreachable_value; + }, + else => unreachable, + } + } + pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, target: Target) u32 { const struct_obj = ty.castTag(.@"struct").?.data; assert(struct_obj.layout == .Packed); diff --git a/test/cases/compile_errors/fieldParentPtr_on_comptime_field.zig b/test/cases/compile_errors/fieldParentPtr_on_comptime_field.zig new file mode 100644 index 0000000000..fb95ea691c --- /dev/null +++ b/test/cases/compile_errors/fieldParentPtr_on_comptime_field.zig @@ -0,0 +1,16 @@ +const T = struct { + comptime a: u32 = 2, +}; +pub export fn entry1() void { + @offsetOf(T, "a"); +} +pub export fn entry2() void { + @fieldParentPtr(T, "a", undefined); +} + +// error +// backend=stage2 +// target=native +// +// :5:5: error: no offset available for comptime field +// :8:5: error: cannot get @fieldParentPtr of a comptime field |
