Why is transmuting raw pointers considered safe?

I don't understand what you're saying - this doesn't appear to answer my question.

But it does - safe code has no business going anywhere near raw pointers.

How would you pass in an arbitrary raw pointer, given the rules above?

That's a bold statement. Nothing about raw pointers in and of themselves is unsafe. You have not shown otherwise. There are absolutely valid purposes for using raw pointers without dereferencing them.

And there are good reasons for having references become raw pointers, and have a safe API that takes raw pointers. (namely the stuff with LLVM and stuff)

Raw pointers are still pointers and should be treated as such.

Are you saying that the fact that unsafe is required to construct a raw pointer means that the code dereferencing a raw pointer can somehow rely on the pointer being safe to dereference?

Consider this code:

fn main() {
    let my_ptr: *const bool;
    {
        let my_bool = true;
        my_ptr = unsafe { &my_bool as *const bool };
    }
    deref_ptr(my_ptr);
}

Under your rules, is that usage of an unsafe block correct?

Not if you want to dereference them. You have no idea what is behind that pointer.

I will ask for the third time, what is unsafe about possessing a raw pointer? You have provided no situation whatsoever where possession, in and of itself, is unsafe. Stop going in circles and address the concerns we are bringing up.

6 Likes

Nope. You'd need to wrap the my_ptr = around the unsafe{} as well (since returning a raw pointer is also unsafe). You'd need the deref_ptr to be wrapped around unsafe {} (because you're reading my_ptr into the call).

This is to say: *const T should be a way to disable/opt-out of optimizations that would apply on an &T, so that unsafe code can be sound.

As I asked before - if a function that dereferences a raw pointer still needs to be unsafe, then what is accomplished by making it unsafe to construct a raw pointer?

The function wouldn't be unsafe. It's the my_ptr that makes it unsafe, not the deref_ptr().

deref_ptr(&"foo") would be 100% safe.

So when you say 'reading my pointer into the call', you mean any use of the my_ptr variable, regardless of whether or not it's a dereference?

Exactly. It also means &*const Foo is sound to pass around (but not create) without the need of unsafe {}. (can't use it for anything without unsafe {} tho, but that unsafe {} can be behind a safe function.)

The only caveat is that there would have to be an ?Safe bound you can put on generics, to allow raw pointers. Maybe.

I will ask for one final time, since you seem set on ignoring my previous requests. Where is the unsafety in this snippet?

fn main() {
    let x = 0;
    let y = 0;

    let ptr_x = &x as *const _ as usize;
    let ptr_y = &y as *const _ as usize;

    println!("{}", ptr_y - ptr_x);
}

Playground

If you can't answer this simple question, I really don't know what you're trying to gain here. Making APIs simpler is not a reason to require marking things unsafe that aren't.

3 Likes

There is no unsoundness there, but it should require the use of a safe wrapper, something like an (safe!) std::ptr::as_usize() that takes a raw pointer and returns an usize and can thus be called safely with the use of a reference.

Otherwise, by that logic malloc is safe.

This code works today. I'm not asking about how this could be implemented some other way. I am asking why you want to require the placing of unsafe blocks on the exact code that I provided.

Will you acknowledge that there is no unsafety in the block I've provided?

1 Like

Then unsafe should not be required - the entire purpose of the unsafe keyword assert that you've checked that a piece of code cannot produce undefined behavior.

There is no unsafety in calling malloc. There is no unsoundness in calling malloc. And yet libc still marks it as unsafe.

Yes, malloc is in fact safe (except for issues with passing in a size of 0). Look at the docs for GlobalAlloc::alloc - the only reason that is unsafe is because of the possibility of passing in a zero-sized Layout