Consider the code:
test {
const MyStruct = struct { x: u32 };
var my_struct: MyStruct align(8) = .{ .x = 5 };
const ptr: *align(8) u32 = &my_struct.x;
_ = ptr;
}
Currently, it fails, with this compiler error:
repro.zig:4:32: error: expected type '*align(8) u32', found '*u32'
const ptr: *align(8) u32 = &my_struct.x;
^~~~~~~~~~~~
repro.zig:4:32: note: pointer alignment '4' cannot cast into pointer alignment '8'
While, if x has an offset of zero relative to the entire struct (which would be the case most of the time), the compiler could actually guarantee that its alignment is equal to that of &my_struct, 8.
This can even happen without over-alignment with unions:
test {
const MyUnion = union { a: u32, b: u64 };
var my_union: MyUnion = .{ .a = 42 };
const ptr: *align(@alignOf(MyUnion)) u32 = &my_union.a;
_ = ptr;
}
Here, both fields could lie at the union’s base address, which is aligned to accommodate a u64, and thus the compiler could guarantee a pointer to an a field has that alignment as well.
Therefore, I propose that pointers to fields are aligned to what the compiler can guarantee, which in my example cases of an offset of zero could be higher than the explicitly declared field alignment or the field type’s natural alignment, without @alignCast(...), and that a new builtin akin to a @fieldPtrAlignment(comptime Ptr: type, comptime field_name: []const u8) is added to determine the alignment of a field pointer given its name and the struct/union pointer type.
With this implemented both tests would pass, given that in their specific compilation mode, @fieldPtrAlignment(*align(8) MyStruct, "x") >= 8 and @fieldPtrAlignment(*MyUnion, "a") >= @alignOf(MyUnion) respectively are true.