From 6f6320a0a916b57dc37568d3ce5f5ed0e749ef61 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Fri, 7 Oct 2022 22:24:31 +0200 Subject: [PATCH] constify `pointer::is_aligned{,_to}` --- library/core/src/lib.rs | 1 + library/core/src/ptr/const_ptr.rs | 25 +++++++++++++++++++------ library/core/src/ptr/mut_ptr.rs | 25 +++++++++++++++++++------ 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 33b969c249a..848eccd7f29 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -130,6 +130,7 @@ #![feature(const_option)] #![feature(const_option_ext)] #![feature(const_pin)] +#![feature(const_pointer_is_aligned)] #![feature(const_ptr_sub_ptr)] #![feature(const_replace)] #![feature(const_result_drop)] diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index f0cdc3d8399..8b96cf06be4 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -1363,10 +1363,13 @@ const fn ctfe_impl(_: *const T, _: usize) -> usize { } /// Returns whether the pointer is properly aligned for `T`. + // #[cfg(not(bootstrap))] -- Calling this function in a const context from the bootstrap + // compiler will always return false. #[must_use] #[inline] #[unstable(feature = "pointer_is_aligned", issue = "96284")] - pub fn is_aligned(self) -> bool + #[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "none")] + pub const fn is_aligned(self) -> bool where T: Sized, { @@ -1381,16 +1384,26 @@ pub fn is_aligned(self) -> bool /// # Panics /// /// The function panics if `align` is not a power-of-two (this includes 0). + // #[cfg(not(bootstrap))] -- Calling this function in a const context from the bootstrap + // compiler will always return false. #[must_use] #[inline] #[unstable(feature = "pointer_is_aligned", issue = "96284")] - pub fn is_aligned_to(self, align: usize) -> bool { - if !align.is_power_of_two() { - panic!("is_aligned_to: align is not a power-of-two"); + #[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "none")] + pub const fn is_aligned_to(self, align: usize) -> bool { + assert!(align.is_power_of_two(), "is_aligned_to: align is not a power-of-two"); + + #[inline] + fn runtime(ptr: *const u8, align: usize) -> bool { + ptr.addr() & (align - 1) == 0 } - // Cast is needed for `T: !Sized` - self.cast::().addr() & align - 1 == 0 + const fn comptime(ptr: *const u8, align: usize) -> bool { + ptr.align_offset(align) == 0 + } + + // SAFETY: `ptr.align_offset(align)` returns 0 if and only if the pointer is already aligned. + unsafe { intrinsics::const_eval_select((self.cast::(), align), comptime, runtime) } } } diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index eb1a6a07c6b..2d73c24b5b4 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1631,10 +1631,13 @@ const fn ctfe_impl(_: *mut T, _: usize) -> usize { } /// Returns whether the pointer is properly aligned for `T`. + // #[cfg(not(bootstrap))] -- Calling this function in a const context from the bootstrap + // compiler will always return false. #[must_use] #[inline] #[unstable(feature = "pointer_is_aligned", issue = "96284")] - pub fn is_aligned(self) -> bool + #[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "none")] + pub const fn is_aligned(self) -> bool where T: Sized, { @@ -1649,16 +1652,26 @@ pub fn is_aligned(self) -> bool /// # Panics /// /// The function panics if `align` is not a power-of-two (this includes 0). + // #[cfg(not(bootstrap))] -- Calling this function in a const context from the bootstrap + // compiler will always return false. #[must_use] #[inline] #[unstable(feature = "pointer_is_aligned", issue = "96284")] - pub fn is_aligned_to(self, align: usize) -> bool { - if !align.is_power_of_two() { - panic!("is_aligned_to: align is not a power-of-two"); + #[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "none")] + pub const fn is_aligned_to(self, align: usize) -> bool { + assert!(align.is_power_of_two(), "is_aligned_to: align is not a power-of-two"); + + #[inline] + fn runtime(ptr: *mut u8, align: usize) -> bool { + ptr.addr() & (align - 1) == 0 } - // Cast is needed for `T: !Sized` - self.cast::().addr() & align - 1 == 0 + const fn comptime(ptr: *mut u8, align: usize) -> bool { + ptr.align_offset(align) == 0 + } + + // SAFETY: `ptr.align_offset(align)` returns 0 if and only if the pointer is already aligned. + unsafe { intrinsics::const_eval_select((self.cast::(), align), comptime, runtime) } } }