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

Tracking issue for const <*const T>::is_null #74939

Open
oli-obk opened this issue Jul 30, 2020 · 6 comments
Open

Tracking issue for const <*const T>::is_null #74939

oli-obk opened this issue Jul 30, 2020 · 6 comments
Labels
A-const-fn Area: const fn foo(..) {..}. Pure functions which can be applied at compile time. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature.

Comments

@oli-obk
Copy link
Contributor

oli-obk commented Jul 30, 2020

This is tracking #[feature(const_ptr_is_null)].

Comparing pointers in const eval is dangerous business.

But checking whether a pointer is the null pointer is actually completely fine, as Rust does not support items being placed at the null address. Any otherwise created null pointers are supposed to return true for is_null anyway, so that's ok. Thus, we implement is_null as ptr.guaranteed_eq(ptr::null()), which returns true if it's guaranteed that ptr is null, and there are no cases where it will return false where it may be null, but we don't know.

@oli-obk oli-obk added A-const-fn Area: const fn foo(..) {..}. Pure functions which can be applied at compile time. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. labels Jul 30, 2020
@RalfJung
Copy link
Member

RalfJung commented Aug 7, 2020

and there are no cases where it will return false where it may be null, but we don't know.

That's not entirely correct. It will at some point be possible to create out-of-bounds raw pointers in const-eval (it might be possible already with enough hacks, I am not sure). Once that is possible, a pointer could be offset enough such that it is NULL at run-time but still non-NULL when checked during CTFE -- we cannot know if out-of-bounds pointers are NULL as that depends on their concrete base address.

@oli-obk
Copy link
Contributor Author

oli-obk commented Aug 10, 2020

So, some examples that we ran reliably check:

  • std::ptr::null::<T>().is_null() will always be true
  • NonZeroUsize::new(x).unwrap().is_null() will always be false
  • `(&x as *const T).is_null() will always be false
  • ((&x as *const T as usize - &x as *const T as usize) as *const T).is_null() will always be true (if you get it or an equivalent to compile)

The problematic case (&x as *const T).offset(496).is_null() will be false, but at runtime could be true. We could set it up so it would be true instead, but then is_null() can return true when at runtime it would return false.

Another alternative is to panic if no exact solution is known (this can be done in a way that it compiles away to nothing at runtime)

Basically the options are:

  • use ptr.guaranteed_eq(std::ptr::null()), but then you get false for out of bounds pointers that at runtime are null
  • use !ptr.guaranteed_ne(std::ptr::null()), but then you get true for all out of bounds pointers, even the ones that are not null at runtime.
  • use both variants and assert that they return the same thing.

bors added a commit to rust-lang-ci/rust that referenced this issue Aug 17, 2020
Make `<*const T>::is_null` const fn

r? @RalfJung

cc @rust-lang/wg-const-eval

tracking issue: rust-lang#74939
@josephlr
Copy link
Contributor

  • use both variants and assert that they return the same thing.

As a user, this seems the most natural to me.

  • Integer pointer that's zero => return true
  • Integer pointer that's non-zero => return false
  • Real pointer that's in-bounds => return false
  • Real pointer that's out-of-bounds => panic, could be either true/false at runtime.

In general, panicking when doing something fundamentally non-const a cosnt fn seems fine.

@kupiakos
Copy link
Contributor

Is there anything blocking stabilization of this? This also blocks NonNull::new from stabilization.

@RalfJung
Copy link
Member

RalfJung commented Mar 22, 2023 via email

@RalfJung
Copy link
Member

RalfJung commented Sep 8, 2024

Given in particular the use of is_null in NonNull::new/ptr::as_ref, I think the only possible interpretation it can have is "might be null": if we allow NonNull::new(ptr.wrapping_sub(0x120000)).unwrap() and later it turns out that pointer is at address 0x120000, we have a problem. Therefore, ptr.wrapping_sub(0x120000).is_null must be true.

Or of course we could panic and thus abort const-eval. We'll never panic at runtime so this may be acceptable.

@rust-lang/wg-const-eval any opinions on this?

workingjubilee added a commit to workingjubilee/rustc that referenced this issue Sep 9, 2024
const: make ptr.is_null() stop execution on ambiguity

This seems better than saying `false` -- saying `false` is in fact actively unsound if `NonNull` then uses this to permit putting this pointer inside of it, but at runtime it turns out to be null.

Part of rust-lang#74939
Cc `@rust-lang/wg-const-eval`
workingjubilee added a commit to workingjubilee/rustc that referenced this issue Sep 9, 2024
const: make ptr.is_null() stop execution on ambiguity

This seems better than saying `false` -- saying `false` is in fact actively unsound if `NonNull` then uses this to permit putting this pointer inside of it, but at runtime it turns out to be null.

Part of rust-lang#74939
Cc ``@rust-lang/wg-const-eval``
workingjubilee added a commit to workingjubilee/rustc that referenced this issue Sep 9, 2024
const: make ptr.is_null() stop execution on ambiguity

This seems better than saying `false` -- saying `false` is in fact actively unsound if `NonNull` then uses this to permit putting this pointer inside of it, but at runtime it turns out to be null.

Part of rust-lang#74939
Cc ```@rust-lang/wg-const-eval```
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Sep 9, 2024
Rollup merge of rust-lang#130107 - RalfJung:const-ptr-is-null, r=oli-obk

const: make ptr.is_null() stop execution on ambiguity

This seems better than saying `false` -- saying `false` is in fact actively unsound if `NonNull` then uses this to permit putting this pointer inside of it, but at runtime it turns out to be null.

Part of rust-lang#74939
Cc ```@rust-lang/wg-const-eval```
workingjubilee added a commit to workingjubilee/rustc that referenced this issue Sep 10, 2024
move some const fn out of the const_ptr_as_ref feature

When a `const fn` is still `#[unstable]`, it should generally use the same feature to track its regular stability and const-stability. Then when that feature moves towards stabilization we can decide whether the const-ness can be stabilized as well, or whether it should be moved into a new feature.

