Use some more const_eval_select in pointer methods for compile times

This commit is contained in:
Nilstrieb 2022-12-29 23:01:31 +01:00
parent 0c0b403f19
commit a8f50453d0
2 changed files with 66 additions and 22 deletions

View file

@ -1,6 +1,6 @@
use super::*; use super::*;
use crate::cmp::Ordering::{self, Equal, Greater, Less}; use crate::cmp::Ordering::{self, Equal, Greater, Less};
use crate::intrinsics; use crate::intrinsics::{self, const_eval_select};
use crate::mem; use crate::mem;
use crate::slice::{self, SliceIndex}; use crate::slice::{self, SliceIndex};
@ -34,14 +34,25 @@ impl<T: ?Sized> *const T {
#[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")]
#[inline] #[inline]
pub const fn is_null(self) -> bool { pub const fn is_null(self) -> bool {
#[inline]
fn runtime_impl(ptr: *const u8) -> bool {
ptr.addr() == 0
}
#[inline]
const fn const_impl(ptr: *const u8) -> bool {
// Compare via a cast to a thin pointer, so fat pointers are only // Compare via a cast to a thin pointer, so fat pointers are only
// considering their "data" part for null-ness. // considering their "data" part for null-ness.
match (self as *const u8).guaranteed_eq(null()) { match (ptr).guaranteed_eq(null_mut()) {
None => false, None => false,
Some(res) => res, Some(res) => res,
} }
} }
// SAFETY: The two versions are equivalent at runtime.
unsafe { const_eval_select((self as *const u8,), const_impl, runtime_impl) }
}
/// Casts to a pointer of another type. /// Casts to a pointer of another type.
#[stable(feature = "ptr_cast", since = "1.38.0")] #[stable(feature = "ptr_cast", since = "1.38.0")]
#[rustc_const_stable(feature = "const_ptr_cast", since = "1.38.0")] #[rustc_const_stable(feature = "const_ptr_cast", since = "1.38.0")]
@ -1587,11 +1598,22 @@ impl<T: ?Sized> *const T {
panic!("is_aligned_to: align is not a power-of-two"); panic!("is_aligned_to: align is not a power-of-two");
} }
#[inline]
fn runtime_impl(ptr: *const (), align: usize) -> bool {
ptr.addr() & (align - 1) == 0
}
#[inline]
const fn const_impl(ptr: *const (), align: usize) -> bool {
// We can't use the address of `self` in a `const fn`, so we use `align_offset` instead. // We can't use the address of `self` in a `const fn`, so we use `align_offset` instead.
// The cast to `()` is used to // The cast to `()` is used to
// 1. deal with fat pointers; and // 1. deal with fat pointers; and
// 2. ensure that `align_offset` doesn't actually try to compute an offset. // 2. ensure that `align_offset` doesn't actually try to compute an offset.
self.cast::<()>().align_offset(align) == 0 ptr.align_offset(align) == 0
}
// SAFETY: The two versions are equivalent at runtime.
unsafe { const_eval_select((self.cast::<()>(), align), const_impl, runtime_impl) }
} }
} }

View file

@ -1,6 +1,6 @@
use super::*; use super::*;
use crate::cmp::Ordering::{self, Equal, Greater, Less}; use crate::cmp::Ordering::{self, Equal, Greater, Less};
use crate::intrinsics; use crate::intrinsics::{self, const_eval_select};
use crate::slice::{self, SliceIndex}; use crate::slice::{self, SliceIndex};
impl<T: ?Sized> *mut T { impl<T: ?Sized> *mut T {
@ -33,14 +33,25 @@ impl<T: ?Sized> *mut T {
#[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")]
#[inline] #[inline]
pub const fn is_null(self) -> bool { pub const fn is_null(self) -> bool {
#[inline]
fn runtime_impl(ptr: *mut u8) -> bool {
ptr.addr() == 0
}
#[inline]
const fn const_impl(ptr: *mut u8) -> bool {
// Compare via a cast to a thin pointer, so fat pointers are only // Compare via a cast to a thin pointer, so fat pointers are only
// considering their "data" part for null-ness. // considering their "data" part for null-ness.
match (self as *mut u8).guaranteed_eq(null_mut()) { match (ptr).guaranteed_eq(null_mut()) {
None => false, None => false,
Some(res) => res, Some(res) => res,
} }
} }
// SAFETY: The two versions are equivalent at runtime.
unsafe { const_eval_select((self as *mut u8,), const_impl, runtime_impl) }
}
/// Casts to a pointer of another type. /// Casts to a pointer of another type.
#[stable(feature = "ptr_cast", since = "1.38.0")] #[stable(feature = "ptr_cast", since = "1.38.0")]
#[rustc_const_stable(feature = "const_ptr_cast", since = "1.38.0")] #[rustc_const_stable(feature = "const_ptr_cast", since = "1.38.0")]
@ -1859,11 +1870,22 @@ impl<T: ?Sized> *mut T {
panic!("is_aligned_to: align is not a power-of-two"); panic!("is_aligned_to: align is not a power-of-two");
} }
#[inline]
fn runtime_impl(ptr: *mut (), align: usize) -> bool {
ptr.addr() & (align - 1) == 0
}
#[inline]
const fn const_impl(ptr: *mut (), align: usize) -> bool {
// We can't use the address of `self` in a `const fn`, so we use `align_offset` instead. // We can't use the address of `self` in a `const fn`, so we use `align_offset` instead.
// The cast to `()` is used to // The cast to `()` is used to
// 1. deal with fat pointers; and // 1. deal with fat pointers; and
// 2. ensure that `align_offset` doesn't actually try to compute an offset. // 2. ensure that `align_offset` doesn't actually try to compute an offset.
self.cast::<()>().align_offset(align) == 0 ptr.align_offset(align) == 0
}
// SAFETY: The two versions are equivalent at runtime.
unsafe { const_eval_select((self.cast::<()>(), align), const_impl, runtime_impl) }
} }
} }