-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
@as
is unchanged. These are affected:
@floatCast
@intCast
@alignCast
@bitCast
@errSetCast
@ptrCast
@truncate
The motivation here is to prevent bugs. Here's an example case:
const Data = struct {
bits: u8,
};
fn updateBits(data: *Data) void {
// ...
const y: usize = indexOfSomethingGuaranteedToFitInBits();
data.bits = @intCast(u8, y);
// ...
}
Here, we obtain y
, a usize
but for whatever reason is guaranteed to fit into the bits
field of Data
. So we use @intCast
here to cast it.
Now, we rework the code, and actually we need to add some more bits, making it a u16
:
const Data = struct {
bits: u16,
};
fn updateBits(data: *Data) void {
// ...
const y: usize = indexOfSomethingGuaranteedToFitInBits();
data.bits = @intCast(u8, y);
// ...
}
We've now introduced a bug into the code. The bits
field is updated, but the @intCast
is still casting too small. The lack of type inference here has actually made the code buggier.
The original code theoretically should have used data.bits = @intCast(@TypeOf(data.bits), y)
however this is so cumbersome that it's rarely done in practice, especially when data.bits
is a more complicated expression.
With this proposal, the original code would look like this:
const Data = struct {
bits: u8,
};
fn updateBits(data: *Data) void {
// ...
const y: usize = indexOfSomethingGuaranteedToFitInBits();
data.bits = @intCast(y);
// ...
}
And the updated code (which only changes the type of the bits
field to u16
) remains correct.
With this proposal, it is still possible to get the older semantics:
const Data = struct {
bits: u8,
};
fn updateBits(data: *Data) void {
// ...
const y: usize = indexOfSomethingGuaranteedToFitInBits();
data.bits = @as(u8, @intCast(y));
// ...
}
A cast operation with an inferred result location type would be a compile error:
test "example" {
var y: i32 = 1;
const x = @intCast(y); // error: unable to infer result type \n hint: coerce the result using `@as`
}