Also, functions like `ptr::as_ref` (which returns an `Option<&mut T>`) require `is_null`, which is tricky and blocked on some design concerns (see rust-lang#74939). So move those to the is_null feature gate, as they should be stabilized together with `ptr.is_null()`.

Affects rust-lang#91822, rust-lang#122034, rust-lang#75402, rust-lang#74939
workingjubilee added a commit to workingjubilee/rustc that referenced this issue Sep 10, 2024
move some const fn out of the const_ptr_as_ref feature

When a `const fn` is still `#[unstable]`, it should generally use the same feature to track its regular stability and const-stability. Then when that feature moves towards stabilization we can decide whether the const-ness can be stabilized as well, or whether it should be moved into a new feature.

Also, functions like `ptr::as_ref` (which returns an `Option<&mut T>`) require `is_null`, which is tricky and blocked on some design concerns (see rust-lang#74939). So move those to the is_null feature gate, as they should be stabilized together with `ptr.is_null()`.

Affects rust-lang#91822, rust-lang#122034, rust-lang#75402, rust-lang#74939
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Sep 10, 2024
Rollup merge of rust-lang#130164 - RalfJung:const_ptr_as_ref, r=dtolnay

move some const fn out of the const_ptr_as_ref feature

When a `const fn` is still `#[unstable]`, it should generally use the same feature to track its regular stability and const-stability. Then when that feature moves towards stabilization we can decide whether the const-ness can be stabilized as well, or whether it should be moved into a new feature.

Also, functions like `ptr::as_ref` (which returns an `Option<&mut T>`) require `is_null`, which is tricky and blocked on some design concerns (see rust-lang#74939). So move those to the is_null feature gate, as they should be stabilized together with `ptr.is_null()`.

Affects rust-lang#91822, rust-lang#122034, rust-lang#75402, rust-lang#74939
github-actions bot pushed a commit to rust-lang/miri that referenced this issue Sep 11, 2024
move some const fn out of the const_ptr_as_ref feature

When a `const fn` is still `#[unstable]`, it should generally use the same feature to track its regular stability and const-stability. Then when that feature moves towards stabilization we can decide whether the const-ness can be stabilized as well, or whether it should be moved into a new feature.

Also, functions like `ptr::as_ref` (which returns an `Option<&mut T>`) require `is_null`, which is tricky and blocked on some design concerns (see #74939). So move those to the is_null feature gate, as they should be stabilized together with `ptr.is_null()`.

Affects #91822, #122034, #75402, rust-lang/rust#74939
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-const-fn Area: const fn foo(..) {..}. Pure functions which can be applied at compile time. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature.
Projects
None yet
Development

No branches or pull requests

4 participants