J. Doe
J. Doe

Reputation: 135

Why is casting a const reference directly to a mutable reference invalid in Rust?

This piece of code is correct:

fn f() {
    let mut x = 11;
    b(&x as *const u8 as *mut u8);
}

fn b(x: *mut u8) {}

Why is b(&x as *const u8 as *mut u8) is valid whereas b(&x as *mut u8) is invalid? The compiler complains about:

error[E0606]: casting &u8 as *mut u8 is invalid

Upvotes: 5

Views: 4988

Answers (2)

EduBic
EduBic

Reputation: 357

Because a rust reference is constant.

What you want to do is to cast a mutable reference &mut x to a raw integer mutable pointer *mut i32.

This code is valid:

let mut x = 42;
let ptr = &mut x as *mut _;
// equivalent to
let ptr_2 = &x as *const _ as *mut _;

Upvotes: 0

Sven Marnach
Sven Marnach

Reputation: 602355

The superficial answer to the question "why?" is that these simply are the rules of as expressions in Rust. Quoting from the Nomicon:

Casting is not transitive, that is, even if e as U1 as U2 is a valid expression, e as U2 is not necessarily so.

With the as operator, you can either perform explicit coercions or casts.

There is neither a cast nor a coercion to go directly from &u8 to *mut u8. However, there is a pointer weakening coercion from &T to *const T and a cast from a pointer to a sized type to any other. The combination of the two results in the expression in your question.

The deeper question is why the language was designed this way. I don't actually know, since I wasn't in the room when these decisions were made, and I couldn't find a rationale on the web. Rust in general tries to be very explicit with type casts, to avoid conversions that weren't actually intended and to keep the rules simple. These princilpes seem to have influenced this particular design decision as well.

Upvotes: 10

Related Questions