-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
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`
}