Dereferencing untyped raw pointer


#1

Why does dereferencing a typed raw pointer requires an unsafe block

fn main() {
    let raw_p: *const i32 = &10;
    assert!(*raw_p == 10);
}
[Output]
main.rs:3:13: 3:19 error: dereference of unsafe pointer requires unsafe function or block [E0133]
main.rs:3     assert!(*raw_p == 10);
                      ^~~~~~
<std macros>:1:1: 5:46 note: in expansion of assert!
main.rs:3:5: 3:27 note: expansion site
error: aborting due to previous error

while dereferencing an untyped raw pointer doesn’t?

fn main() {
    let raw_p = &10;
    assert!(*raw_p == 10);
}

#2

&10 gives you a safe pointer (reference) &i32, not raw pointer *const i32 . I.e. the second example is equivalent to

fn main() {
    let raw_p: &i32 = &10;
    assert!(*raw_p == 10);
}

At the same time &i32 is implicitly convertible to *const i32, so let raw_p: *const i32 = &10; compiles too, but &10 is converted to *const i32.


#3

Ok, thank you. I was getting confused because in gdb I had seen (i32 *) as the type for raw_p in the example:

fn main() {
    let raw_p = &10;
    assert!(*raw_p == 10);
}
(gdb) ptype raw_p
type = i32 *

#4

At runtime, there is no difference between a reference and a pointer, AIUI.

Types in general in most compiled native languages are a wholly compile time concept.


#5

Yes, at runtime there are only addresses and data. But I guess that the debugging data contains some information about the data types. At least with C++ I get the following gdb output:

#include <iostream>

int main()
{
  int* p = new int;

  int& r = *p; 

  std::cout << "p: " << p << std::endl;
  std::cout << "r: " << r << std::endl;
}
(gdb) ptype p
type = int *
(gdb) ptype r
type = int &

#6

That will probably change in the future, but currently gdb doesn’t know anything about Rust.