-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Description
This is a proposal to have the ~ operator propagate its result type to its operand.
My main motivation for proposing this is the following footgun:
const MyStruct = struct {
x: u32,
};
// somewhere far away
const foo: MyStruct = .{ .x = ~@as(u32, 0) };
std.debug.assert(~foo.x == 0);If the type of the x field is changed to u64, the assert will begin failing. In many cases, there is no such assert, and instead the code silently breaks in ways that may be difficult to detect.
Currently, to reliably get the desired behaviour, one must write code like this:
const foo: MyStruct = .{ .x = ~@as(@FieldType(MyStruct, "x"), 0) };Which is pretty difficult to read. With the proposed change, the snippet could be written like this instead:
const foo: MyStruct = .{ .x = ~0 };Breaking
This is unfortunately a breaking change, as illustrated by this example:
const x: u8 = 0;
const y: u16 = ~x;
// prior to this change, y == 0x00ff
// after this change, y == 0xffffI personally think both of these behaviours are equally confusing, but at least with the proposed change you have all the type information you need in one place, and don't have to go look at the type of x.