Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow @bitCast to pass through lvalues #21935

Open
silversquirl opened this issue Nov 8, 2024 · 3 comments
Open

Allow @bitCast to pass through lvalues #21935

silversquirl opened this issue Nov 8, 2024 · 3 comments
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@silversquirl
Copy link
Contributor

Since @bitCast never changes memory layout, it should be possible for it to be an lvalue when its parameter is one. For example:

var x: u32 = 42;
const y: *i32 = &@bitCast(x);
y.* = -1;

Resulting in x == 0xffff_ffff

The advantage of this over just using @ptrCast is that @bitCast checks the parameter type and target type have equal size, as well as that they have defined memory layout (eg. no auto-layout structs).

This change could also be applied to @intFromEnum and @enumFromInt, which are effectively @bitCast in disguise.

@mlugg mlugg added the proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. label Nov 8, 2024
@mlugg mlugg added this to the 0.15.0 milestone Nov 8, 2024
@mlugg
Copy link
Member

mlugg commented Nov 8, 2024

Implementation-wise, this would be relatively straightforward; in AstGen we'd handle the ri.rl == .ref_coerced_ty case with a new ZIR instruction, which just does the normal bitcast (/@intFromEnum/@enumFromInt etc) type checks and otherwise behaves like a ptrcast.

Note also that @field is an example of a builtin which sets a precedent for this kind of lvalue-passthrough behavior in builtins.

@xdBronch
Copy link
Contributor

xdBronch commented Nov 8, 2024

i really like this proposal and what it would allow but it doesnt feel intuitive to me. with the & being outside of the @bitCast what i think when i see it is "bit cast to a temporary and take the address of it" which is the current behavior of these casts, though maybe im somewhat biased since this is just what im used to it doing. if this change happened would the behavior of e.g. const y: *i32 = &@intCast(x); change? i cant think of a reasonable way for it to change to match this but i also dont like the inconsistency

@silversquirl
Copy link
Contributor Author

@xdBronch There is precedent for this sort of lvalue passthrough already, for example this works:

var x: u32 = 1;
var y: u32 = 0;
const z = &if (x > y) x else y;
z.* = 3;
std.debug.print("{} {}\n", .{ x, y }); // -> 3 0

&@intCast(x) would not work in the general case because @intCast can change the memory layout of a value. It could potentially work if the bit size of the target and source integer are the same, however.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Projects
None yet
Development

No branches or pull requests

3 participants