Repository navigation
Tracking issue for const <*const T>::is_null #74939
Copy link
Copy link
Closed
Labels
A-const-evalArea: Constant evaluation, covers all const contexts (static, const fn, ...)Area: Constant evaluation, covers all const contexts (static, const fn, ...)C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFCT-langRelevant to the language teamRelevant to the language teamT-libs-api[DEPRECATED; DO NOT USE][DEPRECATED; DO NOT USE]disposition-mergeThis issue / PR is in PFCP or FCP with a disposition to merge it.This issue / PR is in PFCP or FCP with a disposition to merge it.finished-final-comment-periodThe final comment period is finished for this PR / Issue.The final comment period is finished for this PR / Issue.
Description
This is tracking #[feature(const_ptr_is_null)].
impl<T: ?Sized> *const T {
pub const unsafe fn as_ref<'a>(self) -> Option<&'a T>;
pub const fn is_null(&self) -> bool;
}
impl<T: ?Sized> *mut T {
pub const unsafe fn as_mut<'a>(self) -> Option<&'a mut T>;
pub const unsafe fn as_ref<'a>(self) -> Option<&'a T>;
pub const fn is_null(&self) -> bool;
}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.
Reacted by Eric Shimizu Karbstein
Metadata
Metadata
Assignees
Labels
A-const-evalArea: Constant evaluation, covers all const contexts (static, const fn, ...)Area: Constant evaluation, covers all const contexts (static, const fn, ...)C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFCT-langRelevant to the language teamRelevant to the language teamT-libs-api[DEPRECATED; DO NOT USE][DEPRECATED; DO NOT USE]disposition-mergeThis issue / PR is in PFCP or FCP with a disposition to merge it.This issue / PR is in PFCP or FCP with a disposition to merge it.finished-final-comment-periodThe final comment period is finished for this PR / Issue.The final comment period is finished for this PR / Issue.
Activity
RalfJung commentedon Aug 7, 2020
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 commentedon Aug 10, 2020
So, some examples that we ran reliably check:
std::ptr::null::<T>().is_null()will always be trueNonZeroUsize::new(x).unwrap().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).wrapping_offset(496).is_null()will befalse, but at runtime could betrue. We could set it up so it would betrueinstead, but thenis_null()can returntruewhen at runtime it would returnfalse.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:
ptr.guaranteed_eq(std::ptr::null()), but then you getfalsefor out of bounds pointers that at runtime are null!ptr.guaranteed_ne(std::ptr::null()), but then you gettruefor all out of bounds pointers, even the ones that are not null at runtime.josephlr commentedon Sep 13, 2020
As a user, this seems the most natural to me.
truefalsefalsetrue/falseat runtime.In general, panicking when doing something fundamentally non-const a
cosnt fnseems fine.kupiakos commentedon Mar 21, 2023
Is there anything blocking stabilization of this? This also blocks
NonNull::newfrom stabilization.RalfJung commentedon Mar 22, 2023
RalfJung commentedon Sep 8, 2024
Given in particular the use of
is_nullinNonNull::new/ptr::as_ref, I think the only possible interpretation it can have is "might be null": if we allowNonNull::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_nullmust betrue.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?
Rollup merge of rust-lang#130107 - RalfJung:const-ptr-is-null, r=oli-obk
Rollup merge of rust-lang#130107 - RalfJung:const-ptr-is-null, r=oli-obk
Rollup merge of rust-lang#130107 - RalfJung:const-ptr-is-null, r=oli-obk
Unrolled build for rust-lang#130107
Rollup merge of rust-lang#130164 - RalfJung:const_ptr_as_ref, r=dtolnay
52 remaining items
Correctly document is_null CTFE behavior.
Correctly document is_null CTFE behavior.
Correctly document is_null CTFE behavior.
Correctly document is_null CTFE behavior.
Correctly document is_null CTFE behavior.
Correctly document is_null CTFE behavior.
Correctly document is_null CTFE behavior.
Correctly document is_null CTFE behavior.
Correctly document is_null CTFE behavior.
Correctly document is_null CTFE behavior.
Correctly document is_null CTFE behavior.
Correctly document is_null CTFE behavior.
Correctly document is_null CTFE behavior.
Correctly document is_null CTFE behavior.
Rollup merge of rust-lang#134325 - theemathas:is_null-docs, r=RalfJung