From 507583a40c4bc99630488d0b155b4f1aa721fd0b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 16 Feb 2024 21:22:47 +0100 Subject: [PATCH] align_offset, align_to: no longer allow implementations to spuriously fail to align --- library/core/src/ptr/const_ptr.rs | 13 ++++++++++--- library/core/src/ptr/mut_ptr.rs | 13 ++++++++++--- library/core/src/slice/mod.rs | 14 ++++---------- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index c5e3df07a1cf7..3400d362ea11e 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -1322,9 +1322,7 @@ impl *const T { /// `align`. /// /// If it is not possible to align the pointer, the implementation returns - /// `usize::MAX`. It is permissible for the implementation to *always* - /// return `usize::MAX`. Only your algorithm's performance can depend - /// on getting a usable offset here, not its correctness. + /// `usize::MAX`. /// /// The offset is expressed in number of `T` elements, and not bytes. The value returned can be /// used with the `wrapping_add` method. @@ -1333,6 +1331,15 @@ impl *const T { /// beyond the allocation that the pointer points into. It is up to the caller to ensure that /// the returned offset is correct in all terms other than alignment. /// + /// When this is called during compile-time evaluation (which is unstable), the implementation + /// may return `usize::MAX` in cases where that can never happen at runtime. This is because the + /// actual alignment of pointers is not known yet during compile-time, so an offset with + /// guaranteed alignment can sometimes not be computed. For example, a buffer declared as `[u8; + /// N]` might be allocated at an odd or an even address, but at compile-time this is not yet + /// known, so the execution has to be correct for either choice. It is therefore impossible to + /// find an offset that is guaranteed to be 2-aligned. (This behavior is subject to change, as usual + /// for unstable APIs.) + /// /// # Panics /// /// The function panics if `align` is not a power-of-two. diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 376673d67c10b..8df663b4f30ef 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1585,9 +1585,7 @@ impl *mut T { /// `align`. /// /// If it is not possible to align the pointer, the implementation returns - /// `usize::MAX`. It is permissible for the implementation to *always* - /// return `usize::MAX`. Only your algorithm's performance can depend - /// on getting a usable offset here, not its correctness. + /// `usize::MAX`. /// /// The offset is expressed in number of `T` elements, and not bytes. The value returned can be /// used with the `wrapping_add` method. @@ -1596,6 +1594,15 @@ impl *mut T { /// beyond the allocation that the pointer points into. It is up to the caller to ensure that /// the returned offset is correct in all terms other than alignment. /// + /// When this is called during compile-time evaluation (which is unstable), the implementation + /// may return `usize::MAX` in cases where that can never happen at runtime. This is because the + /// actual alignment of pointers is not known yet during compile-time, so an offset with + /// guaranteed alignment can sometimes not be computed. For example, a buffer declared as `[u8; + /// N]` might be allocated at an odd or an even address, but at compile-time this is not yet + /// known, so the execution has to be correct for either choice. It is therefore impossible to + /// find an offset that is guaranteed to be 2-aligned. (This behavior is subject to change, as usual + /// for unstable APIs.) + /// /// # Panics /// /// The function panics if `align` is not a power-of-two. diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 1d8ac6aa04394..c72ab6ec47060 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -3756,11 +3756,8 @@ impl [T] { /// maintained. /// /// This method splits the slice into three distinct slices: prefix, correctly aligned middle - /// slice of a new type, and the suffix slice. How exactly the slice is split up is not - /// specified; the middle part may be smaller than necessary. However, if this fails to return a - /// maximal middle part, that is because code is running in a context where performance does not - /// matter, such as a sanitizer attempting to find alignment bugs. Regular code running - /// in a default (debug or release) execution *will* return a maximal middle part. + /// slice of a new type, and the suffix slice. The middle part will be as big as possible under + /// the given alignment constraint and element size. /// /// This method has no purpose when either input element `T` or output element `U` are /// zero-sized and will return the original slice without splitting anything. @@ -3824,11 +3821,8 @@ impl [T] { /// types is maintained. /// /// This method splits the slice into three distinct slices: prefix, correctly aligned middle - /// slice of a new type, and the suffix slice. How exactly the slice is split up is not - /// specified; the middle part may be smaller than necessary. However, if this fails to return a - /// maximal middle part, that is because code is running in a context where performance does not - /// matter, such as a sanitizer attempting to find alignment bugs. Regular code running - /// in a default (debug or release) execution *will* return a maximal middle part. + /// slice of a new type, and the suffix slice. The middle part will be as big as possible under + /// the given alignment constraint and element size. /// /// This method has no purpose when either input element `T` or output element `U` are /// zero-sized and will return the original slice without splitting anything.