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

Null fat pointers #66316

Closed
elichai opened this issue Nov 11, 2019 · 6 comments
Closed

Null fat pointers #66316

elichai opened this issue Nov 11, 2019 · 6 comments
Labels
T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@elichai
Copy link
Contributor

elichai commented Nov 11, 2019

Hi,
Currently if you want a null fat pointer you need to do something like this:

ptr::null_mut::<[u8;0]>() as *mut [u8]

which isn't fun and take a while to find.
I see 2 ways of implementing this in libcore:
1:

pub const fn null_mut_fat<T>() -> *mut [T] {
    null_mut::<[T;0]>() as *mut [T] 
}

pub const fn null_fat<T>() -> *const [T] {
    null::<[T;0]>() as *const [T] 
}
  1. (Which I think is better because it doesn't bloat more functions)
pub fn null<T: ?Sized>() -> *mut T {
    unsafe { MaybeUninit::zeroed().assume_init() }
}

The problem is that the second currently isn't possible in a const fn. it requires making both zeroed() and assume_init() const fns, which is physically possible (by making ~4-5 functions const fn, the only problem there is the debug_assert in write_bytes)

But I don't know what's the safety consequences of using intrinsics in const fn.
If it is safe I can start PRing some of these functions to be const fn.

@Mark-Simulacrum Mark-Simulacrum added the T-lang Relevant to the language team, which will review and decide on the PR/issue. label Nov 11, 2019
@cuviper
Copy link
Member

cuviper commented Nov 11, 2019

We have previously decided that Rust's is_null() should only depend on the data pointer -- see the discussions in #44932, #46094, and rust-lang/rfcs#433 (comment). The "fat" part of a pointer is trivial for slices, where a 0 length will do fine, but a trait object pointer always needs to have a valid vtable.

@elichai
Copy link
Contributor Author

elichai commented Nov 11, 2019

@cuviper
Are you telling me that *mut Trait with a null vtable is UB?

But that's a raw pointer. It should only be UB when dereferenced @eddyb

Reading the last url you gave it seems the answer is yes. I find it very hard to reason about, as raw pointers in rust are usually sound no matter what you do unless you dereference

@cuviper
Copy link
Member

cuviper commented Nov 11, 2019

See also rust-lang/unsafe-code-guidelines#166

@elichai
Copy link
Contributor Author

elichai commented Nov 11, 2019

Github should add a facepalm emoji

@ExpHP
Copy link
Contributor

ExpHP commented Nov 12, 2019

There's more than just dereferencing to worry about here. It would appear to me that, by requiring the vtable pointer to be non-null, we enable a niche optimization on Option<NonNull<dyn Trait>>.

Edit: or wait, does it? I'm perhaps too tired to reason about it right now....

@Mark-Simulacrum
Copy link
Member

I am closing this in favor of the UCG issue (rust-lang/unsafe-code-guidelines#166). I don't think we're in a position to decide these things on rust-lang/rust issues; the UCG process for now is the best way to provide feedback on these issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
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

4 participants