Why is @constCast a one-directional function?

Why isn’t it bi-directional?

const print = @import("std").debug.print;

pub fn main() void {
    var v: usize = 123;
    const x = &v;
    print("{}\n", .{ @TypeOf(x) });// *usize
    const y = @constCast(x);
    print("{}\n", .{ @TypeOf(y) });// *usize
    
    const z: *const usize = y;
    print("{}\n", .{ @TypeOf(z) });// *const usize
    const w = @constCast(z);
    print("{}\n", .{ @TypeOf(w) });// *usize
}

Because pointers-to-var coerce to pointers-to-const without any checks or manipulation. It’s always safe and always a no-op. There’s no need for a builtin.

4 Likes

what do you mean bi-directional? if you mean var -> const then the builtin should be named @constToggle()

because

var v: usize = 123;
const x = &v; // *usize
// it coerces
const y: *const usize = x; // just works
6 Likes

I was writing your exact snippet, but then realized he already used it for z

3 Likes

When I first time saw the @constCast function, I thought it will add the const modifier. :smiley:

Maybe @constToggle can be used in some generic functions. (I have not found any practical use cases though.)

1 Like

yeah, makes sense

Should’ve been named @varCast :wink:

2 Likes

been reminded of this

still not sure why you’d need it, but you can implement this with reflection and reification

fn constToggle(ptr: anytype) ConstToggle(@TypeOf(ptr)) {
    return if (@typeInfo(@TypeOf(ptr)).pointer.is_const) @constCast(ptr) else ptr;
}

fn ConstToggle(Ptr: type) type {
    const info = @typeInfo(Ptr).pointer;
    return @Pointer(info.size, .{
        .@"const" = !info.is_const,
        .@"volatile" = info.is_volatile,
        .@"addrspace" = info.address_space,
        .@"align" = info.alignment,
        .@"allowzero" = info.is_allowzero,
    }, info.child, info.sentinel());
}

much nicer on master(0.17) where type info has the same layout as new reify builtins.

1 Like