Commit 94039d66ed

Veikka Tuominen <git@vexu.eu>
2022-10-05 14:06:14
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.
1 parent cc89908
Changed files (3)
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;
 
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);
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