Skip to content

rustc considers casting to violate lifetime analysis #19716

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

Closed
stouset opened this issue Dec 11, 2014 · 4 comments
Closed

rustc considers casting to violate lifetime analysis #19716

stouset opened this issue Dec 11, 2014 · 4 comments
Labels
A-type-system Area: Type system T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@stouset
Copy link

stouset commented Dec 11, 2014

extern crate alloc;
extern crate libc;

fn main() {
    let ptr = alloc::heap::EMPTY as *const libc::c_void;

    let ptrref1 : &*const libc::c_void;
    let ptrref2 : &*const u8;

    {
        ptrref1 = &ptr;
        ptrref2 = &(ptr as *const u8);
    }
}

In this case, ptrref1 is able to be assigned to a ref of the pointer. However, ptrref2 cannot because of the cast. It appears the only way to work around this currently is with transmute:

ptrref2 : &*const u8 = std::mem::transmute(&ptr);

Try it yourself.

$ rustc --version=verbose
rustc 0.13.0-nightly (8bca470c5 2014-12-08 00:12:30 +0000)
binary: rustc
commit-hash: 8bca470c5acf13aa20022a2c462a89f72de721fc
commit-date: 2014-12-08 00:12:30 +0000
host: x86_64-apple-darwin
release: 0.13.0-nightly
@bkoropoff
Copy link
Contributor

The result of a cast expression is an rvalue, and taking a reference to an rvalue is roughly equivalent to hoisting the result to a temporary variable that is only in scope for that statement and taking a reference to it. This makes the inner code block something akin to:

    {
        ptrref1 = &ptr;
        ptrref2 = { let tmp = ptr; &tmp as *const u8 };
    }

Since tmp goes out of scope at the end of the inner block, this would produce a dangling reference, so rustc is correct to reject it.

@stouset
Copy link
Author

stouset commented Dec 12, 2014

That it is the current behavior is distinct issue from whether or not it is desired behavior. It seems like there ought to be an easier way to perform a cast on something you need a reference to than transmuting it.

It would be a different story if I could just directly cast the reference itself:

ptrref2 = &ptr as &*const u8;

@kmcallister kmcallister added the A-type-system Area: Type system label Jan 17, 2015
@huonw huonw added the T-lang Relevant to the language team, which will review and decide on the PR/issue. label Sep 29, 2015
@huonw
Copy link
Member

huonw commented Sep 29, 2015

In general a cast has to be an r-value, since it can change the in-memory representation of a value (1_u8 as f32) and the only correct way for a cast to be an l-value with the same lifetime as what is being cast (X) is if it has exactly the same bit pattern, so the location of X can be used as the address of the result of the cast.

I suspect we don't want to have the l-value-ness of a cast expression depend on the types being cast, but others on the @rust-lang/lang team may think it is OK.

@nikomatsakis
Copy link
Contributor

I like the current behavior. It doesn't seem like casting the type of a variable and getting a direct reference to it in one action is so common, nor is transmute so inappropriate. In general, taking a reference to something and then changing the type of that something is pretty risky, since it can easily cause us to load or store values of the wrong size, or lead to variance problems, etc. I'm going to close this issue -- if you'd care to re-open, I'd suggest re-opening on the RFC repo, since I think that this sort of language change requires an RFC in any case. Thanks.

lnicola pushed a commit to lnicola/rust that referenced this issue May 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-type-system Area: Type system T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants