Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

invalid codegen: implicitly cast a pointer to a const pointer of it #290

Closed
andrewrk opened this issue Mar 31, 2017 · 3 comments
Closed
Labels
bug Observed behavior contradicts documented or intended behavior
Milestone

Comments

@andrewrk
Copy link
Member

andrewrk commented Mar 31, 2017

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

test "implicitly cast a pointer to a const pointer of it" {
    var x: i32 = 1;
    const xp = &x;
    foo(xp);
    assert(x == 2);
}

fn foo(x: &const &i32) {
    **x += 1;
}

Because we allow implicit casting from T to &const T, we expect the parameter to foo to take a const reference of the pointer, however, instead it thinks we should do a pointer reinterpret.

This leaves the question open, however, what should this do?

    var x: i32 = 1;
    const love = (&const &i32)(&x); // what is love?

Is it supposed to do a pointer reinterpret, or does it make a temporary stack variable for &x and then make love point to it?

@andrewrk andrewrk added the bug Observed behavior contradicts documented or intended behavior label Mar 31, 2017
@andrewrk andrewrk added this to the 0.1.0 milestone Mar 31, 2017
@andrewrk
Copy link
Member Author

One solution to this is that we can make pointer reinterpreting a special cast, perhaps with a builtin function.

var x: i32 = 1;
const love = @bitcast(&const &i32, &x); // now it's clear that love is unsafe

@bitcast would be generalized to unsafely transmute any type to any other type, provided the sizes are the same.

@thejoshwolfe
Copy link
Contributor

If we have @bitcast, then we should probably disallow any function-like casting that is generally recognized as unsafe.

const a = u32(i32(-1)); // overflow
const b = @bitcast(u32, i32(-1)); // 0xffffffff
const c = f32(i32(-1)); // -1.0
const d = @bitcast(f32, i32(-1)); // NaN (exponent all 1's, significand non-zero)

const f = f32(1.0);
const g = (&u32)(&f); // error: cannot convert from &f32 to &u32
const h = @bitcast(&u32, &f);
const i = *h; // 0x7f (i think)
const j = (&const f32)(&f); // adding const qualifier is fine.
const k: &const f32 = &f; // adding const qualifier can be implicit.
const fp = &f;
const l = (&const &f32)(fp); // taking const reference is fine.
const m: &const &f32 = fp; // taking const reference can be implicit. 

@andrewrk
Copy link
Member Author

Now that I've gone through and modified all the code to use @bitcast instead of normal casting for pointer reinterpreting, I'm starting to think that @bitcast is too unsafe. You could easily accidentally cast any old thing that wasn't a pointer to a pointer. Plus there are now 2 ways to convert between a usize and a pointer.

So instead I propose that we rename @bitcast to @ptrcast and make it only work when the source and destination types are both &T or both ?&T.

andrewrk added a commit that referenced this issue Mar 31, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior
Projects
None yet
Development

No branches or pull requests

2 participants