Skip to content

remove the destination type parameter from all cast builtins #5909

@andrewrk

Description

@andrewrk

@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`
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    acceptedThis proposal is planned.breakingImplementing this issue could cause existing code to no longer compile or have different behavior.proposalThis issue suggests modifications. If it also has the "accepted" label then it is planned.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions